diff --git a/src/CONST.ts b/src/CONST.ts index 4665ec94625a..1663be1238fd 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1186,6 +1186,10 @@ const CONST = { WEBP: 'image/webp', JPEG: 'image/jpeg', }, + ATTACHMENT_TYPE: { + REPORT: 'r', + NOTE: 'n', + }, IMAGE_OBJECT_POSITION: { TOP: 'top', diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 903496458043..22e19b43f8cd 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -251,9 +251,10 @@ const ROUTES = { route: 'r/:reportID/details/shareCode', getRoute: (reportID: string) => `r/${reportID}/details/shareCode` as const, }, - REPORT_ATTACHMENTS: { - route: 'r/:reportID/attachment', - getRoute: (reportID: string, source: string) => `r/${reportID}/attachment?source=${encodeURIComponent(source)}` as const, + ATTACHMENTS: { + route: 'attachment', + getRoute: (reportID: string, type: ValueOf, url: string, accountID?: number) => + `attachment?source=${encodeURIComponent(url)}&type=${type}${reportID ? `&reportID=${reportID}` : ''}${accountID ? `&accountID=${accountID}` : ''}` as const, }, REPORT_PARTICIPANTS: { route: 'r/:reportID/participants', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 4e7243d0eb2c..2b8abbb5011d 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', - REPORT_ATTACHMENTS: 'ReportAttachments', + ATTACHMENTS: 'Attachments', } as const; const SCREENS = { diff --git a/src/components/AttachmentContext.ts b/src/components/AttachmentContext.ts new file mode 100644 index 000000000000..4ed6bdc9084f --- /dev/null +++ b/src/components/AttachmentContext.ts @@ -0,0 +1,22 @@ +import {createContext} from 'react'; +import type {ValueOf} from 'type-fest'; +import type CONST from '@src/CONST'; + +type AttachmentContextProps = { + type?: ValueOf; + reportID?: string; + accountID?: number; +}; + +const AttachmentContext = createContext({ + type: undefined, + reportID: undefined, + accountID: undefined, +}); + +AttachmentContext.displayName = 'AttachmentContext'; + +export { + // eslint-disable-next-line import/prefer-default-export + AttachmentContext, +}; diff --git a/src/components/AttachmentModal.tsx b/src/components/AttachmentModal.tsx index af7f482198bb..19a9b845093d 100644 --- a/src/components/AttachmentModal.tsx +++ b/src/components/AttachmentModal.tsx @@ -5,6 +5,7 @@ import {GestureHandlerRootView} from 'react-native-gesture-handler'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import {useSharedValue} from 'react-native-reanimated'; +import type {ValueOf} from 'type-fest'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; @@ -101,6 +102,12 @@ type AttachmentModalProps = AttachmentModalOnyxProps & { /** The report that has this attachment */ report?: OnyxEntry | EmptyObject; + /** The type of the attachment */ + type?: ValueOf; + + /** If the attachment originates from a note, the accountID will represent the author of that note. */ + accountID?: number; + /** Optional callback to fire when we want to do something after modal show. */ onModalShow?: () => void; @@ -156,6 +163,8 @@ function AttachmentModal({ onModalClose = () => {}, isLoading = false, shouldShowNotFoundPage = false, + type = undefined, + accountID = undefined, }: AttachmentModalProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); @@ -519,6 +528,8 @@ function AttachmentModal({ )} {!isEmptyObject(report) && !isReceiptAttachment ? ( , reportActions?: OnyxEntry) { - const actions = [...(parentReportAction ? [parentReportAction] : []), ...ReportActionsUtils.getSortedReportActions(Object.values(reportActions ?? {}))]; +function extractAttachments( + type: ValueOf, + {reportID, accountID, parentReportAction, reportActions}: {reportID?: string; accountID?: number; parentReportAction?: OnyxEntry; reportActions?: OnyxEntry}, +) { + const report = getReport(reportID); + const privateNotes = report?.privateNotes; + const targetNote = privateNotes?.[Number(accountID)]?.note ?? ''; const attachments: Attachment[] = []; // We handle duplicate image sources by considering the first instance as original. Selecting any duplicate @@ -71,6 +78,14 @@ function extractAttachmentsFromReport(parentReportAction?: OnyxEntry { if (!ReportActionsUtils.shouldReportActionBeVisible(action, key) || ReportActionsUtils.isMoneyRequestAction(action)) { return; @@ -86,4 +101,4 @@ function extractAttachmentsFromReport(parentReportAction?: OnyxEntry(null); @@ -30,16 +31,21 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, useEffect(() => { const parentReportAction = report.parentReportActionID && parentReportActions ? parentReportActions[report.parentReportActionID] : undefined; - const attachmentsFromReport = extractAttachmentsFromReport(parentReportAction, reportActions); + let targetAttachments: Attachment[] = []; + if (type === CONST.ATTACHMENT_TYPE.NOTE && accountID) { + targetAttachments = extractAttachments(CONST.ATTACHMENT_TYPE.NOTE, {reportID: report.reportID, accountID}); + } else { + targetAttachments = extractAttachments(CONST.ATTACHMENT_TYPE.REPORT, {parentReportAction, reportActions}); + } - const initialPage = attachmentsFromReport.findIndex(compareImage); + const initialPage = targetAttachments.findIndex(compareImage); // Dismiss the modal when deleting an attachment during its display in preview. if (initialPage === -1 && attachments.find(compareImage)) { Navigation.dismissModal(); } else { setPage(initialPage); - setAttachments(attachmentsFromReport); + setAttachments(targetAttachments); // Update the download button visibility in the parent modal if (setDownloadButtonVisibility) { @@ -47,8 +53,8 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, } // Update the parent modal's state with the source and name from the mapped attachments - if (attachmentsFromReport[initialPage] !== undefined && onNavigate) { - onNavigate(attachmentsFromReport[initialPage]); + if (targetAttachments[initialPage] !== undefined && onNavigate) { + onNavigate(targetAttachments[initialPage]); } } // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/src/components/Attachments/AttachmentCarousel/index.tsx b/src/components/Attachments/AttachmentCarousel/index.tsx index 23b285faf10e..947569538d32 100644 --- a/src/components/Attachments/AttachmentCarousel/index.tsx +++ b/src/components/Attachments/AttachmentCarousel/index.tsx @@ -21,7 +21,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import CarouselActions from './CarouselActions'; import CarouselButtons from './CarouselButtons'; import CarouselItem from './CarouselItem'; -import extractAttachmentsFromReport from './extractAttachmentsFromReport'; +import extractAttachments from './extractAttachments'; import type {AttachmentCaraouselOnyxProps, AttachmentCarouselProps, UpdatePageProps} from './types'; import useCarouselArrows from './useCarouselArrows'; @@ -33,7 +33,7 @@ const viewabilityConfig = { const MIN_FLING_VELOCITY = 500; -function AttachmentCarousel({report, reportActions, parentReportActions, source, onNavigate, setDownloadButtonVisibility}: AttachmentCarouselProps) { +function AttachmentCarousel({report, reportActions, parentReportActions, source, onNavigate, setDownloadButtonVisibility, type, accountID}: AttachmentCarouselProps) { const theme = useTheme(); const {translate} = useLocalize(); const {isSmallScreenWidth, windowWidth} = useWindowDimensions(); @@ -57,9 +57,14 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, useEffect(() => { const parentReportAction = report.parentReportActionID && parentReportActions ? parentReportActions[report.parentReportActionID] : undefined; - const attachmentsFromReport = extractAttachmentsFromReport(parentReportAction, reportActions ?? undefined); + let targetAttachments: Attachment[] = []; + if (type === CONST.ATTACHMENT_TYPE.NOTE && accountID) { + targetAttachments = extractAttachments(CONST.ATTACHMENT_TYPE.NOTE, {reportID: report.reportID, accountID}); + } else { + targetAttachments = extractAttachments(CONST.ATTACHMENT_TYPE.REPORT, {parentReportAction, reportActions: reportActions ?? undefined}); + } - if (isEqual(attachments, attachmentsFromReport)) { + if (isEqual(attachments, targetAttachments)) { if (attachments.length === 0) { setPage(-1); setDownloadButtonVisibility?.(false); @@ -67,14 +72,14 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, return; } - const initialPage = attachmentsFromReport.findIndex(compareImage); + const initialPage = targetAttachments.findIndex(compareImage); // Dismiss the modal when deleting an attachment during its display in preview. if (initialPage === -1 && attachments.find(compareImage)) { Navigation.dismissModal(); } else { setPage(initialPage); - setAttachments(attachmentsFromReport); + setAttachments(targetAttachments); // Update the download button visibility in the parent modal if (setDownloadButtonVisibility) { @@ -82,11 +87,11 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, } // Update the parent modal's state with the source and name from the mapped attachments - if (attachmentsFromReport[initialPage] !== undefined && onNavigate) { - onNavigate(attachmentsFromReport[initialPage]); + if (targetAttachments[initialPage] !== undefined && onNavigate) { + onNavigate(targetAttachments[initialPage]); } } - }, [reportActions, parentReportActions, compareImage, report.parentReportActionID, attachments, setDownloadButtonVisibility, onNavigate]); + }, [reportActions, parentReportActions, compareImage, report.parentReportActionID, attachments, setDownloadButtonVisibility, onNavigate, accountID, report.reportID, type]); // Scroll position is affected when window width is resized, so we readjust it on width changes useEffect(() => { diff --git a/src/components/Attachments/AttachmentCarousel/types.ts b/src/components/Attachments/AttachmentCarousel/types.ts index 8ba3489a5fcf..d31ebbd328cd 100644 --- a/src/components/Attachments/AttachmentCarousel/types.ts +++ b/src/components/Attachments/AttachmentCarousel/types.ts @@ -1,6 +1,8 @@ import type {ViewToken} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; import type {Attachment, AttachmentSource} from '@components/Attachments/types'; +import type CONST from '@src/CONST'; import type {Report, ReportActions} from '@src/types/onyx'; type UpdatePageProps = { @@ -28,6 +30,12 @@ type AttachmentCarouselProps = AttachmentCaraouselOnyxProps & { /** The report currently being looked at */ report: Report; + /** The type of the attachment */ + type?: ValueOf; + + /** If the attachment originates from a note, the accountID will represent the author of that note. */ + accountID?: number; + /** A callback that is called when swipe-down-to-close gesture happens */ onClose: () => void; }; diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx index 79eaa30ee922..221731bbeef6 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx @@ -2,6 +2,7 @@ import React, {memo} from 'react'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import type {CustomRendererProps, TBlock} from 'react-native-render-html'; +import {AttachmentContext} from '@components/AttachmentContext'; import * as Expensicons from '@components/Icon/Expensicons'; import PressableWithoutFocus from '@components/Pressable/PressableWithoutFocus'; import {ShowContextMenuContext, showContextMenuForReport} from '@components/ShowContextMenuContext'; @@ -78,19 +79,29 @@ function ImageRenderer({tnode}: ImageRendererProps) { ) : ( {({anchor, report, action, checkIfContextMenuActive}) => ( - { - const route = ROUTES.REPORT_ATTACHMENTS.getRoute(report?.reportID ?? '', source); - Navigation.navigate(route); - }} - onLongPress={(event) => showContextMenuForReport(event, anchor, report?.reportID ?? '', action, checkIfContextMenuActive, ReportUtils.isArchivedRoom(report))} - shouldUseHapticsOnLongPress - accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON} - accessibilityLabel={translate('accessibilityHints.viewAttachment')} - > - {thumbnailImageComponent} - + + {({reportID, accountID, type}) => ( + { + if (!source || !type) { + return; + } + + if (reportID) { + const route = ROUTES.ATTACHMENTS?.getRoute(reportID, type, source, accountID); + Navigation.navigate(route); + } + }} + onLongPress={(event) => showContextMenuForReport(event, anchor, report?.reportID ?? '', action, checkIfContextMenuActive, ReportUtils.isArchivedRoom(report))} + shouldUseHapticsOnLongPress + accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON} + accessibilityLabel={translate('accessibilityHints.viewAttachment')} + > + {thumbnailImageComponent} + + )} + )} ); diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/VideoRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/VideoRenderer.tsx index 095dcb294857..52d14df46471 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/VideoRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/VideoRenderer.tsx @@ -35,7 +35,7 @@ function VideoRenderer({tnode, key}: VideoRendererProps) { videoDimensions={{width, height}} videoDuration={duration} onShowModalPress={() => { - const route = ROUTES.REPORT_ATTACHMENTS.getRoute(report?.reportID ?? '', sourceURL); + const route = ROUTES.ATTACHMENTS.getRoute(report?.reportID ?? '', CONST.ATTACHMENT_TYPE.REPORT, sourceURL); Navigation.navigate(route); }} /> diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index ad437f08523c..394211ce7a9c 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -307,7 +307,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie getComponent={loadConciergePage} /> ) case NAVIGATORS.ONBOARDING_MODAL_NAVIGATOR: case NAVIGATORS.FEATURE_TRANING_MODAL_NAVIGATOR: case SCREENS.NOT_FOUND: - case SCREENS.REPORT_ATTACHMENTS: + case SCREENS.ATTACHMENTS: case SCREENS.TRANSACTION_RECEIPT: case SCREENS.PROFILE_AVATAR: case SCREENS.WORKSPACE_AVATAR: diff --git a/src/libs/Navigation/dismissModalWithReport.ts b/src/libs/Navigation/dismissModalWithReport.ts index c0405c2c9da0..fe6fd288a2f9 100644 --- a/src/libs/Navigation/dismissModalWithReport.ts +++ b/src/libs/Navigation/dismissModalWithReport.ts @@ -37,7 +37,7 @@ function dismissModalWithReport(targetReport: Report | EmptyObject, navigationRe case NAVIGATORS.LEFT_MODAL_NAVIGATOR: case NAVIGATORS.RIGHT_MODAL_NAVIGATOR: case SCREENS.NOT_FOUND: - case SCREENS.REPORT_ATTACHMENTS: + case SCREENS.ATTACHMENTS: case SCREENS.TRANSACTION_RECEIPT: case SCREENS.PROFILE_AVATAR: case SCREENS.WORKSPACE_AVATAR: diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 4a629e323687..606b66d7bf0c 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -19,7 +19,7 @@ const config: LinkingOptions['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.REPORT_ATTACHMENTS]: ROUTES.REPORT_ATTACHMENTS.route, + [SCREENS.ATTACHMENTS]: ROUTES.ATTACHMENTS.route, [SCREENS.PROFILE_AVATAR]: ROUTES.PROFILE_AVATAR.route, [SCREENS.WORKSPACE_AVATAR]: ROUTES.WORKSPACE_AVATAR.route, [SCREENS.REPORT_AVATAR]: ROUTES.REPORT_AVATAR.route, diff --git a/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts b/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts index 4924465145b8..e6baacc1cea9 100644 --- a/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts +++ b/src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts @@ -4,6 +4,7 @@ import {isAnonymousUser} from '@libs/actions/Session'; import getIsNarrowLayout from '@libs/getIsNarrowLayout'; import type {BottomTabName, CentralPaneName, FullScreenName, NavigationPartialRoute, RootStackParamList} from '@libs/Navigation/types'; import {extractPolicyIDFromPath, getPathWithoutPolicyID} from '@libs/PolicyUtils'; +import CONST from '@src/CONST'; import NAVIGATORS from '@src/NAVIGATORS'; import SCREENS from '@src/SCREENS'; import CENTRAL_PANE_TO_RHP_MAPPING from './CENTRAL_PANE_TO_RHP_MAPPING'; @@ -162,8 +163,8 @@ function getAdaptedState(state: PartialState const lhpNavigator = state.routes.find((route) => route.name === NAVIGATORS.LEFT_MODAL_NAVIGATOR); const onboardingModalNavigator = state.routes.find((route) => route.name === NAVIGATORS.ONBOARDING_MODAL_NAVIGATOR); const welcomeVideoModalNavigator = state.routes.find((route) => route.name === NAVIGATORS.WELCOME_VIDEO_MODAL_NAVIGATOR); + const attachmentsScreen = state.routes.find((route) => route.name === SCREENS.ATTACHMENTS); const featureTrainingModalNavigator = state.routes.find((route) => route.name === NAVIGATORS.FEATURE_TRANING_MODAL_NAVIGATOR); - const reportAttachmentsScreen = state.routes.find((route) => route.name === SCREENS.REPORT_ATTACHMENTS); if (isNarrowLayout) { metainfo.isFullScreenNavigatorMandatory = false; @@ -302,25 +303,27 @@ function getAdaptedState(state: PartialState metainfo, }; } - if (reportAttachmentsScreen) { + if (attachmentsScreen) { // Routes // - matching bottom tab // - central pane (report screen) of the attachment // - found report attachments const routes = []; - const reportAttachments = reportAttachmentsScreen as Route<'ReportAttachments', RootStackParamList['ReportAttachments']>; + const reportAttachments = attachmentsScreen as Route<'Attachments', RootStackParamList['Attachments']>; - const matchingBottomTabRoute = getMatchingBottomTabRouteForState(state); - routes.push(createBottomTabNavigator(matchingBottomTabRoute, policyID)); - if (!isNarrowLayout) { - routes.push(createCentralPaneNavigator({name: SCREENS.REPORT, params: {reportID: reportAttachments.params?.reportID ?? ''}})); - } - routes.push(reportAttachments); + if (reportAttachments.params?.type === CONST.ATTACHMENT_TYPE.REPORT) { + const matchingBottomTabRoute = getMatchingBottomTabRouteForState(state); + routes.push(createBottomTabNavigator(matchingBottomTabRoute, policyID)); + if (!isNarrowLayout) { + routes.push(createCentralPaneNavigator({name: SCREENS.REPORT, params: {reportID: reportAttachments.params?.reportID ?? ''}})); + } + routes.push(reportAttachments); - return { - adaptedState: getRoutesWithIndex(routes), - metainfo, - }; + return { + adaptedState: getRoutesWithIndex(routes), + metainfo, + }; + } } // We need to make sure that this if only handles states where we deeplink to the bottom tab directly diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 3a7b8be32a01..29891c494d3f 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -875,9 +875,11 @@ type PublicScreensParamList = SharedScreensParamList & { type AuthScreensParamList = SharedScreensParamList & { [NAVIGATORS.CENTRAL_PANE_NAVIGATOR]: NavigatorScreenParams; [SCREENS.CONCIERGE]: undefined; - [SCREENS.REPORT_ATTACHMENTS]: { + [SCREENS.ATTACHMENTS]: { reportID: string; source: string; + type: ValueOf; + accountID: string; }; [SCREENS.PROFILE_AVATAR]: { accountID: string; diff --git a/src/pages/PrivateNotes/PrivateNotesListPage.tsx b/src/pages/PrivateNotes/PrivateNotesListPage.tsx index 1893f81da2fe..286c91d628fd 100644 --- a/src/pages/PrivateNotes/PrivateNotesListPage.tsx +++ b/src/pages/PrivateNotes/PrivateNotesListPage.tsx @@ -1,7 +1,8 @@ -import React, {useMemo} from 'react'; +import React, {useCallback, useMemo} from 'react'; import {withOnyx} from 'react-native-onyx'; import type {OnyxCollection} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; +import {AttachmentContext} from '@components/AttachmentContext'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -34,29 +35,34 @@ type NoteListItem = { brickRoadIndicator: ValueOf | undefined; note: string; disabled: boolean; + reportID: string; + accountID: string; }; function PrivateNotesListPage({report, personalDetailsList, session}: PrivateNotesListPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); + const getAttachmentValue = useCallback((item: NoteListItem) => ({reportID: item.reportID, accountID: Number(item.accountID), type: CONST.ATTACHMENT_TYPE.NOTE}), []); /** * Gets the menu item for each workspace */ function getMenuItem(item: NoteListItem) { return ( - + + + ); } @@ -68,6 +74,8 @@ function PrivateNotesListPage({report, personalDetailsList, session}: PrivateNot return Object.keys(report.privateNotes ?? {}).map((accountID: string) => { const privateNote = report.privateNotes?.[Number(accountID)]; return { + reportID: report.reportID, + accountID, title: Number(session?.accountID) === Number(accountID) ? translate('privateNotes.myNote') : personalDetailsList?.[accountID]?.login ?? '', action: () => Navigation.navigate(ROUTES.PRIVATE_NOTES_EDIT.getRoute(report.reportID, accountID)), brickRoadIndicator: privateNoteBrickRoadIndicator(Number(accountID)), diff --git a/src/pages/home/report/ReportActionItem.tsx b/src/pages/home/report/ReportActionItem.tsx index 9b08664a9048..4b248bf14131 100644 --- a/src/pages/home/report/ReportActionItem.tsx +++ b/src/pages/home/report/ReportActionItem.tsx @@ -5,6 +5,7 @@ import {InteractionManager, View} from 'react-native'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import type {Emoji} from '@assets/emojis/types'; +import {AttachmentContext} from '@components/AttachmentContext'; import Button from '@components/Button'; import DisplayNames from '@components/DisplayNames'; import Hoverable from '@components/Hoverable'; @@ -389,6 +390,8 @@ function ReportActionItem({ [report, action, toggleContextMenuFromActiveReportAction, transactionThreadReport], ); + const attachmentContextValue = useMemo(() => ({reportID: report.reportID, type: CONST.ATTACHMENT_TYPE.REPORT}), [report.reportID]); + const actionableItemButtons: ActionableItem[] = useMemo(() => { if (!isActionableWhisper && (!ReportActionsUtils.isActionableJoinRequest(action) || action.originalMessage.choice !== '')) { return []; @@ -632,50 +635,54 @@ function ReportActionItem({ !ReportActionsUtils.isPendingRemove(action); children = ( - {draftMessage === undefined ? ( - - - {hasBeenFlagged && ( - - )} - {/** + + {isHidden ? translate('moderation.revealMessage') : translate('moderation.hideMessage')} + + + )} + {/** These are the actionable buttons that appear at the bottom of a Concierge message for example: Invite a user mentioned but not a member of the room https://github.com/Expensify/App/issues/32741 */} - {actionableItemButtons.length > 0 && ( - - )} - - ) : ( - - )} + {actionableItemButtons.length > 0 && ( + + )} + + ) : ( + + )} + ); } diff --git a/src/pages/home/report/ReportAttachments.tsx b/src/pages/home/report/ReportAttachments.tsx index 82b49d1e260c..3ff472baee40 100644 --- a/src/pages/home/report/ReportAttachments.tsx +++ b/src/pages/home/report/ReportAttachments.tsx @@ -9,10 +9,12 @@ import * as ReportUtils from '@libs/ReportUtils'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -type ReportAttachmentsProps = StackScreenProps; +type ReportAttachmentsProps = StackScreenProps; function ReportAttachments({route}: ReportAttachmentsProps) { const reportID = route.params.reportID; + const type = route.params.type; + const accountID = route.params.accountID; const report = ReportUtils.getReport(reportID); // In native the imported images sources are of type number. Ref: https://reactnative.dev/docs/image#imagesource @@ -20,14 +22,16 @@ function ReportAttachments({route}: ReportAttachmentsProps) { const onCarouselAttachmentChange = useCallback( (attachment: Attachment) => { - const routeToNavigate = ROUTES.REPORT_ATTACHMENTS.getRoute(reportID, String(attachment.source)); + const routeToNavigate = ROUTES.ATTACHMENTS.getRoute(reportID, type, String(attachment.source), Number(accountID)); Navigation.navigate(routeToNavigate); }, - [reportID], + [reportID, accountID, type], ); return (