diff --git a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx index 57213dc1d3d2..c4bff718a887 100644 --- a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx +++ b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx @@ -6,10 +6,10 @@ import {ShowContextMenuContext, showContextMenuForReport} from '@components/Show import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; -import * as Browser from '@libs/Browser'; +import {isMobileSafari} from '@libs/Browser'; import fileDownload from '@libs/fileDownload'; -import * as ReportUtils from '@libs/ReportUtils'; -import * as Download from '@userActions/Download'; +import {isArchivedNonExpenseReport} from '@libs/ReportUtils'; +import {setDownload} from '@userActions/Download'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type AnchorForAttachmentsOnlyProps from './types'; @@ -26,7 +26,7 @@ function BaseAnchorForAttachmentsOnly({style, source = '', displayName = '', onP const sourceURLWithAuth = addEncryptedAuthTokenToURL(source); const sourceID = (source.match(CONST.REGEX.ATTACHMENT_ID) ?? [])[1]; - const [download] = useOnyx(`${ONYXKEYS.COLLECTION.DOWNLOAD}${sourceID}`); + const [download] = useOnyx(`${ONYXKEYS.COLLECTION.DOWNLOAD}${sourceID}`, {canBeMissing: true}); const {isOffline} = useNetwork(); const styles = useThemeStyles(); @@ -42,8 +42,8 @@ function BaseAnchorForAttachmentsOnly({style, source = '', displayName = '', onP if (isDownloading || isOffline || !sourceID) { return; } - Download.setDownload(sourceID, true); - fileDownload(sourceURLWithAuth, displayName, '', Browser.isMobileSafari()).then(() => Download.setDownload(sourceID, false)); + setDownload(sourceID, true); + fileDownload(sourceURLWithAuth, displayName, '', isMobileSafari()).then(() => setDownload(sourceID, false)); }} onPressIn={onPressIn} onPressOut={onPressOut} @@ -51,7 +51,14 @@ function BaseAnchorForAttachmentsOnly({style, source = '', displayName = '', onP if (isDisabled || !shouldDisplayContextMenu) { return; } - showContextMenuForReport(event, anchor, report?.reportID, action, checkIfContextMenuActive, ReportUtils.isArchivedNonExpenseReport(report, reportNameValuePairs)); + showContextMenuForReport( + event, + anchor, + report?.reportID, + action, + checkIfContextMenuActive, + isArchivedNonExpenseReport(report, !!reportNameValuePairs?.private_isArchived), + ); }} shouldUseHapticsOnLongPress accessibilityLabel={displayName} diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx index e650df1be650..d26bb0abffe3 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/ImageRenderer.tsx @@ -120,7 +120,14 @@ function ImageRenderer({tnode}: ImageRendererProps) { return; } return onShowContextMenu(() => - showContextMenuForReport(event, anchor, report?.reportID, action, checkIfContextMenuActive, isArchivedNonExpenseReport(report, reportNameValuePairs)), + showContextMenuForReport( + event, + anchor, + report?.reportID, + action, + checkIfContextMenuActive, + isArchivedNonExpenseReport(report, !!reportNameValuePairs?.private_isArchived), + ), ); }} isNested diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx index 71e711a93dcb..f2ab2cf62ca7 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/MentionUserRenderer.tsx @@ -78,7 +78,14 @@ function MentionUserRenderer({style, tnode, TDefaultRenderer, currentUserPersona return; } return onShowContextMenu(() => - showContextMenuForReport(event, anchor, report?.reportID, action, checkIfContextMenuActive, isArchivedNonExpenseReport(report, reportNameValuePairs)), + showContextMenuForReport( + event, + anchor, + report?.reportID, + action, + checkIfContextMenuActive, + isArchivedNonExpenseReport(report, !!reportNameValuePairs?.private_isArchived), + ), ); }} onPress={(event) => { diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer.tsx index 88b614365012..cfaa6598b325 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer.tsx @@ -62,7 +62,14 @@ function PreRenderer({TDefaultRenderer, onPressIn, onPressOut, onLongPress, ...d if (isDisabled || !shouldDisplayContextMenu) { return; } - return showContextMenuForReport(event, anchor, report?.reportID, action, checkIfContextMenuActive, isArchivedNonExpenseReport(report, reportNameValuePairs)); + return showContextMenuForReport( + event, + anchor, + report?.reportID, + action, + checkIfContextMenuActive, + isArchivedNonExpenseReport(report, !!reportNameValuePairs?.private_isArchived), + ); }); }} shouldUseHapticsOnLongPress diff --git a/src/components/ReportWelcomeText.tsx b/src/components/ReportWelcomeText.tsx index 04d661131488..82882b486eb2 100644 --- a/src/components/ReportWelcomeText.tsx +++ b/src/components/ReportWelcomeText.tsx @@ -49,10 +49,7 @@ function ReportWelcomeText({report, policy}: ReportWelcomeTextProps) { const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); const isPolicyExpenseChat = isPolicyExpenseChatReportUtils(report); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID || undefined}`, {canBeMissing: false}); - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID || undefined}`, {canBeMissing: true}); - const isArchivedRoom = isArchivedNonExpenseReport(report, reportNameValuePairs); const isChatRoom = isChatRoomReportUtils(report); const isSelfDM = isSelfDMReportUtils(report); const isInvoiceRoom = isInvoiceRoomReportUtils(report); @@ -64,6 +61,7 @@ function ReportWelcomeText({report, policy}: ReportWelcomeTextProps) { const displayNamesWithTooltips = getDisplayNamesWithTooltips(getPersonalDetailsForAccountIDs(participantAccountIDs, personalDetails), isMultipleParticipant); const isReportArchived = useReportIsArchived(report?.reportID); const welcomeMessage = SidebarUtils.getWelcomeMessage(report, policy, isReportArchived); + const isArchivedRoom = isArchivedNonExpenseReport(report, isReportArchived); const moneyRequestOptions = temporary_getMoneyRequestOptions(report, policy, participantAccountIDs); const policyName = getPolicyName({report}); diff --git a/src/components/VideoPlayerPreview/VideoPlayerThumbnail.tsx b/src/components/VideoPlayerPreview/VideoPlayerThumbnail.tsx index d7115921f58a..03b5e9340a9c 100644 --- a/src/components/VideoPlayerPreview/VideoPlayerThumbnail.tsx +++ b/src/components/VideoPlayerPreview/VideoPlayerThumbnail.tsx @@ -58,7 +58,14 @@ function VideoPlayerThumbnail({thumbnailUrl, onPress, accessibilityLabel, isDele return; } onShowContextMenu(() => { - showContextMenuForReport(event, anchor, report?.reportID, action, checkIfContextMenuActive, isArchivedNonExpenseReport(report, reportNameValuePairs)); + showContextMenuForReport( + event, + anchor, + report?.reportID, + action, + checkIfContextMenuActive, + isArchivedNonExpenseReport(report, !!reportNameValuePairs?.private_isArchived), + ); }); }} shouldUseHapticsOnLongPress diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index f2b51dfe6b2c..88e51099ef02 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -729,7 +729,7 @@ function getLastMessageTextForReport( const lastOriginalReportAction = reportID ? lastReportActions[reportID] : undefined; let lastMessageTextFromReport = ''; - if (isArchivedNonExpenseReport(report, reportNameValuePairs)) { + if (isArchivedNonExpenseReport(report, !!reportNameValuePairs?.private_isArchived)) { const archiveReason = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing (isClosedAction(lastOriginalReportAction) && getOriginalMessage(lastOriginalReportAction)?.reason) || CONST.REPORT.ARCHIVE_REASON.DEFAULT; @@ -977,7 +977,7 @@ function createOption(accountIDs: number[], personalDetails: OnyxInputOrEntry, transact * Whether the provided report is an archived room */ // eslint-disable-next-line @typescript-eslint/no-unused-vars -function isArchivedNonExpenseReport(report: OnyxInputOrEntry | SearchReport, reportNameValuePairs?: OnyxInputOrEntry): boolean { - return !(isExpenseReport(report) || isExpenseRequest(report)) && !!reportNameValuePairs?.private_isArchived; +function isArchivedNonExpenseReport(report: OnyxInputOrEntry | SearchReport, isReportArchived = false): boolean { + return isReportArchived && !(isExpenseReport(report) || isExpenseRequest(report)); } /** @@ -3273,7 +3273,12 @@ function getIcons( const reportNameValuePairs = allReportNameValuePair?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]; // This will get removed as part of https://github.com/Expensify/App/issues/59961 // eslint-disable-next-line deprecation/deprecation - if (isAdminRoom(report) || isAnnounceRoom(report) || isChatRoom(report) || (isArchivedNonExpenseReport(report, reportNameValuePairs) && !chatIncludesConcierge(report))) { + if ( + isAdminRoom(report) || + isAnnounceRoom(report) || + isChatRoom(report) || + (isArchivedNonExpenseReport(report, !!reportNameValuePairs?.private_isArchived) && !chatIncludesConcierge(report)) + ) { return getIconsForPolicyRoom(report, personalDetails, policy, invoiceReceiverPolicy); } if (isPolicyExpenseChat(report)) { @@ -3748,7 +3753,7 @@ function getPolicyExpenseChatName({ // of the account which was merged into the current user's account. Use the name of the policy as the name of the report. // This will get removed as part of https://github.com/Expensify/App/issues/59961 // eslint-disable-next-line deprecation/deprecation - if (isArchivedNonExpenseReport(report, getReportNameValuePairs(report?.reportID))) { + if (isArchivedNonExpenseReport(report, !!getReportNameValuePairs(report?.reportID)?.private_isArchived)) { const lastAction = getLastVisibleActionReportActionsUtils(report?.reportID); const archiveReason = isClosedAction(lastAction) ? getOriginalMessage(lastAction)?.reason : CONST.REPORT.ARCHIVE_REASON.DEFAULT; if (archiveReason === CONST.REPORT.ARCHIVE_REASON.ACCOUNT_MERGED && policyExpenseChatRole !== CONST.POLICY.ROLE.ADMIN) { @@ -5054,7 +5059,7 @@ function getReportNameInternal({ const parentReportActionMessage = getReportActionMessageReportUtils(parentReportAction); const isArchivedNonExpense = isArchivedNonExpenseReport( report, - reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID ?? String(CONST.DEFAULT_NUMBER_ID)}`], + !!reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID ?? String(CONST.DEFAULT_NUMBER_ID)}`]?.private_isArchived, ); if ( @@ -5387,7 +5392,7 @@ function getParentNavigationSubtitle(report: OnyxEntry, invoiceReceiverP // This will get removed as part of https://github.com/Expensify/App/issues/59961 // eslint-disable-next-line deprecation/deprecation - if (isArchivedNonExpenseReport(parentReport, getReportNameValuePairs(parentReport?.reportID))) { + if (isArchivedNonExpenseReport(parentReport, !!getReportNameValuePairs(parentReport?.reportID)?.private_isArchived)) { reportName += ` (${translateLocal('common.archived')})`; } @@ -7882,7 +7887,7 @@ function canSeeDefaultRoom(report: OnyxEntry, betas: OnyxEntry): // Include archived rooms // This will get removed as part of https://github.com/Expensify/App/issues/59961 // eslint-disable-next-line deprecation/deprecation - if (isArchivedNonExpenseReport(report, getReportNameValuePairs(report?.reportID))) { + if (isArchivedNonExpenseReport(report, !!getReportNameValuePairs(report?.reportID)?.private_isArchived)) { return true; } @@ -8261,7 +8266,7 @@ function reasonForReportToBeInOptionList({ // Archived reports should always be shown when in default (most recent) mode. This is because you should still be able to access and search for the chats to find them. // This will get removed as part of https://github.com/Expensify/App/issues/59961 // eslint-disable-next-line deprecation/deprecation - if (isInDefaultMode && isArchivedNonExpenseReport(report, getReportNameValuePairs(report?.reportID))) { + if (isInDefaultMode && isArchivedNonExpenseReport(report, !!getReportNameValuePairs(report?.reportID)?.private_isArchived)) { return CONST.REPORT_IN_LHN_REASONS.IS_ARCHIVED; } @@ -8442,7 +8447,7 @@ function shouldShowFlagComment(reportAction: OnyxInputOrEntry, rep canFlagReportAction(reportAction, report?.reportID) && // This will get removed as part of https://github.com/Expensify/App/issues/59961 // eslint-disable-next-line deprecation/deprecation - !isArchivedNonExpenseReport(report, getReportNameValuePairs(report?.reportID)) && + !isArchivedNonExpenseReport(report, !!getReportNameValuePairs(report?.reportID)?.private_isArchived) && !chatIncludesChronos(report) && !isConciergeChatReport(report) && reportAction?.actorAccountID !== CONST.ACCOUNT_ID.CONCIERGE @@ -8786,7 +8791,7 @@ function getWhisperDisplayNames(participantAccountIDs?: number[]): string | unde function shouldReportShowSubscript(report: OnyxEntry): boolean { // This will get removed as part of https://github.com/Expensify/App/issues/59961 // eslint-disable-next-line deprecation/deprecation - if (isArchivedNonExpenseReport(report, getReportNameValuePairs(report?.reportID)) && !isWorkspaceThread(report)) { + if (isArchivedNonExpenseReport(report, !!getReportNameValuePairs(report?.reportID)?.private_isArchived) && !isWorkspaceThread(report)) { return false; } @@ -8905,7 +8910,14 @@ function canUserPerformWriteAction(report: OnyxEntry) { // This will get removed as part of https://github.com/Expensify/App/issues/59961 // eslint-disable-next-line deprecation/deprecation const reportNameValuePairs = getReportNameValuePairs(report?.reportID); - return !isArchivedNonExpenseReport(report, reportNameValuePairs) && isEmptyObject(reportErrors) && report && isAllowedToComment(report) && !isAnonymousUser && canWriteInReport(report); + return ( + !isArchivedNonExpenseReport(report, !!reportNameValuePairs?.private_isArchived) && + isEmptyObject(reportErrors) && + report && + isAllowedToComment(report) && + !isAnonymousUser && + canWriteInReport(report) + ); } /** @@ -9015,12 +9027,11 @@ function canEditWriteCapability(report: OnyxEntry, policy: OnyxEntry, policy: OnyxEntry): boolean { - // This will get removed as part of https://github.com/Expensify/App/issues/59961 - // eslint-disable-next-line deprecation/deprecation - return isPolicyAdminPolicyUtils(policy) && !isArchivedNonExpenseReport(report, getReportNameValuePairs(report?.reportID)); +function canEditRoomVisibility(policy: OnyxEntry, isReportArchived: boolean): boolean { + return !isReportArchived && isPolicyAdminPolicyUtils(policy); } /** diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index 763e4b939482..15a4832845fd 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -390,7 +390,7 @@ function sortReportsToDisplayInLHN( errorReports.push(miniReport); } else if (hasValidDraftComment(report?.reportID)) { draftReports.push(miniReport); - } else if (isArchivedNonExpenseReport(report, rNVPs)) { + } else if (isArchivedNonExpenseReport(report, !!rNVPs?.private_isArchived)) { archivedReports.push(miniReport); } else { nonArchivedReports.push(miniReport); diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 4e8aac186183..33e168ebb6ff 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -167,7 +167,6 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail const [isDebugModeEnabled] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.isDebugModeEnabled, canBeMissing: false}); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false}); - const [isLastMemberLeavingGroupModalVisible, setIsLastMemberLeavingGroupModalVisible] = useState(false); const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false); const isPolicyAdmin = useMemo(() => isPolicyAdminUtil(policy), [policy]); @@ -178,7 +177,6 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail const isUserCreatedPolicyRoom = useMemo(() => isUserCreatedPolicyRoomUtil(report), [report]); const isDefaultRoom = useMemo(() => isDefaultRoomUtil(report), [report]); const isChatThread = useMemo(() => isChatThreadUtil(report), [report]); - const isArchivedRoom = useMemo(() => isArchivedNonExpenseReport(report, reportNameValuePairs), [report, reportNameValuePairs]); const isMoneyRequestReport = useMemo(() => isMoneyRequestReportUtil(report), [report]); const isMoneyRequest = useMemo(() => isMoneyRequestUtil(report), [report]); const isInvoiceReport = useMemo(() => isInvoiceReportUtil(report), [report]); @@ -197,6 +195,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail const isSingleTransactionView = isMoneyRequest || isTrackExpenseReport; const isSelfDMTrackExpenseReport = isTrackExpenseReport && isSelfDMUtil(parentReport); const isReportArchived = useReportIsArchived(report?.reportID); + const isArchivedRoom = useMemo(() => isArchivedNonExpenseReport(report, isReportArchived), [report, isReportArchived]); const shouldDisableRename = useMemo(() => shouldDisableRenameUtil(report, isReportArchived), [report, isReportArchived]); const parentNavigationSubtitleData = getParentNavigationSubtitle(report); const base62ReportID = getBase62ReportID(Number(report.reportID)); diff --git a/src/pages/ReportParticipantsPage.tsx b/src/pages/ReportParticipantsPage.tsx index 82333a6c1349..5ff92c2bc1ed 100755 --- a/src/pages/ReportParticipantsPage.tsx +++ b/src/pages/ReportParticipantsPage.tsx @@ -21,6 +21,7 @@ import useFilteredSelection from '@hooks/useFilteredSelection'; import useLocalize from '@hooks/useLocalize'; import useMobileSelectionMode from '@hooks/useMobileSelectionMode'; import useNetwork from '@hooks/useNetwork'; +import useReportIsArchived from '@hooks/useReportIsArchived'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useSearchBackPress from '@hooks/useSearchBackPress'; import useStyleUtils from '@hooks/useStyleUtils'; @@ -71,7 +72,6 @@ function ReportParticipantsPage({report, route}: ReportParticipantsPageProps) { const selectionListRef = useRef(null); const textInputRef = useRef(null); const [userSearchPhrase] = useOnyx(ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE, {canBeMissing: true}); - const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: false}); const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID}`, {canBeMissing: false}); const [reportAttributes] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {selector: (attributes) => attributes?.reports, canBeMissing: false}); const {selectionMode} = useMobileSelectionMode(); @@ -84,6 +84,7 @@ function ReportParticipantsPage({report, route}: ReportParticipantsPageProps) { const {isOffline} = useNetwork(); const canSelectMultiple = isGroupChat && isCurrentUserAdmin && (isSmallScreenWidth ? selectionMode?.isEnabled : true); const [searchValue, setSearchValue] = useState(''); + const isReportArchived = useReportIsArchived(report?.reportID); const {chatParticipants, personalDetailsParticipants} = useMemo( () => getReportPersonalDetailsParticipants(report, personalDetails, reportMetadata), @@ -396,7 +397,7 @@ function ReportParticipantsPage({report, route}: ReportParticipantsPageProps) { style={[styles.defaultModalContainer]} testID={ReportParticipantsPage.displayName} > - + { diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx index c902f0b44069..09fc2a881969 100755 --- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -203,7 +203,10 @@ function BaseReportActionContextMenu({ const areHoldRequirementsMet = !isInvoiceReport && isMoneyRequestOrReport && - !isArchivedNonExpenseReport(transactionThreadReportID ? childReport : parentReport, transactionThreadReportID ? childReportNameValuePairs : parentReportNameValuePairs); + !isArchivedNonExpenseReport( + transactionThreadReportID ? childReport : parentReport, + transactionThreadReportID ? !!childReportNameValuePairs?.private_isArchived : !!parentReportNameValuePairs?.private_isArchived, + ); const shouldEnableArrowNavigation = !isMini && (isVisible || shouldKeepOpen); let filteredContextMenuActions = ContextMenuActions.filter( diff --git a/src/pages/home/report/PureReportActionItem.tsx b/src/pages/home/report/PureReportActionItem.tsx index 065cf7cc6bcd..3b93fc9ddf26 100644 --- a/src/pages/home/report/PureReportActionItem.tsx +++ b/src/pages/home/report/PureReportActionItem.tsx @@ -1236,7 +1236,8 @@ function PureReportActionItem({ index={index} ref={composerTextInputRef} shouldDisableEmojiPicker={ - (chatIncludesConcierge(report) && isBlockedFromConcierge(blockedFromConcierge)) || isArchivedNonExpenseReport(report, reportNameValuePairs) + (chatIncludesConcierge(report) && isBlockedFromConcierge(blockedFromConcierge)) || + isArchivedNonExpenseReport(report, !!reportNameValuePairs?.private_isArchived) } isGroupPolicyReport={!!report?.policyID && report.policyID !== CONST.POLICY.ID_FAKE} /> diff --git a/src/pages/home/report/ReportActionsList.tsx b/src/pages/home/report/ReportActionsList.tsx index 35d4ba034b5c..5d32f5991166 100644 --- a/src/pages/home/report/ReportActionsList.tsx +++ b/src/pages/home/report/ReportActionsList.tsx @@ -14,6 +14,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' import useLocalize from '@hooks/useLocalize'; import useNetworkWithOfflineStatus from '@hooks/useNetworkWithOfflineStatus'; import usePrevious from '@hooks/usePrevious'; +import useReportIsArchived from '@hooks/useReportIsArchived'; import useReportScrollManager from '@hooks/useReportScrollManager'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -171,9 +172,9 @@ function ReportActionsList({ const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false}); const [transactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: true}); - const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.accountID, canBeMissing: true}); const participantsContext = useContext(PersonalDetailsContext); + const isReportArchived = useReportIsArchived(report?.reportID); const [isScrollToBottomEnabled, setIsScrollToBottomEnabled] = useState(false); @@ -555,7 +556,7 @@ function ReportActionsList({ const newMessageTimeReference = lastMessageTime.current && report.lastReadTime && lastMessageTime.current > report.lastReadTime ? userActiveSince.current : report.lastReadTime; lastMessageTime.current = null; - const isArchivedReport = isArchivedNonExpenseReport(report, reportNameValuePairs); + const isArchivedReport = isArchivedNonExpenseReport(report, isReportArchived); const hasNewMessagesInView = scrollingVerticalOffset.current < CONST.REPORT.ACTIONS.ACTION_VISIBLE_THRESHOLD; const hasUnreadReportAction = sortedVisibleReportActions.some( (reportAction) => @@ -628,8 +629,8 @@ function ReportActionsList({ // Native mobile does not render updates flatlist the changes even though component did update called. // To notify there something changes we can use extraData prop to flatlist const extraData = useMemo( - () => [shouldUseNarrowLayout ? unreadMarkerReportActionID : undefined, isArchivedNonExpenseReport(report, reportNameValuePairs)], - [unreadMarkerReportActionID, shouldUseNarrowLayout, report, reportNameValuePairs], + () => [shouldUseNarrowLayout ? unreadMarkerReportActionID : undefined, isArchivedNonExpenseReport(report, isReportArchived)], + [unreadMarkerReportActionID, shouldUseNarrowLayout, report, isReportArchived], ); const hideComposer = !canUserPerformWriteAction(report); const shouldShowReportRecipientLocalTime = canShowReportRecipientLocalTime(personalDetailsList, report, currentUserPersonalDetails.accountID) && !isComposerFullSize; diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index 03fcea1e72e6..320c6688ab8a 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -14,6 +14,7 @@ import {usePersonalDetails} from '@components/OnyxProvider'; import SwipeableView from '@components/SwipeableView'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; +import useReportIsArchived from '@hooks/useReportIsArchived'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; @@ -102,10 +103,9 @@ function ReportFooter({ }, canBeMissing: true, }); - const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); - + const isReportArchived = useReportIsArchived(report?.reportID); const chatFooterStyles = {...styles.chatFooter, minHeight: !isOffline ? CONST.CHAT_FOOTER_MIN_HEIGHT : 0}; - const isArchivedRoom = isArchivedNonExpenseReport(report, reportNameValuePairs); + const isArchivedRoom = isArchivedNonExpenseReport(report, isReportArchived); const isSmallSizeLayout = windowWidth - (shouldUseNarrowLayout ? 0 : variables.sideBarWithLHBWidth) < variables.anonymousReportFooterBreakpoint; diff --git a/src/pages/settings/Report/NotificationPreferencePage.tsx b/src/pages/settings/Report/NotificationPreferencePage.tsx index 434505ad473e..62df62907ccd 100644 --- a/src/pages/settings/Report/NotificationPreferencePage.tsx +++ b/src/pages/settings/Report/NotificationPreferencePage.tsx @@ -1,6 +1,5 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback} from 'react'; -import {useOnyx} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -8,14 +7,21 @@ import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; +import useReportIsArchived from '@hooks/useReportIsArchived'; import type {PlatformStackRouteProp, PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; -import * as ReportUtils from '@libs/ReportUtils'; +import { + getReportNotificationPreference, + goBackToDetailsPage, + isArchivedNonExpenseReport, + isHiddenForCurrentUser, + isMoneyRequestReport as isMoneyRequestReportUtils, + isSelfDM, +} from '@libs/ReportUtils'; import type {ReportSettingsNavigatorParamList} from '@navigation/types'; import withReportOrNotFound from '@pages/home/report/withReportOrNotFound'; import type {WithReportOrNotFoundProps} from '@pages/home/report/withReportOrNotFound'; -import * as ReportActions from '@userActions/Report'; +import {updateNotificationPreference as updateNotificationPreferenceReportActionUtils} from '@userActions/Report'; import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; type NotificationPreferencePageProps = WithReportOrNotFoundProps & PlatformStackScreenProps; @@ -23,15 +29,13 @@ type NotificationPreferencePageProps = WithReportOrNotFoundProps & PlatformStack function NotificationPreferencePage({report}: NotificationPreferencePageProps) { const route = useRoute>(); const {translate} = useLocalize(); - const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID || undefined}`); - const isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report); - const currentNotificationPreference = ReportUtils.getReportNotificationPreference(report); + const isMoneyRequestReport = isMoneyRequestReportUtils(report); + const currentNotificationPreference = getReportNotificationPreference(report); + const isReportArchived = useReportIsArchived(report?.reportID); const shouldDisableNotificationPreferences = - ReportUtils.isArchivedNonExpenseReport(report, reportNameValuePairs) || - ReportUtils.isSelfDM(report) || - (!isMoneyRequestReport && ReportUtils.isHiddenForCurrentUser(currentNotificationPreference)); + isArchivedNonExpenseReport(report, isReportArchived) || isSelfDM(report) || (!isMoneyRequestReport && isHiddenForCurrentUser(currentNotificationPreference)); const notificationPreferenceOptions = Object.values(CONST.REPORT.NOTIFICATION_PREFERENCE) - .filter((pref) => !ReportUtils.isHiddenForCurrentUser(pref)) + .filter((pref) => !isHiddenForCurrentUser(pref)) .map((preference) => ({ value: preference, text: translate(`notificationPreferencesPage.notificationPreferences.${preference}`), @@ -40,12 +44,12 @@ function NotificationPreferencePage({report}: NotificationPreferencePageProps) { })); const goBack = useCallback(() => { - ReportUtils.goBackToDetailsPage(report, route.params.backTo); + goBackToDetailsPage(report, route.params.backTo); }, [report, route.params.backTo]); const updateNotificationPreference = useCallback( (value: ValueOf) => { - ReportActions.updateNotificationPreference(report.reportID, currentNotificationPreference, value, undefined, undefined); + updateNotificationPreferenceReportActionUtils(report.reportID, currentNotificationPreference, value, undefined, undefined); goBack(); }, [report.reportID, currentNotificationPreference, goBack], diff --git a/src/pages/settings/Report/ReportSettingsPage.tsx b/src/pages/settings/Report/ReportSettingsPage.tsx index 752e0e2bc4e7..082e6211571d 100644 --- a/src/pages/settings/Report/ReportSettingsPage.tsx +++ b/src/pages/settings/Report/ReportSettingsPage.tsx @@ -1,6 +1,5 @@ import React, {useMemo} from 'react'; import {View} from 'react-native'; -import {useOnyx} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; @@ -8,6 +7,7 @@ import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; +import useReportIsArchived from '@hooks/useReportIsArchived'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; @@ -16,17 +16,15 @@ import { canEditWriteCapability, getReportNotificationPreference, isAdminRoom, - isArchivedNonExpenseReport, - isArchivedReport, + isArchivedNonExpenseReport as isArchivedNonExpenseReportUtils, isHiddenForCurrentUser, - isMoneyRequestReport as isMoneyRequestReportUtil, + isMoneyRequestReport as isMoneyRequestReportUtils, isSelfDM, } from '@libs/ReportUtils'; import type {ReportSettingsNavigatorParamList} from '@navigation/types'; import withReportOrNotFound from '@pages/home/report/withReportOrNotFound'; import type {WithReportOrNotFoundProps} from '@pages/home/report/withReportOrNotFound'; 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'; @@ -38,23 +36,21 @@ function ReportSettingsPage({report, policy, route}: ReportSettingsPageProps) { const reportID = report?.reportID; const styles = useThemeStyles(); const {translate} = useLocalize(); - const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`, {canBeMissing: true}); + const isReportArchived = useReportIsArchived(reportID); + const isArchivedNonExpenseReport = isArchivedNonExpenseReportUtils(report, isReportArchived); // The workspace the report is on, null if the user isn't a member of the workspace const linkedWorkspace = useMemo(() => (report?.policyID && policy?.id === report?.policyID ? policy : undefined), [policy, report?.policyID]); - const isMoneyRequestReport = isMoneyRequestReportUtil(report); - - const shouldDisableSettings = isEmptyObject(report) || isArchivedNonExpenseReport(report, reportNameValuePairs) || isSelfDM(report); + const isMoneyRequestReport = isMoneyRequestReportUtils(report); + const shouldDisableSettings = isArchivedNonExpenseReport || isEmptyObject(report) || isSelfDM(report); const notificationPreferenceValue = getReportNotificationPreference(report); const notificationPreference = notificationPreferenceValue && !isHiddenForCurrentUser(notificationPreferenceValue) ? translate(`notificationPreferencesPage.notificationPreferences.${notificationPreferenceValue}`) : ''; const writeCapability = isAdminRoom(report) ? CONST.REPORT.WRITE_CAPABILITIES.ADMINS : (report?.writeCapability ?? CONST.REPORT.WRITE_CAPABILITIES.ALL); - const writeCapabilityText = translate(`writeCapabilityPage.writeCapability.${writeCapability}`); - const isReportArchived = isArchivedReport(reportNameValuePairs); const shouldAllowWriteCapabilityEditing = useMemo(() => canEditWriteCapability(report, linkedWorkspace, isReportArchived), [report, linkedWorkspace, isReportArchived]); - const shouldAllowChangeVisibility = useMemo(() => canEditRoomVisibility(report, linkedWorkspace), [report, linkedWorkspace]); + const shouldAllowChangeVisibility = useMemo(() => canEditRoomVisibility(linkedWorkspace, isArchivedNonExpenseReport), [linkedWorkspace, isArchivedNonExpenseReport]); const shouldShowNotificationPref = !isMoneyRequestReport && !isHiddenForCurrentUser(notificationPreferenceValue); diff --git a/src/pages/settings/Report/VisibilityPage.tsx b/src/pages/settings/Report/VisibilityPage.tsx index 560b96383a57..d6ba63bc29ed 100644 --- a/src/pages/settings/Report/VisibilityPage.tsx +++ b/src/pages/settings/Report/VisibilityPage.tsx @@ -1,6 +1,5 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo, useRef, useState} from 'react'; -import {useOnyx} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import ConfirmModal from '@components/ConfirmModal'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -8,14 +7,14 @@ import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; +import useReportIsArchived from '@hooks/useReportIsArchived'; import type {PlatformStackRouteProp, PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {ReportSettingsNavigatorParamList} from '@libs/Navigation/types'; -import * as ReportUtils from '@libs/ReportUtils'; +import {goBackToDetailsPage, isArchivedNonExpenseReport} from '@libs/ReportUtils'; import type {WithReportOrNotFoundProps} from '@pages/home/report/withReportOrNotFound'; import withReportOrNotFound from '@pages/home/report/withReportOrNotFound'; -import * as ReportActions from '@userActions/Report'; +import {updateRoomVisibility} from '@userActions/Report'; import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type {RoomVisibility} from '@src/types/onyx/Report'; @@ -24,10 +23,11 @@ type VisibilityProps = WithReportOrNotFoundProps & PlatformStackScreenProps>(); const [showConfirmModal, setShowConfirmModal] = useState(false); - const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID || undefined}`); const shouldGoBackToDetailsPage = useRef(false); - const shouldDisableVisibility = ReportUtils.isArchivedNonExpenseReport(report, reportNameValuePairs); + const isReportArchived = useReportIsArchived(report?.reportID); + const shouldDisableVisibility = isArchivedNonExpenseReport(report, isReportArchived); + const {translate} = useLocalize(); const visibilityOptions = useMemo( @@ -45,7 +45,7 @@ function VisibilityPage({report}: VisibilityProps) { ); const goBack = useCallback(() => { - ReportUtils.goBackToDetailsPage(report, route.params.backTo); + goBackToDetailsPage(report, route.params.backTo); }, [report, route.params.backTo]); const changeVisibility = useCallback( @@ -53,7 +53,7 @@ function VisibilityPage({report}: VisibilityProps) { if (!report) { return; } - ReportActions.updateRoomVisibility(report.reportID, report.visibility, newVisibility); + updateRoomVisibility(report.reportID, report.visibility, newVisibility); if (showConfirmModal) { shouldGoBackToDetailsPage.current = true; } else { diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index fb1daf290d35..a93aca1944b9 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -22,6 +22,7 @@ import { canDeleteReportAction, canDeleteTransaction, canEditReportDescription, + canEditRoomVisibility, canEditWriteCapability, canHoldUnholdReportAction, findLastAccessedReport, @@ -2567,6 +2568,20 @@ describe('ReportUtils', () => { }); }); + describe('canEditRoomVisibility', () => { + it('should return true for policy rooms that are not archived and the user is an admin', () => { + expect(canEditRoomVisibility({...policy, role: CONST.POLICY.ROLE.ADMIN}, false)).toBeTruthy(); + expect(canEditRoomVisibility({...policy, role: CONST.POLICY.ROLE.AUDITOR}, false)).toBeFalsy(); + expect(canEditRoomVisibility({...policy, role: CONST.POLICY.ROLE.USER}, false)).toBeFalsy(); + }); + + it('should return false for policy rooms that are archived regardless of the policy role', () => { + expect(canEditRoomVisibility({...policy, role: CONST.POLICY.ROLE.ADMIN}, true)).toBeFalsy(); + expect(canEditRoomVisibility({...policy, role: CONST.POLICY.ROLE.AUDITOR}, true)).toBeFalsy(); + expect(canEditRoomVisibility({...policy, role: CONST.POLICY.ROLE.USER}, true)).toBeFalsy(); + }); + }); + describe('canDeleteReportAction', () => { it('should return false for delete button visibility if transaction is not allowed to be deleted', () => { const parentReport = LHNTestUtils.getFakeReport();