Skip to content

Commit 5133c29

Browse files
authored
Merge pull request #34580 from software-mansion-labs/ts/ShareCodePage
2 parents 50d81ef + c08f4b6 commit 5133c29

7 files changed

+147
-178
lines changed

src/components/MenuItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ type NoIcon = {
5757

5858
type MenuItemProps = (IconProps | AvatarProps | NoIcon) & {
5959
/** Function to fire when component is pressed */
60-
onPress?: (event: GestureResponderEvent | KeyboardEvent) => void;
60+
onPress?: (event: GestureResponderEvent | KeyboardEvent) => void | Promise<void>;
6161

6262
/** Whether the menu item should be interactive at all */
6363
interactive?: boolean;

src/libs/UserUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ function getAvatar(avatarSource?: AvatarSource, accountID?: number): AvatarSourc
176176
* @param avatarURL - the avatar source from user's personalDetails
177177
* @param accountID - the accountID of the user
178178
*/
179-
function getAvatarUrl(avatarURL: string, accountID: number): string {
180-
return isDefaultAvatar(avatarURL) ? getDefaultAvatarURL(accountID) : avatarURL;
179+
function getAvatarUrl(avatarSource: AvatarSource | undefined, accountID: number): AvatarSource {
180+
return isDefaultAvatar(avatarSource) ? getDefaultAvatarURL(accountID) : avatarSource;
181181
}
182182

183183
/**

src/pages/ShareCodePage.js

Lines changed: 0 additions & 144 deletions
This file was deleted.

src/pages/ShareCodePage.tsx

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import React, {useRef} from 'react';
2+
import {ScrollView, View} from 'react-native';
3+
import type {ImageSourcePropType} from 'react-native';
4+
import type {OnyxEntry} from 'react-native-onyx';
5+
import expensifyLogo from '@assets/images/expensify-logo-round-transparent.png';
6+
import ContextMenuItem from '@components/ContextMenuItem';
7+
import HeaderWithBackButton from '@components/HeaderWithBackButton';
8+
import * as Expensicons from '@components/Icon/Expensicons';
9+
import MenuItem from '@components/MenuItem';
10+
import QRShareWithDownload from '@components/QRShare/QRShareWithDownload';
11+
import type QRShareWithDownloadHandle from '@components/QRShare/QRShareWithDownload/types';
12+
import ScreenWrapper from '@components/ScreenWrapper';
13+
import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails';
14+
import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails';
15+
import useEnvironment from '@hooks/useEnvironment';
16+
import useLocalize from '@hooks/useLocalize';
17+
import useThemeStyles from '@hooks/useThemeStyles';
18+
import useWindowDimensions from '@hooks/useWindowDimensions';
19+
import Clipboard from '@libs/Clipboard';
20+
import getPlatform from '@libs/getPlatform';
21+
import Navigation from '@libs/Navigation/Navigation';
22+
import * as ReportUtils from '@libs/ReportUtils';
23+
import * as Url from '@libs/Url';
24+
import * as UserUtils from '@libs/UserUtils';
25+
import CONST from '@src/CONST';
26+
import ROUTES from '@src/ROUTES';
27+
import type {Report, Session} from '@src/types/onyx';
28+
29+
type ShareCodePageOnyxProps = WithCurrentUserPersonalDetailsProps & {
30+
/** Session info for the currently logged in user. */
31+
session: OnyxEntry<Session>;
32+
33+
/** The report currently being looked at */
34+
report?: OnyxEntry<Report>;
35+
};
36+
37+
type ShareCodePageProps = ShareCodePageOnyxProps;
38+
39+
function ShareCodePage({report, session, currentUserPersonalDetails}: ShareCodePageProps) {
40+
const themeStyles = useThemeStyles();
41+
const {translate} = useLocalize();
42+
const {environmentURL} = useEnvironment();
43+
const qrCodeRef = useRef<QRShareWithDownloadHandle>(null);
44+
const {isSmallScreenWidth} = useWindowDimensions();
45+
46+
const isReport = !!report?.reportID;
47+
48+
const getSubtitle = () => {
49+
if (isReport) {
50+
if (ReportUtils.isExpenseReport(report)) {
51+
return ReportUtils.getPolicyName(report);
52+
}
53+
if (ReportUtils.isMoneyRequestReport(report)) {
54+
// generate subtitle from participants
55+
return ReportUtils.getVisibleMemberIDs(report)
56+
.map((accountID) => ReportUtils.getDisplayNameForParticipant(accountID))
57+
.join(' & ');
58+
}
59+
60+
return ReportUtils.getParentNavigationSubtitle(report).workspaceName ?? ReportUtils.getChatRoomSubtitle(report);
61+
}
62+
63+
return session?.email;
64+
};
65+
66+
const title = isReport ? ReportUtils.getReportName(report) : currentUserPersonalDetails.displayName ?? '';
67+
const subtitle = getSubtitle();
68+
const urlWithTrailingSlash = Url.addTrailingForwardSlash(environmentURL);
69+
const url = isReport ? `${urlWithTrailingSlash}${ROUTES.REPORT_WITH_ID.getRoute(report.reportID)}` : `${urlWithTrailingSlash}${ROUTES.PROFILE.getRoute(session?.accountID ?? '')}`;
70+
const platform = getPlatform();
71+
const isNative = platform === CONST.PLATFORM.IOS || platform === CONST.PLATFORM.ANDROID;
72+
73+
return (
74+
<ScreenWrapper
75+
testID={ShareCodePage.displayName}
76+
shouldShowOfflineIndicatorInWideScreen={!isReport}
77+
>
78+
<HeaderWithBackButton
79+
title={translate('common.shareCode')}
80+
onBackButtonPress={() => Navigation.goBack(isReport ? ROUTES.REPORT_WITH_ID_DETAILS.getRoute(report.reportID) : ROUTES.SETTINGS)}
81+
shouldShowBackButton={isReport || isSmallScreenWidth}
82+
/>
83+
<ScrollView style={[themeStyles.flex1, themeStyles.mt3]}>
84+
<View style={[isSmallScreenWidth ? themeStyles.workspaceSectionMobile : themeStyles.workspaceSection, themeStyles.ph4]}>
85+
<QRShareWithDownload
86+
ref={qrCodeRef}
87+
url={url}
88+
title={title}
89+
subtitle={subtitle}
90+
logo={isReport ? expensifyLogo : (UserUtils.getAvatarUrl(currentUserPersonalDetails?.avatar, currentUserPersonalDetails?.accountID) as ImageSourcePropType)}
91+
logoRatio={isReport ? CONST.QR.EXPENSIFY_LOGO_SIZE_RATIO : CONST.QR.DEFAULT_LOGO_SIZE_RATIO}
92+
logoMarginRatio={isReport ? CONST.QR.EXPENSIFY_LOGO_MARGIN_RATIO : CONST.QR.DEFAULT_LOGO_MARGIN_RATIO}
93+
/>
94+
</View>
95+
96+
<View style={{marginTop: 36}}>
97+
<ContextMenuItem
98+
isAnonymousAction
99+
text={translate('qrCodes.copy')}
100+
icon={Expensicons.Copy}
101+
successIcon={Expensicons.Checkmark}
102+
successText={translate('qrCodes.copied')}
103+
onPress={() => Clipboard.setString(url)}
104+
shouldLimitWidth={false}
105+
/>
106+
107+
{isNative && (
108+
<MenuItem
109+
isAnonymousAction
110+
title={translate('common.download')}
111+
icon={Expensicons.Download}
112+
onPress={qrCodeRef.current?.download}
113+
/>
114+
)}
115+
116+
<MenuItem
117+
title={translate(`referralProgram.${CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SHARE_CODE}.buttonText1`)}
118+
icon={Expensicons.Cash}
119+
onPress={() => Navigation.navigate(ROUTES.REFERRAL_DETAILS_MODAL.getRoute(CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SHARE_CODE))}
120+
/>
121+
</View>
122+
</ScrollView>
123+
</ScreenWrapper>
124+
);
125+
}
126+
127+
ShareCodePage.displayName = 'ShareCodePage';
128+
129+
export default withCurrentUserPersonalDetails(ShareCodePage);

src/pages/home/report/ReportDetailsShareCodePage.js

Lines changed: 0 additions & 31 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from 'react';
2+
import ShareCodePage from '@pages/ShareCodePage';
3+
import type {WithReportOrNotFoundProps} from './withReportOrNotFound';
4+
import withReportOrNotFound from './withReportOrNotFound';
5+
6+
type ReportDetailsShareCodePageProps = WithReportOrNotFoundProps;
7+
8+
function ReportDetailsShareCodePage({report}: ReportDetailsShareCodePageProps) {
9+
return <ShareCodePage report={report} />;
10+
}
11+
12+
export default withReportOrNotFound()(ReportDetailsShareCodePage);

src/pages/home/report/withReportOrNotFound.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject';
1616
type WithReportOrNotFoundOnyxProps = {
1717
/** The report currently being looked at */
1818
report: OnyxEntry<OnyxTypes.Report>;
19+
1920
/** The policies which the user has access to */
2021
policies: OnyxCollection<OnyxTypes.Policy>;
22+
2123
/** Beta features list */
2224
betas: OnyxEntry<OnyxTypes.Beta[]>;
25+
2326
/** Indicated whether the report data is loading */
2427
isLoadingReportData: OnyxEntry<boolean>;
2528
};

0 commit comments

Comments
 (0)