From a1c4f22695339e1e5ae5e6580f97babceb4d6101 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Mon, 13 Oct 2025 00:17:50 +0100 Subject: [PATCH 1/3] refactor: rename ReportAttachments route --- src/ROUTES.ts | 6 +++--- src/SCREENS.ts | 2 +- .../HTMLRenderers/ImageRenderer.tsx | 2 +- .../HTMLRenderers/VideoRenderer.tsx | 10 +++++++++- .../PlaybackContext/playbackContextReportIDUtils.ts | 2 +- src/components/VideoPlayerPreview/index.tsx | 2 +- src/hooks/useCheckIfRouteHasRemainedUnchanged.ts | 6 +++--- src/hooks/useSearchState.ts | 2 +- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 2 +- .../GetStateForActionHandlers.ts | 2 +- src/libs/Navigation/helpers/linkTo/index.ts | 2 +- src/libs/Navigation/linkingConfig/config.ts | 2 +- src/libs/Navigation/types.ts | 4 ++-- src/pages/media/AttachmentModalScreen/index.tsx | 6 +++--- .../routes/ReportAttachmentModalContent.tsx | 4 ++-- src/pages/media/AttachmentModalScreen/types.ts | 2 +- tests/ui/ReportAttachments.tsx | 12 ++++++------ 17 files changed, 38 insertions(+), 30 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index f599663ad3e2..55c57e3842b9 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -485,7 +485,7 @@ const ROUTES = { return `r/${reportID}/avatar` as const; }, }, - ATTACHMENTS: { + REPORT_ATTACHMENTS: { route: 'attachment', getRoute: (params?: ReportAttachmentsRouteParams) => getAttachmentModalScreenRoute('attachment', params), }, @@ -3317,11 +3317,11 @@ const SHARED_ROUTE_PARAMS: Partial> = { export {PUBLIC_SCREENS_ROUTES, SHARED_ROUTE_PARAMS, VERIFY_ACCOUNT}; export default ROUTES; -type ReportAttachmentsRoute = typeof ROUTES.ATTACHMENTS.route; +type ReportAttachmentsRoute = typeof ROUTES.REPORT_ATTACHMENTS.route; type ReportAddAttachmentRoute = `r/${string}/attachment/add`; type AttachmentRoutes = ReportAttachmentsRoute | ReportAddAttachmentRoute; -type ReportAttachmentsRouteParams = RootNavigatorParamList[typeof SCREENS.ATTACHMENTS]; +type ReportAttachmentsRouteParams = RootNavigatorParamList[typeof SCREENS.REPORT_ATTACHMENTS]; type ReportAddAttachmentRouteParams = RootNavigatorParamList[typeof SCREENS.REPORT_ADD_ATTACHMENT]; function getAttachmentModalScreenRoute(url: AttachmentRoutes, params?: ReportAttachmentsRouteParams | ReportAddAttachmentRouteParams) { diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 60e8139be4eb..53ca71a02410 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -7,7 +7,7 @@ import type DeepValueOf from './types/utils/DeepValueOf'; const PROTECTED_SCREENS = { HOME: 'Home', CONCIERGE: 'Concierge', - ATTACHMENTS: 'Attachments', + REPORT_ATTACHMENTS: 'ReportAttachments', REPORT_ADD_ATTACHMENT: 'ReportAddAttachment', TRACK_EXPENSE: 'TrackExpense', SUBMIT_EXPENSE: 'SubmitExpense', diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx index 005465adbbbf..45f9ed3dac3d 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx @@ -104,7 +104,7 @@ function ImageRenderer({tnode}: CustomRendererProps) { } const attachmentLink = tnode.parent?.attributes?.href; - const route = ROUTES.ATTACHMENTS?.getRoute({ + const route = ROUTES.REPORT_ATTACHMENTS?.getRoute({ attachmentID, reportID, type, diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/VideoRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/VideoRenderer.tsx index 4efb88bc4f91..eda39a37df21 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/VideoRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/VideoRenderer.tsx @@ -46,7 +46,15 @@ function VideoRenderer({tnode, key}: VideoRendererProps) { return; } const isAuthTokenRequired = !!htmlAttribs[CONST.ATTACHMENT_SOURCE_ATTRIBUTE]; - const route = ROUTES.ATTACHMENTS.getRoute({attachmentID, reportID: report?.reportID, type, source: sourceURL, accountID, isAuthTokenRequired, hashKey}); + const route = ROUTES.REPORT_ATTACHMENTS.getRoute({ + attachmentID, + reportID: report?.reportID, + type, + source: sourceURL, + accountID, + isAuthTokenRequired, + hashKey, + }); Navigation.navigate(route); }} /> diff --git a/src/components/VideoPlayerContexts/PlaybackContext/playbackContextReportIDUtils.ts b/src/components/VideoPlayerContexts/PlaybackContext/playbackContextReportIDUtils.ts index 25cfd4b8f6a0..b8fce5c618ab 100644 --- a/src/components/VideoPlayerContexts/PlaybackContext/playbackContextReportIDUtils.ts +++ b/src/components/VideoPlayerContexts/PlaybackContext/playbackContextReportIDUtils.ts @@ -47,7 +47,7 @@ const getCurrentRouteReportID: (url: string) => string | ProtectedCurrentRouteRe return isFocusedRouteAChatThread ? firstReportThatHasURLInAttachments : focusedRouteReportID; }; -const screensWithReportID = [SCREENS.SEARCH.REPORT_RHP, SCREENS.REPORT, SCREENS.SEARCH.MONEY_REQUEST_REPORT, SCREENS.ATTACHMENTS]; +const screensWithReportID = [SCREENS.SEARCH.REPORT_RHP, SCREENS.REPORT, SCREENS.SEARCH.MONEY_REQUEST_REPORT, SCREENS.REPORT_ATTACHMENTS]; function hasReportIdInRouteParams(route: SearchRoute): route is RouteWithReportIDInParams { return !!route && !!route.params && !!screensWithReportID.find((screen) => screen === route.name) && 'reportID' in route.params; diff --git a/src/components/VideoPlayerPreview/index.tsx b/src/components/VideoPlayerPreview/index.tsx index 6c6bd194d3e2..b4dd3fc4461c 100644 --- a/src/components/VideoPlayerPreview/index.tsx +++ b/src/components/VideoPlayerPreview/index.tsx @@ -50,7 +50,7 @@ type VideoPlayerPreviewProps = { isDeleted?: boolean; }; -const isOnAttachmentRoute = () => Navigation.getActiveRouteWithoutParams() === `/${ROUTES.ATTACHMENTS.route}`; +const isOnAttachmentRoute = () => Navigation.getActiveRouteWithoutParams() === `/${ROUTES.REPORT_ATTACHMENTS.route}`; function VideoPlayerPreview({videoUrl, thumbnailUrl, reportID, fileName, videoDimensions, videoDuration, onShowModalPress, isDeleted}: VideoPlayerPreviewProps) { const styles = useThemeStyles(); diff --git a/src/hooks/useCheckIfRouteHasRemainedUnchanged.ts b/src/hooks/useCheckIfRouteHasRemainedUnchanged.ts index 22c1153c624d..0c6c2bd5794e 100644 --- a/src/hooks/useCheckIfRouteHasRemainedUnchanged.ts +++ b/src/hooks/useCheckIfRouteHasRemainedUnchanged.ts @@ -33,7 +33,7 @@ function useCheckIfRouteHasRemainedUnchanged(videoUrl: string) { // If on AttachmentModal, only play when the source parameters match videoUrl ensures correct play VideoPlayer share for this one const currentRoute = navigationRef.getCurrentRoute(); if ( - currentRoute?.name === SCREENS.ATTACHMENTS && + currentRoute?.name === SCREENS.REPORT_ATTACHMENTS && currentRoute?.params && 'source' in currentRoute.params && currentRoute.params.source === videoUrl && @@ -57,7 +57,7 @@ function useCheckIfRouteHasRemainedUnchanged(videoUrl: string) { const route = navigationRef.getCurrentRoute(); // If the app is launched with the attachment route, it will always remain on the report screen. // Thus, it can be considered as still being on the rendered route. - isOnInitialRenderedRouteRef.current = navigation.isFocused() || route?.name === SCREENS.ATTACHMENTS; + isOnInitialRenderedRouteRef.current = navigation.isFocused() || route?.name === SCREENS.REPORT_ATTACHMENTS; }); // eslint-disable-next-line react-compiler/react-compiler // eslint-disable-next-line react-hooks/exhaustive-deps @@ -71,7 +71,7 @@ function useCheckIfRouteHasRemainedUnchanged(videoUrl: string) { const unsubscribeBlur = navigation.addListener('blur', () => { const route = navigationRef.getCurrentRoute(); - if (route?.name === SCREENS.ATTACHMENTS) { + if (route?.name === SCREENS.REPORT_ATTACHMENTS) { // Skip route update when attachment modal is opened return; } diff --git a/src/hooks/useSearchState.ts b/src/hooks/useSearchState.ts index c9f0f55cadb6..b5825e1c9880 100644 --- a/src/hooks/useSearchState.ts +++ b/src/hooks/useSearchState.ts @@ -30,7 +30,7 @@ const useSearchState = (): SearchStateResult => { return {isOnSearch: false, hashKey: undefined}; } - const isSearchAttachmentModal = route?.name === SCREENS.ATTACHMENTS && type === CONST.ATTACHMENT_TYPE.SEARCH; + const isSearchAttachmentModal = route?.name === SCREENS.REPORT_ATTACHMENTS && type === CONST.ATTACHMENT_TYPE.SEARCH; const queryJSON = q ? buildSearchQueryJSON(q) : ({} as Partial); // for attachment modal the hashKey is passed through route params, fallback to it if not found in queryJSON const hashKey = queryJSON?.hash ? queryJSON.hash : (hashKeyFromRoute ?? undefined); diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 64b60bbe948a..6a09d6745e8c 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -570,7 +570,7 @@ function AuthScreens() { getComponent={loadSubmitExpensePage} /> ['config'] = { [SCREENS.SIGN_IN_WITH_GOOGLE_DESKTOP]: ROUTES.GOOGLE_SIGN_IN, [SCREENS.SAML_SIGN_IN]: ROUTES.SAML_SIGN_IN, [SCREENS.DESKTOP_SIGN_IN_REDIRECT]: ROUTES.DESKTOP_SIGN_IN_REDIRECT, - [SCREENS.ATTACHMENTS]: ROUTES.ATTACHMENTS.route, + [SCREENS.REPORT_ATTACHMENTS]: ROUTES.REPORT_ATTACHMENTS.route, [SCREENS.REPORT_ADD_ATTACHMENT]: ROUTES.REPORT_ADD_ATTACHMENT.route, [SCREENS.PROFILE_AVATAR]: ROUTES.PROFILE_AVATAR.route, [SCREENS.WORKSPACE_AVATAR]: ROUTES.WORKSPACE_AVATAR.route, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 856d0e8957aa..fd28274b4ecc 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1917,7 +1917,7 @@ type ReportsSplitNavigatorParamList = { referrer?: string; backTo?: Routes; }; - [SCREENS.ATTACHMENTS]: AttachmentModalScreensParamList[typeof SCREENS.ATTACHMENTS]; + [SCREENS.REPORT_ATTACHMENTS]: AttachmentModalScreensParamList[typeof SCREENS.REPORT_ATTACHMENTS]; }; type SettingsSplitNavigatorParamList = { @@ -2176,7 +2176,7 @@ type PublicScreensParamList = SharedScreensParamList & { }; type AttachmentModalScreensParamList = { - [SCREENS.ATTACHMENTS]: AttachmentModalContainerModalProps & { + [SCREENS.REPORT_ATTACHMENTS]: AttachmentModalContainerModalProps & { source?: AvatarSource; reportID?: string; accountID?: number; diff --git a/src/pages/media/AttachmentModalScreen/index.tsx b/src/pages/media/AttachmentModalScreen/index.tsx index 749260326f9a..de7c63294ecc 100644 --- a/src/pages/media/AttachmentModalScreen/index.tsx +++ b/src/pages/media/AttachmentModalScreen/index.tsx @@ -27,11 +27,11 @@ function AttachmentModalScreen({route, return route; }, [attachmentsContext, route]); - if (route.name === SCREENS.ATTACHMENTS) { + if (route.name === SCREENS.REPORT_ATTACHMENTS) { return ( } - navigation={navigation as NavigationType} + route={routeWithContext as RouteType} + navigation={navigation as NavigationType} /> ); } diff --git a/src/pages/media/AttachmentModalScreen/routes/ReportAttachmentModalContent.tsx b/src/pages/media/AttachmentModalScreen/routes/ReportAttachmentModalContent.tsx index a59fa877059b..03abdf210c40 100644 --- a/src/pages/media/AttachmentModalScreen/routes/ReportAttachmentModalContent.tsx +++ b/src/pages/media/AttachmentModalScreen/routes/ReportAttachmentModalContent.tsx @@ -20,7 +20,7 @@ import useDownloadAttachment from './hooks/useDownloadAttachment'; import useNavigateToReportOnRefresh from './hooks/useNavigateToReportOnRefresh'; import useReportAttachmentModalType from './hooks/useReportAttachmentModalType'; -function ReportAttachmentModalContent({route, navigation}: AttachmentModalScreenProps) { +function ReportAttachmentModalContent({route, navigation}: AttachmentModalScreenProps) { const {attachmentID, type, source: sourceParam, isAuthTokenRequired, attachmentLink, originalFileName, accountID, reportID, hashKey, headerTitle, onShow, onClose} = route.params; const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, { @@ -115,7 +115,7 @@ function ReportAttachmentModalContent({route, navigation}: AttachmentModalScreen ); return ( - + navigation={navigation} contentProps={contentProps} modalType={modalType} diff --git a/src/pages/media/AttachmentModalScreen/types.ts b/src/pages/media/AttachmentModalScreen/types.ts index e383d298bc97..112a347513de 100644 --- a/src/pages/media/AttachmentModalScreen/types.ts +++ b/src/pages/media/AttachmentModalScreen/types.ts @@ -39,7 +39,7 @@ type AttachmentModalContainerModalProps = { }; const ATTACHMENT_MODAL_SCREENS = [ - SCREENS.ATTACHMENTS, + SCREENS.REPORT_ATTACHMENTS, SCREENS.REPORT_ADD_ATTACHMENT, SCREENS.REPORT_AVATAR, SCREENS.PROFILE_AVATAR, diff --git a/tests/ui/ReportAttachments.tsx b/tests/ui/ReportAttachments.tsx index 5180364f32a9..895ac9ca9af1 100644 --- a/tests/ui/ReportAttachments.tsx +++ b/tests/ui/ReportAttachments.tsx @@ -39,13 +39,13 @@ jest.mock('@react-native-community/geolocation', () => ({ })); jest.mock('@src/components/Attachments/AttachmentCarousel/Pager/usePageScrollHandler', () => jest.fn()); -const renderPage = (initialRouteName: typeof SCREENS.ATTACHMENTS, initialParams: AuthScreensParamList[typeof SCREENS.ATTACHMENTS]) => { +const renderPage = (initialRouteName: typeof SCREENS.REPORT_ATTACHMENTS, initialParams: AuthScreensParamList[typeof SCREENS.REPORT_ATTACHMENTS]) => { return render( @@ -181,7 +181,7 @@ describe('ReportAttachments', () => { await waitForBatchedUpdatesWithAct(); // Given the report attachments params - const params: AuthScreensParamList[typeof SCREENS.ATTACHMENTS] = { + const params: AuthScreensParamList[typeof SCREENS.REPORT_ATTACHMENTS] = { source: 'https://staging.expensify.com/chat-attachments/7006877151048865417/w_d060af4fb7ac4a815e6ed99df9ef8dd216fdd8c7.png', type: 'r', reportID: '7487537791562875', @@ -191,7 +191,7 @@ describe('ReportAttachments', () => { }; // And ReportAttachments is opened - renderPage(SCREENS.ATTACHMENTS, params); + renderPage(SCREENS.REPORT_ATTACHMENTS, params); await waitForBatchedUpdatesWithAct(); @@ -201,7 +201,7 @@ describe('ReportAttachments', () => { }); it('should fetch the report id, if the report has not yet been opened by the user', async () => { // Given the report attachments params - const params: AuthScreensParamList[typeof SCREENS.ATTACHMENTS] = { + const params: AuthScreensParamList[typeof SCREENS.REPORT_ATTACHMENTS] = { source: 'https://staging.expensify.com/chat-attachments/7006877151048865417/w_d060af4fb7ac4a815e6ed99df9ef8dd216fdd8c7.png', type: 'r', reportID: '7487537791562875', @@ -211,7 +211,7 @@ describe('ReportAttachments', () => { }; // And ReportAttachments is opened - renderPage(SCREENS.ATTACHMENTS, params); + renderPage(SCREENS.REPORT_ATTACHMENTS, params); await waitForBatchedUpdatesWithAct(); const openReportRequest = getFetchMockCalls(WRITE_COMMANDS.OPEN_REPORT).find((request) => { From 682c3904a28000a73eaf3fe5ef898c240bf60d3e Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Mon, 13 Oct 2025 00:33:37 +0100 Subject: [PATCH 2/3] refactor: move ReportAttachments route into routes/report --- src/pages/media/AttachmentModalScreen/index.tsx | 2 +- .../routes/{ => report}/ReportAttachmentModalContent.tsx | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/pages/media/AttachmentModalScreen/routes/{ => report}/ReportAttachmentModalContent.tsx (100%) diff --git a/src/pages/media/AttachmentModalScreen/index.tsx b/src/pages/media/AttachmentModalScreen/index.tsx index de7c63294ecc..a6340f41c20b 100644 --- a/src/pages/media/AttachmentModalScreen/index.tsx +++ b/src/pages/media/AttachmentModalScreen/index.tsx @@ -3,7 +3,7 @@ import SCREENS from '@src/SCREENS'; import AttachmentModalContext from './AttachmentModalContext'; import ProfileAvatarModalContent from './routes/ProfileAvatarModalContent'; import ReportAddAttachmentModalContent from './routes/report/ReportAddAttachmentModalContent'; -import ReportAttachmentModalContent from './routes/ReportAttachmentModalContent'; +import ReportAttachmentModalContent from './routes/report/ReportAttachmentModalContent'; import ReportAvatarModalContent from './routes/ReportAvatarModalContent'; import TransactionReceiptModalContent from './routes/TransactionReceiptModalContent'; import WorkspaceAvatarModalContent from './routes/WorkspaceAvatarModalContent'; diff --git a/src/pages/media/AttachmentModalScreen/routes/ReportAttachmentModalContent.tsx b/src/pages/media/AttachmentModalScreen/routes/report/ReportAttachmentModalContent.tsx similarity index 100% rename from src/pages/media/AttachmentModalScreen/routes/ReportAttachmentModalContent.tsx rename to src/pages/media/AttachmentModalScreen/routes/report/ReportAttachmentModalContent.tsx From 9d77735936c3c484ad71c71087473ac802180dff Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Mon, 13 Oct 2025 00:56:49 +0100 Subject: [PATCH 3/3] fix: TS/ESLint errors --- .../routes/report/ReportAttachmentModalContent.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/media/AttachmentModalScreen/routes/report/ReportAttachmentModalContent.tsx b/src/pages/media/AttachmentModalScreen/routes/report/ReportAttachmentModalContent.tsx index 03abdf210c40..9e780a856ea8 100644 --- a/src/pages/media/AttachmentModalScreen/routes/report/ReportAttachmentModalContent.tsx +++ b/src/pages/media/AttachmentModalScreen/routes/report/ReportAttachmentModalContent.tsx @@ -10,15 +10,15 @@ import {isReportNotFound} from '@libs/ReportUtils'; import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot'; import type {AttachmentModalBaseContentProps} from '@pages/media/AttachmentModalScreen/AttachmentModalBaseContent/types'; import AttachmentModalContainer from '@pages/media/AttachmentModalScreen/AttachmentModalContainer'; +import useDownloadAttachment from '@pages/media/AttachmentModalScreen/routes/hooks/useDownloadAttachment'; +import useNavigateToReportOnRefresh from '@pages/media/AttachmentModalScreen/routes/hooks/useNavigateToReportOnRefresh'; +import useReportAttachmentModalType from '@pages/media/AttachmentModalScreen/routes/hooks/useReportAttachmentModalType'; import type {AttachmentModalScreenProps} from '@pages/media/AttachmentModalScreen/types'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import useDownloadAttachment from './hooks/useDownloadAttachment'; -import useNavigateToReportOnRefresh from './hooks/useNavigateToReportOnRefresh'; -import useReportAttachmentModalType from './hooks/useReportAttachmentModalType'; function ReportAttachmentModalContent({route, navigation}: AttachmentModalScreenProps) { const {attachmentID, type, source: sourceParam, isAuthTokenRequired, attachmentLink, originalFileName, accountID, reportID, hashKey, headerTitle, onShow, onClose} = route.params; @@ -70,7 +70,7 @@ function ReportAttachmentModalContent({route, navigation}: AttachmentModalScreen const onCarouselAttachmentChange = useCallback( (attachment: Attachment) => { - const routeToNavigate = ROUTES.ATTACHMENTS.getRoute({ + const routeToNavigate = ROUTES.REPORT_ATTACHMENTS.getRoute({ reportID, attachmentID: attachment.attachmentID, type,