From 4ce1443b839da2a75ada8193ecbbf6aea46958dd Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 25 Jan 2024 15:48:02 +0100 Subject: [PATCH 1/5] ref: move ReportDetailsPage to TS --- src/components/DisplayNames/types.ts | 2 +- src/libs/PolicyUtils.ts | 2 +- src/libs/ReportUtils.ts | 2 +- ...rtDetailsPage.js => ReportDetailsPage.tsx} | 182 +++++++++--------- .../home/report/withReportOrNotFound.tsx | 8 +- 5 files changed, 94 insertions(+), 102 deletions(-) rename src/pages/{ReportDetailsPage.js => ReportDetailsPage.tsx} (65%) diff --git a/src/components/DisplayNames/types.ts b/src/components/DisplayNames/types.ts index 2e6f36d5cc07..7da1819c9f01 100644 --- a/src/components/DisplayNames/types.ts +++ b/src/components/DisplayNames/types.ts @@ -20,7 +20,7 @@ type DisplayNamesProps = { fullTitle: string; /** Array of objects that map display names to their corresponding tooltip */ - displayNamesWithTooltips: DisplayNameWithTooltip[]; + displayNamesWithTooltips?: DisplayNameWithTooltip[]; /** Number of lines before wrapping */ numberOfLines: number; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index b8ed62f93082..47916dc474ba 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -112,7 +112,7 @@ function isExpensifyGuideTeam(email: string): boolean { */ const isPolicyAdmin = (policy: OnyxEntry): boolean => policy?.role === CONST.POLICY.ROLE.ADMIN; -const isPolicyMember = (policyID: string, policies: Record): boolean => Object.values(policies).some((policy) => policy?.id === policyID); +const isPolicyMember = (policyID: string, policies: OnyxCollection): boolean => Object.values(policies ?? {}).some((policy) => policy?.id === policyID); /** * Create an object mapping member emails to their accountIDs. Filter for members without errors, and get the login email from the personalDetail object using the accountID. diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index e9c3b1710cc0..fb15feb38d59 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4540,7 +4540,7 @@ function shouldAutoFocusOnKeyPress(event: KeyboardEvent): boolean { /** * Navigates to the appropriate screen based on the presence of a private note for the current user. */ -function navigateToPrivateNotes(report: Report, session: Session) { +function navigateToPrivateNotes(report: OnyxEntry, session: OnyxEntry) { if (isEmpty(report) || isEmpty(session) || !session.accountID) { return; } diff --git a/src/pages/ReportDetailsPage.js b/src/pages/ReportDetailsPage.tsx similarity index 65% rename from src/pages/ReportDetailsPage.js rename to src/pages/ReportDetailsPage.tsx index 3e682d592370..9a9ca49c68eb 100644 --- a/src/pages/ReportDetailsPage.js +++ b/src/pages/ReportDetailsPage.tsx @@ -1,103 +1,99 @@ -import PropTypes from 'prop-types'; +import type {FC} from 'react'; import React, {useEffect, useMemo} from 'react'; import {ScrollView, View} from 'react-native'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {SvgProps} from 'react-native-svg'; +import type {ValueOf} from 'type-fest'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import DisplayNames from '@components/DisplayNames'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; import MenuItem from '@components/MenuItem'; import MultipleAvatars from '@components/MultipleAvatars'; -import {withNetwork} from '@components/OnyxProvider'; import ParentNavigationSubtitle from '@components/ParentNavigationSubtitle'; -import participantPropTypes from '@components/participantPropTypes'; import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; import RoomHeaderAvatars from '@components/RoomHeaderAvatars'; import ScreenWrapper from '@components/ScreenWrapper'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import useLocalize from '@hooks/useLocalize'; +import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as Report from '@userActions/Report'; import CONST from '@src/CONST'; +import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type * as OnyxTypes from '@src/types/onyx'; +import type DeepValueOf from '@src/types/utils/DeepValueOf'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import type {WithReportOrNotFoundProps} from './home/report/withReportOrNotFound'; import withReportOrNotFound from './home/report/withReportOrNotFound'; -import reportPropTypes from './reportPropTypes'; -const propTypes = { - ...withLocalizePropTypes, - - /** The report currently being looked at */ - report: reportPropTypes.isRequired, - - /** The policies which the user has access to and which the report could be tied to */ - policies: PropTypes.shape({ - /** Name of the policy */ - name: PropTypes.string, - }), - - /** Route params */ - route: PropTypes.shape({ - params: PropTypes.shape({ - /** Report ID passed via route r/:reportID/details */ - reportID: PropTypes.string, - }), - }).isRequired, - - /** Personal details of all the users */ - personalDetails: PropTypes.objectOf(participantPropTypes), +type ReportDetailsPageMenuItem = { + key: DeepValueOf; + translationKey: TranslationPaths; + icon: FC; + isAnonymousAction: boolean; + action: () => void; + brickRoadIndicator?: ValueOf; + subtitle?: number; }; -const defaultProps = { - policies: {}, - personalDetails: {}, +type ReportDetailsPageOnyxProps = { + personalDetails: OnyxCollection; + session: OnyxEntry; }; +type ReportDetailsPageProps = { + report: OnyxEntry; +} & ReportDetailsPageOnyxProps & + WithReportOrNotFoundProps; -function ReportDetailsPage(props) { +function ReportDetailsPage({policies, report, session, personalDetails}: ReportDetailsPageProps) { + const {translate} = useLocalize(); + const {isOffline} = useNetwork(); const styles = useThemeStyles(); - const policy = useMemo(() => props.policies[`${ONYXKEYS.COLLECTION.POLICY}${props.report.policyID}`], [props.policies, props.report.policyID]); - const isPolicyAdmin = useMemo(() => PolicyUtils.isPolicyAdmin(policy), [policy]); - const isPolicyMember = useMemo(() => PolicyUtils.isPolicyMember(props.report.policyID, props.policies), [props.report.policyID, props.policies]); - const shouldUseFullTitle = useMemo(() => ReportUtils.shouldUseFullTitleToDisplay(props.report), [props.report]); - const isChatRoom = useMemo(() => ReportUtils.isChatRoom(props.report), [props.report]); - const isThread = useMemo(() => ReportUtils.isChatThread(props.report), [props.report]); - const isUserCreatedPolicyRoom = useMemo(() => ReportUtils.isUserCreatedPolicyRoom(props.report), [props.report]); - const isArchivedRoom = useMemo(() => ReportUtils.isArchivedRoom(props.report), [props.report]); - const isMoneyRequestReport = useMemo(() => ReportUtils.isMoneyRequestReport(props.report), [props.report]); + const policy = useMemo(() => policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID ?? ''}`], [policies, report?.policyID]); + const isPolicyAdmin = useMemo(() => PolicyUtils.isPolicyAdmin(policy ?? null), [policy]); + const isPolicyMember = useMemo(() => PolicyUtils.isPolicyMember(report?.policyID ?? '', policies), [report?.policyID, policies]); + const shouldUseFullTitle = useMemo(() => ReportUtils.shouldUseFullTitleToDisplay(report), [report]); + const isChatRoom = useMemo(() => ReportUtils.isChatRoom(report), [report]); + const isThread = useMemo(() => ReportUtils.isChatThread(report), [report]); + const isUserCreatedPolicyRoom = useMemo(() => ReportUtils.isUserCreatedPolicyRoom(report), [report]); + const isArchivedRoom = useMemo(() => ReportUtils.isArchivedRoom(report), [report]); + const isMoneyRequestReport = useMemo(() => ReportUtils.isMoneyRequestReport(report), [report]); // eslint-disable-next-line react-hooks/exhaustive-deps -- policy is a dependency because `getChatRoomSubtitle` calls `getPolicyName` which in turn retrieves the value from the `policy` value stored in Onyx - const chatRoomSubtitle = useMemo(() => ReportUtils.getChatRoomSubtitle(props.report), [props.report, policy]); - const parentNavigationSubtitleData = ReportUtils.getParentNavigationSubtitle(props.report); - const participants = useMemo(() => ReportUtils.getVisibleMemberIDs(props.report), [props.report]); + const chatRoomSubtitle = useMemo(() => ReportUtils.getChatRoomSubtitle(report), [report, policy]); + const parentNavigationSubtitleData = ReportUtils.getParentNavigationSubtitle(report); + const participants = useMemo(() => ReportUtils.getVisibleMemberIDs(report), [report]); - const isGroupDMChat = useMemo(() => ReportUtils.isDM(props.report) && participants.length > 1, [props.report, participants.length]); + const isGroupDMChat = useMemo(() => ReportUtils.isDM(report) && participants.length > 1, [report, participants.length]); - const isPrivateNotesFetchTriggered = !_.isUndefined(props.report.isLoadingPrivateNotes); + const isPrivateNotesFetchTriggered = report?.isLoadingPrivateNotes !== undefined; useEffect(() => { // Do not fetch private notes if isLoadingPrivateNotes is already defined, or if network is offline. - if (isPrivateNotesFetchTriggered || props.network.isOffline) { + if (isPrivateNotesFetchTriggered || isOffline) { return; } - Report.getReportPrivateNote(props.report.reportID); - }, [props.report.reportID, props.network.isOffline, isPrivateNotesFetchTriggered]); + Report.getReportPrivateNote(report?.reportID ?? ''); + }, [report?.reportID, isOffline, isPrivateNotesFetchTriggered]); - const menuItems = useMemo(() => { + const menuItems: ReportDetailsPageMenuItem[] = useMemo(() => { const items = []; if (!isGroupDMChat) { items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.SHARE_CODE, - translationKey: 'common.shareCode', + translationKey: 'common.shareCode' as const, icon: Expensicons.QrCode, isAnonymousAction: true, - action: () => Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS_SHARE_CODE.getRoute(props.report.reportID)), + action: () => Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS_SHARE_CODE.getRoute(report?.reportID ?? '')), }); } @@ -111,61 +107,62 @@ function ReportDetailsPage(props) { if ((!isUserCreatedPolicyRoom && participants.length) || (isUserCreatedPolicyRoom && isPolicyMember)) { items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.MEMBERS, - translationKey: 'common.members', + translationKey: 'common.members' as const, icon: Expensicons.Users, subtitle: participants.length, isAnonymousAction: false, action: () => { - if (isUserCreatedPolicyRoom && !props.report.parentReportID) { - Navigation.navigate(ROUTES.ROOM_MEMBERS.getRoute(props.report.reportID)); + if (isUserCreatedPolicyRoom && !report?.parentReportID) { + Navigation.navigate(ROUTES.ROOM_MEMBERS.getRoute(report?.reportID ?? '')); } else { - Navigation.navigate(ROUTES.REPORT_PARTICIPANTS.getRoute(props.report.reportID)); + Navigation.navigate(ROUTES.REPORT_PARTICIPANTS.getRoute(report?.reportID ?? '')); } }, }); - } else if (isUserCreatedPolicyRoom && (!participants.length || !isPolicyMember) && !props.report.parentReportID) { + } else if (isUserCreatedPolicyRoom && (!participants.length || !isPolicyMember) && !report?.parentReportID) { items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.INVITE, - translationKey: 'common.invite', + translationKey: 'common.invite' as const, icon: Expensicons.Users, isAnonymousAction: false, action: () => { - Navigation.navigate(ROUTES.ROOM_INVITE.getRoute(props.report.reportID)); + Navigation.navigate(ROUTES.ROOM_INVITE.getRoute(report?.reportID ?? '')); }, }); } items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.SETTINGS, - translationKey: 'common.settings', + translationKey: 'common.settings' as const, icon: Expensicons.Gear, isAnonymousAction: false, action: () => { - Navigation.navigate(ROUTES.REPORT_SETTINGS.getRoute(props.report.reportID)); + Navigation.navigate(ROUTES.REPORT_SETTINGS.getRoute(report?.reportID ?? '')); }, }); // Prevent displaying private notes option for threads and task reports - if (!isThread && !isMoneyRequestReport && !ReportUtils.isTaskReport(props.report)) { + if (!isThread && !isMoneyRequestReport && !ReportUtils.isTaskReport(report)) { items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.PRIVATE_NOTES, - translationKey: 'privateNotes.title', + translationKey: 'privateNotes.title' as const, icon: Expensicons.Pencil, isAnonymousAction: false, - action: () => ReportUtils.navigateToPrivateNotes(props.report, props.session), - brickRoadIndicator: Report.hasErrorInPrivateNotes(props.report) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : '', + action: () => ReportUtils.navigateToPrivateNotes(report, session), + brickRoadIndicator: Report.hasErrorInPrivateNotes(report) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }); } return items; - }, [isArchivedRoom, participants.length, isThread, isMoneyRequestReport, props.report, isGroupDMChat, isPolicyMember, isUserCreatedPolicyRoom, props.session]); + }, [isArchivedRoom, participants.length, isThread, isMoneyRequestReport, report, isGroupDMChat, isPolicyMember, isUserCreatedPolicyRoom, session]); const displayNamesWithTooltips = useMemo(() => { const hasMultipleParticipants = participants.length > 1; - return ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForAccountIDs(participants, props.personalDetails), hasMultipleParticipants); - }, [participants, props.personalDetails]); + // @ts-expect-error TODO: Remove this once OptionsListUtils (https://github.com/Expensify/App/issues/24921) is migrated to TypeScript. + return ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForAccountIDs(participants, personalDetails), hasMultipleParticipants); + }, [participants, personalDetails]); - const icons = useMemo(() => ReportUtils.getIcons(props.report, props.personalDetails, props.policies), [props.report, props.personalDetails, props.policies]); + const icons = useMemo(() => ReportUtils.getIcons(report, personalDetails, policies), [report, personalDetails, policies]); const chatRoomSubtitleText = chatRoomSubtitle ? ( - + { Navigation.goBack(); - Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(props.report.reportID)); + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report?.reportID ?? '')); }} /> @@ -199,14 +196,14 @@ function ReportDetailsPage(props) { ) : ( )} { - Navigation.navigate(ROUTES.WORKSPACE_INITIAL.getRoute(props.report.policyID)); + Navigation.navigate(ROUTES.WORKSPACE_INITIAL.getRoute(report?.policyID ?? '')); }} > {chatRoomSubtitleText} @@ -229,28 +227,28 @@ function ReportDetailsPage(props) { ) : ( chatRoomSubtitleText )} - {!_.isEmpty(parentNavigationSubtitleData) && isMoneyRequestReport && ( + {!isEmptyObject(parentNavigationSubtitleData) && isMoneyRequestReport && ( )} - {_.map(menuItems, (item) => { + {menuItems.map((item) => { const brickRoadIndicator = - ReportUtils.hasReportNameError(props.report) && item.key === CONST.REPORT_DETAILS_MENU_ITEM.SETTINGS ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''; + ReportUtils.hasReportNameError(report) && item.key === CONST.REPORT_DETAILS_MENU_ITEM.SETTINGS ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined; return ( ); })} @@ -261,22 +259,14 @@ function ReportDetailsPage(props) { } ReportDetailsPage.displayName = 'ReportDetailsPage'; -ReportDetailsPage.propTypes = propTypes; -ReportDetailsPage.defaultProps = defaultProps; -export default compose( - withLocalize, - withReportOrNotFound(), - withNetwork(), - withOnyx({ +export default withReportOrNotFound()( + withOnyx({ personalDetails: { key: ONYXKEYS.PERSONAL_DETAILS_LIST, }, - policies: { - key: ONYXKEYS.COLLECTION.POLICY, - }, session: { key: ONYXKEYS.SESSION, }, - }), -)(ReportDetailsPage); + })(ReportDetailsPage), +); diff --git a/src/pages/home/report/withReportOrNotFound.tsx b/src/pages/home/report/withReportOrNotFound.tsx index 7613bafeacdc..a8facc3e1c76 100644 --- a/src/pages/home/report/withReportOrNotFound.tsx +++ b/src/pages/home/report/withReportOrNotFound.tsx @@ -22,16 +22,16 @@ type OnyxProps = { isLoadingReportData: OnyxEntry; }; -type ComponentProps = OnyxProps & { +type WithReportOrNotFoundProps = OnyxProps & { route: RouteProp<{params: {reportID: string}}>; }; export default function ( shouldRequireReportID = true, -): ( +): ( WrappedComponent: React.ComponentType>, ) => React.ComponentType, keyof OnyxProps>> { - return function (WrappedComponent: ComponentType>) { + return function (WrappedComponent: ComponentType>) { function WithReportOrNotFound(props: TProps, ref: ForwardedRef) { const contentShown = React.useRef(false); @@ -89,3 +89,5 @@ export default function ( })(React.forwardRef(WithReportOrNotFound)); }; } + +export type {WithReportOrNotFoundProps}; From 8bf49b65d002766aa90e71ff7a03eba6c01a854d Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 25 Jan 2024 15:53:52 +0100 Subject: [PATCH 2/5] fix: typecheck --- src/components/DisplayNames/DisplayNamesWithTooltip.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/DisplayNames/DisplayNamesWithTooltip.tsx b/src/components/DisplayNames/DisplayNamesWithTooltip.tsx index ce0ae7ddcf4f..1cacb0e20c5d 100644 --- a/src/components/DisplayNames/DisplayNamesWithTooltip.tsx +++ b/src/components/DisplayNames/DisplayNamesWithTooltip.tsx @@ -56,7 +56,7 @@ function DisplayNamesWithToolTip({shouldUseFullTitle, fullTitle, displayNamesWit > {shouldUseFullTitle ? ReportUtils.formatReportLastMessageText(fullTitle) - : displayNamesWithTooltips.map(({displayName, accountID, avatar, login}, index) => ( + : displayNamesWithTooltips?.map(({displayName, accountID, avatar, login}, index) => ( // eslint-disable-next-line react/no-array-index-key Date: Thu, 25 Jan 2024 15:59:50 +0100 Subject: [PATCH 3/5] fix: add comments to props --- src/pages/ReportDetailsPage.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 9a9ca49c68eb..bceaeddc0349 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -44,10 +44,14 @@ type ReportDetailsPageMenuItem = { }; type ReportDetailsPageOnyxProps = { + /** Personal details of all the users */ personalDetails: OnyxCollection; + + /** Session info for the currently logged in user. */ session: OnyxEntry; }; type ReportDetailsPageProps = { + /** The report currently being looked at */ report: OnyxEntry; } & ReportDetailsPageOnyxProps & WithReportOrNotFoundProps; From 888c5fc67d9fda330769dc094de74cebcffe7f9b Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 30 Jan 2024 12:42:45 +0100 Subject: [PATCH 4/5] fix: resolved comments --- src/pages/ReportDetailsPage.tsx | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index bceaeddc0349..d858b47e9cc2 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -1,3 +1,4 @@ +import type {StackScreenProps} from '@react-navigation/stack'; import type {FC} from 'react'; import React, {useEffect, useMemo} from 'react'; import {ScrollView, View} from 'react-native'; @@ -19,6 +20,7 @@ import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; +import type {ReportDetailsNavigatorParamList} from '@libs/Navigation/types'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -27,6 +29,7 @@ import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -50,11 +53,7 @@ type ReportDetailsPageOnyxProps = { /** Session info for the currently logged in user. */ session: OnyxEntry; }; -type ReportDetailsPageProps = { - /** The report currently being looked at */ - report: OnyxEntry; -} & ReportDetailsPageOnyxProps & - WithReportOrNotFoundProps; +type ReportDetailsPageProps = ReportDetailsPageOnyxProps & WithReportOrNotFoundProps & StackScreenProps; function ReportDetailsPage({policies, report, session, personalDetails}: ReportDetailsPageProps) { const {translate} = useLocalize(); @@ -89,12 +88,12 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD }, [report?.reportID, isOffline, isPrivateNotesFetchTriggered]); const menuItems: ReportDetailsPageMenuItem[] = useMemo(() => { - const items = []; + const items: ReportDetailsPageMenuItem[] = []; if (!isGroupDMChat) { items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.SHARE_CODE, - translationKey: 'common.shareCode' as const, + translationKey: 'common.shareCode', icon: Expensicons.QrCode, isAnonymousAction: true, action: () => Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS_SHARE_CODE.getRoute(report?.reportID ?? '')), @@ -111,7 +110,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD if ((!isUserCreatedPolicyRoom && participants.length) || (isUserCreatedPolicyRoom && isPolicyMember)) { items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.MEMBERS, - translationKey: 'common.members' as const, + translationKey: 'common.members', icon: Expensicons.Users, subtitle: participants.length, isAnonymousAction: false, @@ -126,7 +125,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD } else if (isUserCreatedPolicyRoom && (!participants.length || !isPolicyMember) && !report?.parentReportID) { items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.INVITE, - translationKey: 'common.invite' as const, + translationKey: 'common.invite', icon: Expensicons.Users, isAnonymousAction: false, action: () => { @@ -137,7 +136,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.SETTINGS, - translationKey: 'common.settings' as const, + translationKey: 'common.settings', icon: Expensicons.Gear, isAnonymousAction: false, action: () => { @@ -149,7 +148,7 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD if (!isThread && !isMoneyRequestReport && !ReportUtils.isTaskReport(report)) { items.push({ key: CONST.REPORT_DETAILS_MENU_ITEM.PRIVATE_NOTES, - translationKey: 'privateNotes.title' as const, + translationKey: 'privateNotes.title', icon: Expensicons.Pencil, isAnonymousAction: false, action: () => ReportUtils.navigateToPrivateNotes(report, session), From b2a5a009825a18f06cbdc19ef6a7dc6c337d4089 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 30 Jan 2024 12:48:10 +0100 Subject: [PATCH 5/5] fix: typecheck --- src/pages/ReportDetailsPage.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index d858b47e9cc2..fc905e35899e 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -1,10 +1,8 @@ import type {StackScreenProps} from '@react-navigation/stack'; -import type {FC} from 'react'; import React, {useEffect, useMemo} from 'react'; import {ScrollView, View} from 'react-native'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import type {SvgProps} from 'react-native-svg'; import type {ValueOf} from 'type-fest'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import DisplayNames from '@components/DisplayNames'; @@ -33,13 +31,14 @@ import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import type IconAsset from '@src/types/utils/IconAsset'; import type {WithReportOrNotFoundProps} from './home/report/withReportOrNotFound'; import withReportOrNotFound from './home/report/withReportOrNotFound'; type ReportDetailsPageMenuItem = { key: DeepValueOf; translationKey: TranslationPaths; - icon: FC; + icon: IconAsset; isAnonymousAction: boolean; action: () => void; brickRoadIndicator?: ValueOf; @@ -161,7 +160,6 @@ function ReportDetailsPage({policies, report, session, personalDetails}: ReportD const displayNamesWithTooltips = useMemo(() => { const hasMultipleParticipants = participants.length > 1; - // @ts-expect-error TODO: Remove this once OptionsListUtils (https://github.com/Expensify/App/issues/24921) is migrated to TypeScript. return ReportUtils.getDisplayNamesWithTooltips(OptionsListUtils.getPersonalDetailsForAccountIDs(participants, personalDetails), hasMultipleParticipants); }, [participants, personalDetails]);