From 588f7ca0cee50a1e30915ad54b9dd82264b31c48 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 11 Mar 2025 09:36:35 +0100 Subject: [PATCH 1/6] Remove reportID param from dismissModal function --- contributingGuides/NAVIGATION.md | 2 +- .../GetStateForActionHandlers.ts | 26 +++++++- .../RootStackRouter.ts | 19 +++++- .../createRootStackNavigator/types.ts | 3 + src/libs/Navigation/Navigation.ts | 42 +++++++++---- src/libs/actions/IOU.ts | 60 +++++++++++++++---- src/libs/actions/Report.ts | 10 +++- src/libs/actions/Task.ts | 2 +- src/libs/actions/TeachersUnite.ts | 4 +- src/pages/AddPersonalBankAccountPage.tsx | 2 +- src/pages/EditReportFieldPage.tsx | 12 +++- .../AddBankAccount/AddBankAccount.tsx | 2 +- src/pages/NewChatPage.tsx | 2 +- src/pages/RoomInvitePage.tsx | 2 +- .../TransactionDuplicate/Confirmation.tsx | 2 +- src/pages/TransactionReceiptPage.tsx | 2 +- src/pages/tasks/TaskAssigneeSelectorModal.tsx | 4 +- src/pages/tasks/TaskDescriptionPage.tsx | 4 +- src/pages/tasks/TaskTitlePage.tsx | 4 +- src/pages/workspace/WorkspaceNewRoomPage.tsx | 2 +- .../workspace/WorkspaceOverviewSharePage.tsx | 2 +- 21 files changed, 162 insertions(+), 46 deletions(-) diff --git a/contributingGuides/NAVIGATION.md b/contributingGuides/NAVIGATION.md index f0db6723b4e5..20d284b8e5a7 100644 --- a/contributingGuides/NAVIGATION.md +++ b/contributingGuides/NAVIGATION.md @@ -34,7 +34,7 @@ When creating RHP flows, you have to remember a couple of things: - We use a custom `goBack` function to handle the browser and the `react-navigation` history stack. Under the hood, it resolves to either replacing the current screen with the one we navigate to (deeplinking scenario) or just going back if we reached the current page by navigating in App (pops the screen). It ensures the requested behaviors on web, which is navigating back to the place from where you deeplinked when going into the RHP flow by it. -- If you want to navigate to a certain report after completing a flow related to it, e.g. `RequestMoney` flow with a certain group/user, you should use `Navigation.dismissModal` with this `reportID` as an argument. If, in the future, we would like to navigate to something different than the report after such flows, the API should be rather easy to change. We do it like that in order to replace the RHP flow with the new report instead of pushing it, so pressing the back button does not navigate back to the ending page of the flow. If we were to navigate to the same report, we just pop the RHP modal. +- If you want to navigate to a certain report after completing a flow related to it, e.g. `RequestMoney` flow with a certain group/user, you should use `Navigation.dismissModalWithReport` with this `reportID` as an argument. If, in the future, we would like to navigate to something different than the report after such flows, the API should be rather easy to change. We do it like that in order to replace the RHP flow with the new report instead of pushing it, so pressing the back button does not navigate back to the ending page of the flow. If we were to navigate to the same report, we just pop the RHP modal. ### Example of usage diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts index bb796c74eee1..1965d7a1bc0c 100644 --- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts +++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts @@ -7,7 +7,7 @@ import type {RootNavigatorParamList, State} from '@libs/Navigation/types'; import * as SearchQueryUtils from '@libs/SearchQueryUtils'; import NAVIGATORS from '@src/NAVIGATORS'; import SCREENS from '@src/SCREENS'; -import type {OpenWorkspaceSplitActionType, PushActionType, SwitchPolicyIdActionType} from './types'; +import type {OpenWorkspaceSplitActionType, PushActionType, ReplaceActionType, SwitchPolicyIdActionType} from './types'; const MODAL_ROUTES_TO_DISMISS: string[] = [ NAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR, @@ -237,6 +237,29 @@ function handlePushSearchPageAction( return stackRouter.getStateForAction(state, updatedAction, configOptions); } +function handleReplaceReportsSplitNavigatorAction( + state: StackNavigationState, + action: ReplaceActionType, + configOptions: RouterConfigOptions, + stackRouter: Router, CommonActions.Action | StackActionType>, +) { + const stateWithReportsSplitNavigator = stackRouter.getStateForAction(state, action, configOptions); + + if (!stateWithReportsSplitNavigator) { + Log.hmmm('[handleReplaceReportsSplitNavigatorAction] ReportsSplitNavigator has not been found in the navigation state.'); + return null; + } + + const lastReportsSplitNavigator = stateWithReportsSplitNavigator.routes.at(-1); + + // ReportScreen should always be opened with an animation when replacing the navigator + if (lastReportsSplitNavigator?.key) { + reportsSplitsWithEnteringAnimation.add(lastReportsSplitNavigator.key); + } + + return stateWithReportsSplitNavigator; +} + /** * Handles the DISMISS_MODAL action. * If the last route is a modal route, it has to be popped from the navigation stack. @@ -275,6 +298,7 @@ export { handleDismissModalAction, handlePushReportSplitAction, handlePushSearchPageAction, + handleReplaceReportsSplitNavigatorAction, handleSwitchPolicyIDAction, handleSwitchPolicyIDFromSearchAction, handleNavigatingToModalFromModal, diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts index fcaad4ae232a..0e9b4b2c3669 100644 --- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts +++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts @@ -14,10 +14,19 @@ import { handleOpenWorkspaceSplitAction, handlePushReportSplitAction, handlePushSearchPageAction, + handleReplaceReportsSplitNavigatorAction, handleSwitchPolicyIDAction, } from './GetStateForActionHandlers'; import syncBrowserHistory from './syncBrowserHistory'; -import type {DismissModalActionType, OpenWorkspaceSplitActionType, PushActionType, RootStackNavigatorAction, RootStackNavigatorRouterOptions, SwitchPolicyIdActionType} from './types'; +import type { + DismissModalActionType, + OpenWorkspaceSplitActionType, + PushActionType, + ReplaceActionType, + RootStackNavigatorAction, + RootStackNavigatorRouterOptions, + SwitchPolicyIdActionType, +} from './types'; function isOpenWorkspaceSplitAction(action: RootStackNavigatorAction): action is OpenWorkspaceSplitActionType { return action.type === CONST.NAVIGATION.ACTION_TYPE.OPEN_WORKSPACE_SPLIT; @@ -31,6 +40,10 @@ function isPushAction(action: RootStackNavigatorAction): action is PushActionTyp return action.type === CONST.NAVIGATION.ACTION_TYPE.PUSH; } +function isReplaceAction(action: RootStackNavigatorAction): action is ReplaceActionType { + return action.type === CONST.NAVIGATION.ACTION_TYPE.REPLACE; +} + function isDismissModalAction(action: RootStackNavigatorAction): action is DismissModalActionType { return action.type === CONST.NAVIGATION.ACTION_TYPE.DISMISS_MODAL; } @@ -82,6 +95,10 @@ function RootStackRouter(options: RootStackNavigatorRouterOptions) { return handleDismissModalAction(state, configOptions, stackRouter); } + if (isReplaceAction(action) && action.payload.name === NAVIGATORS.REPORTS_SPLIT_NAVIGATOR) { + return handleReplaceReportsSplitNavigatorAction(state, action, configOptions, stackRouter); + } + if (isPushAction(action)) { if (action.payload.name === NAVIGATORS.REPORTS_SPLIT_NAVIGATOR) { return handlePushReportSplitAction(state, action, configOptions, stackRouter, setActiveWorkspaceID); diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/types.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/types.ts index 6dae82db35b5..67d69f90a205 100644 --- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/types.ts +++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/types.ts @@ -29,6 +29,8 @@ type SwitchPolicyIdActionType = RootStackNavigatorActionType & { type PushActionType = StackActionType & {type: typeof CONST.NAVIGATION.ACTION_TYPE.PUSH}; +type ReplaceActionType = StackActionType & {type: typeof CONST.NAVIGATION.ACTION_TYPE.REPLACE}; + type DismissModalActionType = RootStackNavigatorActionType & { type: typeof CONST.NAVIGATION.ACTION_TYPE.DISMISS_MODAL; }; @@ -49,6 +51,7 @@ export type { OpenWorkspaceSplitActionType, SwitchPolicyIdActionType, PushActionType, + ReplaceActionType, DismissModalActionType, RootStackNavigatorAction, RootStackNavigatorActionType, diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts index 26399ca62664..22843600cd8e 100644 --- a/src/libs/Navigation/Navigation.ts +++ b/src/libs/Navigation/Navigation.ts @@ -24,6 +24,7 @@ import originalCloseRHPFlow from './helpers/closeRHPFlow'; import getPolicyIDFromState from './helpers/getPolicyIDFromState'; import getStateFromPath from './helpers/getStateFromPath'; import getTopmostReportParams from './helpers/getTopmostReportParams'; +import {isFullScreenName} from './helpers/isNavigatorName'; import isReportOpenInRHP from './helpers/isReportOpenInRHP'; import linkTo from './helpers/linkTo'; import getMinimalAction from './helpers/linkTo/getMinimalAction'; @@ -468,20 +469,20 @@ function waitForProtectedRoutes() { }); } -type NavigateToReportWithPolicyCheckPayload = {report?: OnyxEntry; reportID?: string; reportActionID?: string; referrer?: string; policyIDToCheck?: string}; +type NavigateToReportWithPolicyCheckPayload = {report?: OnyxEntry; reportID?: string; reportActionID?: string; referrer?: string; policyIDToCheck?: string; forceReplace?: boolean}; /** * Navigates to a report passed as a param (as an id or report object) and checks whether the target object belongs to the currently selected workspace. * If not, the current workspace is set to global. */ -function navigateToReportWithPolicyCheck({report, reportID, reportActionID, referrer, policyIDToCheck}: NavigateToReportWithPolicyCheckPayload, ref = navigationRef) { +function navigateToReportWithPolicyCheck({report, reportID, reportActionID, referrer, policyIDToCheck}: NavigateToReportWithPolicyCheckPayload, forceReplace = false, ref = navigationRef) { const targetReport = reportID ? {reportID, ...allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]} : report; const policyID = policyIDToCheck ?? getPolicyIDFromState(navigationRef.getRootState() as State); const policyMemberAccountIDs = getPolicyEmployeeAccountIDs(policyID); const shouldOpenAllWorkspace = isEmptyObject(targetReport) ? true : !doesReportBelongToWorkspace(targetReport, policyMemberAccountIDs, policyID); if ((shouldOpenAllWorkspace && !policyID) || !shouldOpenAllWorkspace) { - linkTo(ref.current, ROUTES.REPORT_WITH_ID.getRoute(targetReport?.reportID, reportActionID, referrer)); + linkTo(ref.current, ROUTES.REPORT_WITH_ID.getRoute(targetReport?.reportID, reportActionID, referrer), {forceReplace: !!forceReplace}); return; } @@ -497,6 +498,17 @@ function navigateToReportWithPolicyCheck({report, reportID, reportActionID, refe params.referrer = referrer; } + if (forceReplace) { + ref.dispatch( + StackActions.replace(NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, { + policyID: undefined, + screen: SCREENS.REPORT, + params, + }), + ); + return; + } + ref.dispatch( StackActions.push(NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, { policyID: undefined, @@ -527,23 +539,31 @@ function getReportRouteByID(reportID?: string, routes: NavigationRoute[] = navig /** * Closes the modal navigator (RHP, LHP, onboarding). */ -const dismissModal = (reportID?: string, ref = navigationRef) => { +const dismissModal = (ref = navigationRef) => { isNavigationReady().then(() => { ref.dispatch({type: CONST.NAVIGATION.ACTION_TYPE.DISMISS_MODAL}); - if (!reportID) { - return; - } - navigateToReportWithPolicyCheck({reportID}); }); }; /** * Dismisses the modal and opens the given report. */ -const dismissModalWithReport = (report: OnyxEntry, ref = navigationRef) => { +const dismissModalWithReport = (navigateToReportPayload: NavigateToReportWithPolicyCheckPayload, ref = navigationRef) => { isNavigationReady().then(() => { - ref.dispatch({type: CONST.NAVIGATION.ACTION_TYPE.DISMISS_MODAL}); - navigateToReportWithPolicyCheck({report}); + if (getIsNarrowLayout()) { + const topmostReportID = getTopmostReportId(); + const areReportsIDsDefined = !!topmostReportID && !!navigateToReportPayload.reportID; + const isReportsSplitTopmostFullScreen = ref.getRootState().routes.findLast((route) => isFullScreenName(route.name))?.name === NAVIGATORS.REPORTS_SPLIT_NAVIGATOR; + if (topmostReportID === navigateToReportPayload.reportID && areReportsIDsDefined && isReportsSplitTopmostFullScreen) { + dismissModal(); + return; + } + const forceReplace = true; + navigateToReportWithPolicyCheck(navigateToReportPayload, forceReplace); + return; + } + dismissModal(); + navigateToReportWithPolicyCheck(navigateToReportPayload); }); }; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index b9d1ce96e6a4..50c3c69c9e36 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -4717,7 +4717,11 @@ function requestMoney(requestMoneyInformation: RequestMoneyInformation) { } InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); - Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : activeReportID); + if (isSearchTopmostFullScreenRoute()) { + Navigation.dismissModal(); + } else { + Navigation.dismissModalWithReport({reportID: activeReportID}); + } const trackReport = Navigation.getReportRouteByID(linkedTrackedExpenseReportAction?.childReportID); if (trackReport?.key) { @@ -4801,7 +4805,12 @@ function submitPerDiemExpense(submitPerDiemExpenseInformation: PerDiemExpenseInf API.write(WRITE_COMMANDS.CREATE_PER_DIEM_REQUEST, parameters, onyxData); InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); - Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : activeReportID); + if (isSearchTopmostFullScreenRoute()) { + Navigation.dismissModal(); + } else { + Navigation.dismissModalWithReport({reportID: activeReportID}); + } + if (activeReportID) { notifyNewAction(activeReportID, payeeAccountID); } @@ -4868,7 +4877,7 @@ function sendInvoice( if (isSearchTopmostFullScreenRoute()) { Navigation.dismissModal(); } else { - Navigation.dismissModalWithReport(invoiceRoom); + Navigation.dismissModalWithReport({report: invoiceRoom}); } notifyNewAction(invoiceRoom.reportID, receiver.accountID); @@ -5094,7 +5103,11 @@ function trackExpense(params: CreateTrackExpenseParams) { } } InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); - Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : activeReportID); + if (isSearchTopmostFullScreenRoute()) { + Navigation.dismissModal(); + } else { + Navigation.dismissModalWithReport({reportID: activeReportID}); + } if (action === CONST.IOU.ACTION.SHARE) { if (isSearchTopmostFullScreenRoute() && activeReportID) { @@ -5676,7 +5689,12 @@ function splitBill({ API.write(WRITE_COMMANDS.SPLIT_BILL, parameters, onyxData); InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); - Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : existingSplitChatReportID); + if (isSearchTopmostFullScreenRoute()) { + Navigation.dismissModal(); + } else { + Navigation.dismissModalWithReport({reportID: existingSplitChatReportID}); + } + notifyNewAction(splitData.chatReportID, currentUserAccountID); } @@ -5749,7 +5767,11 @@ function splitBillAndOpenReport({ API.write(WRITE_COMMANDS.SPLIT_BILL_AND_OPEN_REPORT, parameters, onyxData); InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); - Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : splitData.chatReportID); + if (isSearchTopmostFullScreenRoute()) { + Navigation.dismissModal(); + } else { + Navigation.dismissModalWithReport({reportID: splitData.chatReportID}); + } notifyNewAction(splitData.chatReportID, currentUserAccountID); } @@ -6072,7 +6094,7 @@ function startSplitBill({ API.write(WRITE_COMMANDS.START_SPLIT_BILL, parameters, {optimisticData, successData, failureData}); - Navigation.dismissModalWithReport(splitChatReport); + Navigation.dismissModalWithReport({report: splitChatReport}); notifyNewAction(splitChatReport.reportID, currentUserAccountID); } @@ -6331,7 +6353,11 @@ function completeSplitBill( API.write(WRITE_COMMANDS.COMPLETE_SPLIT_BILL, parameters, {optimisticData, successData, failureData}); InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); - Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : chatReportID); + if (isSearchTopmostFullScreenRoute()) { + Navigation.dismissModal(); + } else { + Navigation.dismissModalWithReport({reportID: chatReportID}); + } notifyNewAction(chatReportID, sessionAccountID); } @@ -6514,7 +6540,11 @@ function createDistanceRequest(distanceRequestInformation: CreateDistanceRequest API.write(WRITE_COMMANDS.CREATE_DISTANCE_REQUEST, parameters, onyxData); InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); const activeReportID = isMoneyRequestReport && report?.reportID ? report.reportID : parameters.chatReportID; - Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : activeReportID); + if (isSearchTopmostFullScreenRoute()) { + Navigation.dismissModal(); + } else { + Navigation.dismissModalWithReport({reportID: activeReportID}); + } notifyNewAction(activeReportID, userAccountID); } @@ -8202,7 +8232,11 @@ function sendMoneyElsewhere(report: OnyxEntry, amount: number, API.write(WRITE_COMMANDS.SEND_MONEY_ELSEWHERE, params, {optimisticData, successData, failureData}); - Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : params.chatReportID); + if (isSearchTopmostFullScreenRoute()) { + Navigation.dismissModal(); + } else { + Navigation.dismissModalWithReport({reportID: params.chatReportID}); + } notifyNewAction(params.chatReportID, managerID); } @@ -8215,7 +8249,11 @@ function sendMoneyWithWallet(report: OnyxEntry, amount: number API.write(WRITE_COMMANDS.SEND_MONEY_WITH_WALLET, params, {optimisticData, successData, failureData}); - Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : params.chatReportID); + if (isSearchTopmostFullScreenRoute()) { + Navigation.dismissModal(); + } else { + Navigation.dismissModalWithReport({reportID: params.chatReportID}); + } notifyNewAction(params.chatReportID, managerID); } diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 9f725a3a2a02..cc8fc7febbee 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -62,6 +62,7 @@ import getEnvironment from '@libs/Environment/getEnvironment'; import type EnvironmentType from '@libs/Environment/getEnvironment/types'; import * as ErrorUtils from '@libs/ErrorUtils'; import fileDownload from '@libs/fileDownload'; +import getIsNarrowLayout from '@libs/getIsNarrowLayout'; import HttpUtils from '@libs/HttpUtils'; import isPublicScreenRoute from '@libs/isPublicScreenRoute'; import * as Localize from '@libs/Localize'; @@ -1187,6 +1188,11 @@ function navigateToAndOpenReport( // We want to pass newChat here because if anything is passed in that param (even an existing chat), we will try to create a chat on the server openReport(report?.reportID, '', userLogins, newChat, undefined, undefined, undefined, avatarFile); if (shouldDismissModal) { + if (getIsNarrowLayout()) { + Navigation.dismissModalWithReport({report}); + return; + } + Navigation.dismissModal(); } @@ -2394,7 +2400,7 @@ function navigateToConciergeChat(shouldDismissModal = false, checkIfCurrentPageA navigateToAndOpenReport([CONST.EMAIL.CONCIERGE], shouldDismissModal); }); } else if (shouldDismissModal) { - Navigation.dismissModal(conciergeChatReportID); + Navigation.dismissModalWithReport({reportID: conciergeChatReportID}); } else { Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(conciergeChatReportID), linkToOptions); } @@ -2503,7 +2509,7 @@ function addPolicyReport(policyReport: OptimisticChatReport) { }; API.write(WRITE_COMMANDS.ADD_WORKSPACE_ROOM, parameters, {optimisticData, successData, failureData}); - Navigation.dismissModalWithReport(policyReport); + Navigation.dismissModalWithReport({report: policyReport}); } /** Deletes a report, along with its reportActions, any linked reports, and any linked IOU report. */ diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 0c3fc2b251a2..fd08ea92bb84 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -339,7 +339,7 @@ function createTaskAndNavigate( InteractionManager.runAfterInteractions(() => { clearOutTaskInfo(); }); - Navigation.dismissModal(parentReportID); + Navigation.dismissModalWithReport({reportID: parentReportID}); } notifyNewAction(parentReportID, currentUserAccountID); } diff --git a/src/libs/actions/TeachersUnite.ts b/src/libs/actions/TeachersUnite.ts index 44420d21a7db..c26411e763a3 100644 --- a/src/libs/actions/TeachersUnite.ts +++ b/src/libs/actions/TeachersUnite.ts @@ -69,7 +69,7 @@ function referTeachersUniteVolunteer(partnerUserID: string, firstName: string, l }; API.write(WRITE_COMMANDS.REFER_TEACHERS_UNITE_VOLUNTEER, parameters, {optimisticData}); - Navigation.dismissModal(publicRoomReportID); + Navigation.dismissModalWithReport({reportID: publicRoomReportID}); } /** @@ -193,7 +193,7 @@ function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: }; API.write(WRITE_COMMANDS.ADD_SCHOOL_PRINCIPAL, parameters, {optimisticData, successData, failureData}); - Navigation.dismissModal(expenseChatReportID); + Navigation.dismissModalWithReport({reportID: expenseChatReportID}); } export default {referTeachersUniteVolunteer, addSchoolPrincipal}; diff --git a/src/pages/AddPersonalBankAccountPage.tsx b/src/pages/AddPersonalBankAccountPage.tsx index c441174a21e5..c71b72b4ce2f 100644 --- a/src/pages/AddPersonalBankAccountPage.tsx +++ b/src/pages/AddPersonalBankAccountPage.tsx @@ -65,7 +65,7 @@ function AddPersonalBankAccountPage() { const onSuccessFallbackRoute = personalBankAccount?.onSuccessFallbackRoute ?? ''; if (exitReportID) { - Navigation.dismissModal(exitReportID); + Navigation.dismissModalWithReport({reportID: exitReportID}); } else if (shouldContinue && onSuccessFallbackRoute) { continueSetup(onSuccessFallbackRoute); } else { diff --git a/src/pages/EditReportFieldPage.tsx b/src/pages/EditReportFieldPage.tsx index fd617998da98..28949779f728 100644 --- a/src/pages/EditReportFieldPage.tsx +++ b/src/pages/EditReportFieldPage.tsx @@ -71,14 +71,22 @@ function EditReportFieldPage({route}: EditReportFieldPageProps) { if (value !== '') { ReportActions.updateReportField(report.reportID, {...reportField, value}, reportField); } - Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : report?.reportID); + if (isSearchTopmostFullScreenRoute()) { + Navigation.dismissModal(); + return; + } + Navigation.dismissModalWithReport({reportID: report?.reportID}); } }; const handleReportFieldDelete = () => { ReportActions.deleteReportField(report.reportID, reportField); setIsDeleteModalVisible(false); - Navigation.dismissModal(isSearchTopmostFullScreenRoute() ? undefined : report?.reportID); + if (isSearchTopmostFullScreenRoute()) { + Navigation.dismissModal(); + return; + } + Navigation.dismissModalWithReport({reportID: report?.reportID}); }; const fieldValue = isReportFieldTitle ? report.reportName ?? '' : reportField.value ?? reportField.defaultValue; diff --git a/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx b/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx index a273b210efa9..7bb194b07b48 100644 --- a/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx +++ b/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx @@ -45,7 +45,7 @@ function AddBankAccount() { const onSuccessFallbackRoute = personalBankAccount?.onSuccessFallbackRoute ?? ''; if (exitReportID) { - Navigation.dismissModal(exitReportID); + Navigation.dismissModalWithReport({reportID: exitReportID}); return; } if (shouldContinue && onSuccessFallbackRoute) { diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index f49b50da3c6a..7f016bd1c34c 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -229,7 +229,7 @@ function NewChatPage() { const selectOption = useCallback( (option?: Option) => { if (option?.isSelfDM) { - Navigation.dismissModal(option.reportID); + Navigation.dismissModalWithReport({reportID: option.reportID}); return; } if (selectedOptions.length && option) { diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index 700e2eaa68e7..e3f5828cd411 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -213,7 +213,7 @@ function RoomInvitePage({ const goBack = useCallback(() => { if (role === CONST.IOU.SHARE.ROLE.ACCOUNTANT) { - Navigation.dismissModal(reportID); + Navigation.dismissModalWithReport({reportID}); return; } Navigation.goBack(backRoute); diff --git a/src/pages/TransactionDuplicate/Confirmation.tsx b/src/pages/TransactionDuplicate/Confirmation.tsx index 805fda5c298a..0e9f7a86077d 100644 --- a/src/pages/TransactionDuplicate/Confirmation.tsx +++ b/src/pages/TransactionDuplicate/Confirmation.tsx @@ -66,7 +66,7 @@ function Confirmation() { const resolveDuplicates = useCallback(() => { IOU.resolveDuplicates(transactionsMergeParams); - Navigation.dismissModal(reportAction?.childReportID); + Navigation.dismissModalWithReport({reportID: reportAction?.childReportID}); }, [transactionsMergeParams, reportAction?.childReportID]); const contextValue = useMemo( diff --git a/src/pages/TransactionReceiptPage.tsx b/src/pages/TransactionReceiptPage.tsx index 132d1607fb52..abda0014c792 100644 --- a/src/pages/TransactionReceiptPage.tsx +++ b/src/pages/TransactionReceiptPage.tsx @@ -59,7 +59,7 @@ function TransactionReceipt({route}: TransactionReceiptProps) { Navigation.dismissModal(); } else { const isOneTransactionThread = isOneTransactionThreadReportUtils(report?.reportID, report?.parentReportID, parentReportAction); - Navigation.dismissModal(isOneTransactionThread ? report?.parentReportID : report?.reportID); + Navigation.dismissModalWithReport({reportID: isOneTransactionThread ? report?.parentReportID : report?.reportID}); } }; diff --git a/src/pages/tasks/TaskAssigneeSelectorModal.tsx b/src/pages/tasks/TaskAssigneeSelectorModal.tsx index 5aaf02d8ba3e..fbfefaefec8c 100644 --- a/src/pages/tasks/TaskAssigneeSelectorModal.tsx +++ b/src/pages/tasks/TaskAssigneeSelectorModal.tsx @@ -106,7 +106,7 @@ function TaskAssigneeSelectorModal() { const reportOnyx = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${route.params?.reportID}`]; if (reportOnyx && !ReportUtils.isTaskReport(reportOnyx)) { Navigation.isNavigationReady().then(() => { - Navigation.dismissModal(reportOnyx.reportID); + Navigation.dismissModalWithReport({reportID: reportOnyx.reportID}); }); } return reports?.[`${ONYXKEYS.COLLECTION.REPORT}${route.params?.reportID}`]; @@ -178,7 +178,7 @@ function TaskAssigneeSelectorModal() { TaskActions.editTaskAssignee(report, session?.accountID ?? -1, option?.login ?? '', option?.accountID, assigneeChatReport); } InteractionManager.runAfterInteractions(() => { - Navigation.dismissModal(report.reportID); + Navigation.dismissModalWithReport({reportID: report?.reportID}); }); // If there's no report, we're creating a new task } else if (option.accountID) { diff --git a/src/pages/tasks/TaskDescriptionPage.tsx b/src/pages/tasks/TaskDescriptionPage.tsx index 9fdf1757ca96..d855228e3c97 100644 --- a/src/pages/tasks/TaskDescriptionPage.tsx +++ b/src/pages/tasks/TaskDescriptionPage.tsx @@ -59,14 +59,14 @@ function TaskDescriptionPage({report, currentUserPersonalDetails}: TaskDescripti editTask(report, {description: values.description}); } - Navigation.dismissModal(report?.reportID); + Navigation.dismissModalWithReport({reportID: report?.reportID}); }, [report], ); if (!isTaskReport(report)) { Navigation.isNavigationReady().then(() => { - Navigation.dismissModal(report?.reportID); + Navigation.dismissModalWithReport({reportID: report?.reportID}); }); } const inputRef = useRef(null); diff --git a/src/pages/tasks/TaskTitlePage.tsx b/src/pages/tasks/TaskTitlePage.tsx index 30beb0bd700d..8d2f33d2cd75 100644 --- a/src/pages/tasks/TaskTitlePage.tsx +++ b/src/pages/tasks/TaskTitlePage.tsx @@ -63,14 +63,14 @@ function TaskTitlePage({report, currentUserPersonalDetails}: TaskTitlePageProps) editTask(report, {title: values.title}); } - Navigation.dismissModal(report?.reportID); + Navigation.dismissModalWithReport({reportID: report?.reportID}); }, [report], ); if (!isTaskReport(report)) { Navigation.isNavigationReady().then(() => { - Navigation.dismissModal(report?.reportID); + Navigation.dismissModalWithReport({reportID: report?.reportID}); }); } diff --git a/src/pages/workspace/WorkspaceNewRoomPage.tsx b/src/pages/workspace/WorkspaceNewRoomPage.tsx index a7f6cc329ff9..b95b09db644d 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.tsx +++ b/src/pages/workspace/WorkspaceNewRoomPage.tsx @@ -135,7 +135,7 @@ function WorkspaceNewRoomPage() { if (!(((wasLoading && !isLoading) || (isOffline && isLoading)) && isEmptyObject(errorFields))) { return; } - Navigation.dismissModal(newRoomReportID); + Navigation.dismissModalWithReport({reportID: newRoomReportID}); // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- we just want this to update on changing the form State }, [isLoading, errorFields]); diff --git a/src/pages/workspace/WorkspaceOverviewSharePage.tsx b/src/pages/workspace/WorkspaceOverviewSharePage.tsx index 2eab58a65e78..a01acab81542 100644 --- a/src/pages/workspace/WorkspaceOverviewSharePage.tsx +++ b/src/pages/workspace/WorkspaceOverviewSharePage.tsx @@ -89,7 +89,7 @@ function WorkspaceOverviewSharePage({policy}: WithPolicyProps) { if (!adminRoom?.reportID) { return; } - Navigation.dismissModal(adminRoom.reportID); + Navigation.dismissModalWithReport({reportID: adminRoom.reportID}); }} > {CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS} From ace13465f9904d7242bbd42e530d10c1ebe78b07 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 11 Mar 2025 09:51:32 +0100 Subject: [PATCH 2/6] Fix issue: Workspace-Overview page is shown briefly before landing on memebers page when inviting a user --- src/pages/workspace/WorkspaceInviteMessagePage.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/pages/workspace/WorkspaceInviteMessagePage.tsx b/src/pages/workspace/WorkspaceInviteMessagePage.tsx index 3f48e3c7a2f9..458395e47dbf 100644 --- a/src/pages/workspace/WorkspaceInviteMessagePage.tsx +++ b/src/pages/workspace/WorkspaceInviteMessagePage.tsx @@ -24,6 +24,7 @@ import {clearDraftValues} from '@libs/actions/FormActions'; import {openExternalLink} from '@libs/actions/Link'; import {addMembersToWorkspace} from '@libs/actions/Policy/Member'; import {setWorkspaceInviteMessageDraft} from '@libs/actions/Policy/Policy'; +import getIsNarrowLayout from '@libs/getIsNarrowLayout'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import {getAvatarsForAccountIDs} from '@libs/OptionsListUtils'; @@ -112,6 +113,12 @@ function WorkspaceInviteMessagePage({policy, route, currentUserPersonalDetails}: Navigation.setNavigationActionToMicrotaskQueue(() => Navigation.dismissModal()); return; } + + if (getIsNarrowLayout()) { + Navigation.navigate(ROUTES.WORKSPACE_MEMBERS.getRoute(route.params.policyID), {forceReplace: true}); + return; + } + Navigation.setNavigationActionToMicrotaskQueue(() => { Navigation.dismissModal(); InteractionManager.runAfterInteractions(() => { From c80127dd72c8835f7217449cf514de199c2c42b0 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 11 Mar 2025 11:15:21 +0100 Subject: [PATCH 3/6] Adjust NavigateToReportWithPolicyCheckPayload type to pass report or reportID --- src/libs/Navigation/Navigation.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts index 22843600cd8e..d523db0507a5 100644 --- a/src/libs/Navigation/Navigation.ts +++ b/src/libs/Navigation/Navigation.ts @@ -5,7 +5,7 @@ import {CommonActions, getPathFromState, StackActions} from '@react-navigation/n import omit from 'lodash/omit'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; -import type {Writable} from 'type-fest'; +import type {MergeExclusive, Writable} from 'type-fest'; import getIsNarrowLayout from '@libs/getIsNarrowLayout'; import Log from '@libs/Log'; import {shallowCompare} from '@libs/ObjectUtils'; @@ -469,7 +469,12 @@ function waitForProtectedRoutes() { }); } -type NavigateToReportWithPolicyCheckPayload = {report?: OnyxEntry; reportID?: string; reportActionID?: string; referrer?: string; policyIDToCheck?: string; forceReplace?: boolean}; +// It should not be possible to pass a report and a reportID at the same time. +type NavigateToReportWithPolicyCheckPayload = MergeExclusive<{report?: OnyxEntry}, {reportID?: string}> & { + reportActionID?: string; + referrer?: string; + policyIDToCheck?: string; +}; /** * Navigates to a report passed as a param (as an id or report object) and checks whether the target object belongs to the currently selected workspace. From 3f16676a0d1b2c7fbfc3ae2bff4aa1abeffebf83 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Tue, 11 Mar 2025 13:52:59 +0100 Subject: [PATCH 4/6] Make report and reportID params of dismissModal function mandatory --- src/libs/Navigation/Navigation.ts | 2 +- src/libs/actions/IOU.ts | 10 +++++----- src/pages/NewChatPage.tsx | 4 ++++ src/pages/TransactionDuplicate/Confirmation.tsx | 6 +++++- src/pages/TransactionReceiptPage.tsx | 7 ++++++- src/pages/workspace/WorkspaceNewRoomPage.tsx | 4 ++++ 6 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts index d523db0507a5..1798f19b5347 100644 --- a/src/libs/Navigation/Navigation.ts +++ b/src/libs/Navigation/Navigation.ts @@ -470,7 +470,7 @@ function waitForProtectedRoutes() { } // It should not be possible to pass a report and a reportID at the same time. -type NavigateToReportWithPolicyCheckPayload = MergeExclusive<{report?: OnyxEntry}, {reportID?: string}> & { +type NavigateToReportWithPolicyCheckPayload = MergeExclusive<{report: OnyxEntry}, {reportID: string}> & { reportActionID?: string; referrer?: string; policyIDToCheck?: string; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 50c3c69c9e36..8bebcc86f748 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -4717,7 +4717,7 @@ function requestMoney(requestMoneyInformation: RequestMoneyInformation) { } InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); - if (isSearchTopmostFullScreenRoute()) { + if (isSearchTopmostFullScreenRoute() || !activeReportID) { Navigation.dismissModal(); } else { Navigation.dismissModalWithReport({reportID: activeReportID}); @@ -4805,7 +4805,7 @@ function submitPerDiemExpense(submitPerDiemExpenseInformation: PerDiemExpenseInf API.write(WRITE_COMMANDS.CREATE_PER_DIEM_REQUEST, parameters, onyxData); InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); - if (isSearchTopmostFullScreenRoute()) { + if (isSearchTopmostFullScreenRoute() || !activeReportID) { Navigation.dismissModal(); } else { Navigation.dismissModalWithReport({reportID: activeReportID}); @@ -5103,7 +5103,7 @@ function trackExpense(params: CreateTrackExpenseParams) { } } InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); - if (isSearchTopmostFullScreenRoute()) { + if (isSearchTopmostFullScreenRoute() || !activeReportID) { Navigation.dismissModal(); } else { Navigation.dismissModalWithReport({reportID: activeReportID}); @@ -5689,7 +5689,7 @@ function splitBill({ API.write(WRITE_COMMANDS.SPLIT_BILL, parameters, onyxData); InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); - if (isSearchTopmostFullScreenRoute()) { + if (isSearchTopmostFullScreenRoute() || !existingSplitChatReportID) { Navigation.dismissModal(); } else { Navigation.dismissModalWithReport({reportID: existingSplitChatReportID}); @@ -6540,7 +6540,7 @@ function createDistanceRequest(distanceRequestInformation: CreateDistanceRequest API.write(WRITE_COMMANDS.CREATE_DISTANCE_REQUEST, parameters, onyxData); InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); const activeReportID = isMoneyRequestReport && report?.reportID ? report.reportID : parameters.chatReportID; - if (isSearchTopmostFullScreenRoute()) { + if (isSearchTopmostFullScreenRoute() || !activeReportID) { Navigation.dismissModal(); } else { Navigation.dismissModalWithReport({reportID: activeReportID}); diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index 7f016bd1c34c..33ce838a2918 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -229,6 +229,10 @@ function NewChatPage() { const selectOption = useCallback( (option?: Option) => { if (option?.isSelfDM) { + if (!option.reportID) { + Navigation.dismissModal(); + return; + } Navigation.dismissModalWithReport({reportID: option.reportID}); return; } diff --git a/src/pages/TransactionDuplicate/Confirmation.tsx b/src/pages/TransactionDuplicate/Confirmation.tsx index 0e9f7a86077d..e6d19a4d9815 100644 --- a/src/pages/TransactionDuplicate/Confirmation.tsx +++ b/src/pages/TransactionDuplicate/Confirmation.tsx @@ -66,7 +66,11 @@ function Confirmation() { const resolveDuplicates = useCallback(() => { IOU.resolveDuplicates(transactionsMergeParams); - Navigation.dismissModalWithReport({reportID: reportAction?.childReportID}); + if (!reportAction?.childReportID) { + Navigation.dismissModal(); + return; + } + Navigation.dismissModalWithReport({reportID: reportAction.childReportID}); }, [transactionsMergeParams, reportAction?.childReportID]); const contextValue = useMemo( diff --git a/src/pages/TransactionReceiptPage.tsx b/src/pages/TransactionReceiptPage.tsx index abda0014c792..78a35fcd163b 100644 --- a/src/pages/TransactionReceiptPage.tsx +++ b/src/pages/TransactionReceiptPage.tsx @@ -59,7 +59,12 @@ function TransactionReceipt({route}: TransactionReceiptProps) { Navigation.dismissModal(); } else { const isOneTransactionThread = isOneTransactionThreadReportUtils(report?.reportID, report?.parentReportID, parentReportAction); - Navigation.dismissModalWithReport({reportID: isOneTransactionThread ? report?.parentReportID : report?.reportID}); + const reportID = isOneTransactionThread ? report?.parentReportID : report?.reportID; + if (!reportID) { + Navigation.dismissModal(); + return; + } + Navigation.dismissModalWithReport({reportID}); } }; diff --git a/src/pages/workspace/WorkspaceNewRoomPage.tsx b/src/pages/workspace/WorkspaceNewRoomPage.tsx index b95b09db644d..c16757e154a2 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.tsx +++ b/src/pages/workspace/WorkspaceNewRoomPage.tsx @@ -135,6 +135,10 @@ function WorkspaceNewRoomPage() { if (!(((wasLoading && !isLoading) || (isOffline && isLoading)) && isEmptyObject(errorFields))) { return; } + if (!newRoomReportID) { + Navigation.dismissModal(); + return; + } Navigation.dismissModalWithReport({reportID: newRoomReportID}); // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- we just want this to update on changing the form State }, [isLoading, errorFields]); From 57993ee22ad7721dba13c3c5995604e77b982146 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Wed, 12 Mar 2025 08:57:04 +0100 Subject: [PATCH 5/6] Fix imports and default id values --- src/libs/actions/TeachersUnite.ts | 2 +- src/pages/EditReportFieldPage.tsx | 10 +-- .../AddBankAccount/AddBankAccount.tsx | 14 ++-- src/pages/RoomInvitePage.tsx | 82 +++++++++---------- src/pages/tasks/TaskAssigneeSelectorModal.tsx | 40 ++++----- .../workspace/WorkspaceOverviewSharePage.tsx | 16 ++-- 6 files changed, 81 insertions(+), 83 deletions(-) diff --git a/src/libs/actions/TeachersUnite.ts b/src/libs/actions/TeachersUnite.ts index c26411e763a3..42da9df63983 100644 --- a/src/libs/actions/TeachersUnite.ts +++ b/src/libs/actions/TeachersUnite.ts @@ -27,7 +27,7 @@ Onyx.connect({ key: ONYXKEYS.SESSION, callback: (value) => { sessionEmail = value?.email ?? ''; - sessionAccountID = value?.accountID ?? -1; + sessionAccountID = value?.accountID ?? CONST.DEFAULT_NUMBER_ID; }, }); diff --git a/src/pages/EditReportFieldPage.tsx b/src/pages/EditReportFieldPage.tsx index 28949779f728..d0ca5b5e9c16 100644 --- a/src/pages/EditReportFieldPage.tsx +++ b/src/pages/EditReportFieldPage.tsx @@ -15,7 +15,7 @@ import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTop import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {EditRequestNavigatorParamList} from '@libs/Navigation/types'; -import * as ReportUtils from '@libs/ReportUtils'; +import {getReportFieldKey, isInvoiceReport, isPaidGroupPolicyExpenseReport, isReportFieldDisabled, isReportFieldOfTypeTitle} from '@libs/ReportUtils'; import CONST from '@src/CONST'; import * as ReportActions from '@src/libs/actions/Report'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -31,16 +31,16 @@ function EditReportFieldPage({route}: EditReportFieldPageProps) { const {windowWidth} = useWindowDimensions(); const styles = useThemeStyles(); const {backTo, reportID, policyID} = route.params; - const fieldKey = ReportUtils.getReportFieldKey(route.params.fieldID); + const fieldKey = getReportFieldKey(route.params.fieldID); const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`); const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); const reportField = report?.fieldList?.[fieldKey] ?? policy?.fieldList?.[fieldKey]; const policyField = policy?.fieldList?.[fieldKey] ?? reportField; - const isDisabled = ReportUtils.isReportFieldDisabled(report, reportField, policy); + const isDisabled = isReportFieldDisabled(report, reportField, policy); const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false); const {translate} = useLocalize(); - const isReportFieldTitle = ReportUtils.isReportFieldOfTypeTitle(reportField); - const reportFieldsEnabled = ((ReportUtils.isPaidGroupPolicyExpenseReport(report) || ReportUtils.isInvoiceReport(report)) && !!policy?.areReportFieldsEnabled) || isReportFieldTitle; + const isReportFieldTitle = isReportFieldOfTypeTitle(reportField); + const reportFieldsEnabled = ((isPaidGroupPolicyExpenseReport(report) || isInvoiceReport(report)) && !!policy?.areReportFieldsEnabled) || isReportFieldTitle; if (!reportFieldsEnabled || !reportField || !policyField || !report || isDisabled) { return ( diff --git a/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx b/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx index 7bb194b07b48..5b38a557ad2c 100644 --- a/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx +++ b/src/pages/EnablePayments/AddBankAccount/AddBankAccount.tsx @@ -8,10 +8,10 @@ import useLocalize from '@hooks/useLocalize'; import useSubStep from '@hooks/useSubStep'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; +import {addPersonalBankAccount, clearPersonalBankAccount} from '@libs/actions/BankAccounts'; +import {continueSetup} from '@libs/actions/PaymentMethods'; +import {updateCurrentStep} from '@libs/actions/Wallet'; import Navigation from '@navigation/Navigation'; -import * as BankAccounts from '@userActions/BankAccounts'; -import * as PaymentMethods from '@userActions/PaymentMethods'; -import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -32,7 +32,7 @@ function AddBankAccount() { const selectedPlaidBankAccount = bankAccounts.find((bankAccount) => bankAccount.plaidAccountID === personalBankAccountDraft?.plaidAccountID); if (selectedPlaidBankAccount) { - BankAccounts.addPersonalBankAccount(selectedPlaidBankAccount); + addPersonalBankAccount(selectedPlaidBankAccount); } }, [personalBankAccountDraft?.plaidAccountID, plaidData?.bankAccounts]); @@ -49,7 +49,7 @@ function AddBankAccount() { return; } if (shouldContinue && onSuccessFallbackRoute) { - PaymentMethods.continueSetup(onSuccessFallbackRoute); + continueSetup(onSuccessFallbackRoute); return; } Navigation.goBack(ROUTES.SETTINGS_WALLET); @@ -61,8 +61,8 @@ function AddBankAccount() { return; } if (screenIndex === 0) { - BankAccounts.clearPersonalBankAccount(); - Wallet.updateCurrentStep(null); + clearPersonalBankAccount(); + updateCurrentStep(null); Navigation.goBack(ROUTES.SETTINGS_WALLET); return; } diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index e3f5828cd411..9f77ec87fdee 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -16,21 +16,23 @@ import type {WithNavigationTransitionEndProps} from '@components/withNavigationT import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ReportActions from '@libs/actions/Report'; -import * as UserSearchPhraseActions from '@libs/actions/RoomMembersUserSearchPhrase'; +import {inviteToRoom, searchInServer} from '@libs/actions/Report'; +import {clearUserSearchPhrase, updateUserSearchPhrase} from '@libs/actions/RoomMembersUserSearchPhrase'; import {READ_COMMANDS} from '@libs/API/types'; -import * as DeviceCapabilities from '@libs/DeviceCapabilities'; +import {canUseTouchScreen} from '@libs/DeviceCapabilities'; import HttpUtils from '@libs/HttpUtils'; -import * as LoginUtils from '@libs/LoginUtils'; +import {appendCountryCode} from '@libs/LoginUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {RoomMembersNavigatorParamList} from '@libs/Navigation/types'; -import * as OptionsListUtils from '@libs/OptionsListUtils'; -import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; -import * as PhoneNumber from '@libs/PhoneNumber'; -import * as PolicyUtils from '@libs/PolicyUtils'; -import * as ReportUtils from '@libs/ReportUtils'; -import * as Report from '@userActions/Report'; +import type {MemberForList} from '@libs/OptionsListUtils'; +import {filterAndOrderOptions, formatMemberForList, getHeaderMessage, getMemberInviteOptions} from '@libs/OptionsListUtils'; +import {getLoginsByAccountIDs} from '@libs/PersonalDetailsUtils'; +import {addSMSDomainIfPhoneNumber, parsePhoneNumber} from '@libs/PhoneNumber'; +import {isPolicyEmployee} from '@libs/PolicyUtils'; +import type {MemberEmailsToAccountIDs} from '@libs/PolicyUtils'; +import type {OptionData} from '@libs/ReportUtils'; +import {getReportName, isHiddenForCurrentUser} from '@libs/ReportUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -42,7 +44,7 @@ import withReportOrNotFound from './home/report/withReportOrNotFound'; type RoomInvitePageProps = WithReportOrNotFoundProps & WithNavigationTransitionEndProps & PlatformStackScreenProps; -type Sections = Array>>; +type Sections = Array>>; function RoomInvitePage({ betas, report, @@ -55,7 +57,7 @@ function RoomInvitePage({ const {translate} = useLocalize(); const [userSearchPhrase] = useOnyx(ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE); const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(userSearchPhrase ?? ''); - const [selectedOptions, setSelectedOptions] = useState([]); + const [selectedOptions, setSelectedOptions] = useState([]); const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false}); const {options, areOptionsInitialized} = useOptionsList(); @@ -66,10 +68,10 @@ function RoomInvitePage({ ...CONST.EXPENSIFY_EMAILS_OBJECT, }; const visibleParticipantAccountIDs = Object.entries(report.participants ?? {}) - .filter(([, participant]) => participant && !ReportUtils.isHiddenForCurrentUser(participant.notificationPreference)) + .filter(([, participant]) => participant && !isHiddenForCurrentUser(participant.notificationPreference)) .map(([accountID]) => Number(accountID)); - PersonalDetailsUtils.getLoginsByAccountIDs(visibleParticipantAccountIDs).forEach((participant) => { - const smsDomain = PhoneNumber.addSMSDomainIfPhoneNumber(participant); + getLoginsByAccountIDs(visibleParticipantAccountIDs).forEach((participant) => { + const smsDomain = addSMSDomainIfPhoneNumber(participant); res[smsDomain] = true; }); @@ -81,16 +83,16 @@ function RoomInvitePage({ return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null}; } - const inviteOptions = OptionsListUtils.getMemberInviteOptions(options.personalDetails, betas ?? [], excludedUsers); + const inviteOptions = getMemberInviteOptions(options.personalDetails, betas ?? [], excludedUsers); // Update selectedOptions with the latest personalDetails information - const detailsMap: Record = {}; + const detailsMap: Record = {}; inviteOptions.personalDetails.forEach((detail) => { if (!detail.login) { return; } - detailsMap[detail.login] = OptionsListUtils.formatMemberForList(detail); + detailsMap[detail.login] = formatMemberForList(detail); }); - const newSelectedOptions: ReportUtils.OptionData[] = []; + const newSelectedOptions: OptionData[] = []; selectedOptions.forEach((option) => { newSelectedOptions.push(option.login && option.login in detailsMap ? {...detailsMap[option.login], isSelected: true} : option); }); @@ -108,7 +110,7 @@ function RoomInvitePage({ if (debouncedSearchTerm.trim() === '') { return defaultOptions; } - const filteredOptions = OptionsListUtils.filterAndOrderOptions(defaultOptions, debouncedSearchTerm, {excludeLogins: excludedUsers}); + const filteredOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, {excludeLogins: excludedUsers}); return filteredOptions; }, [debouncedSearchTerm, defaultOptions, excludedUsers]); @@ -127,13 +129,13 @@ function RoomInvitePage({ filterSelectedOptions = selectedOptions.filter((option) => { const accountID = option?.accountID; const isOptionInPersonalDetails = personalDetails ? personalDetails.some((personalDetail) => accountID && personalDetail?.accountID === accountID) : false; - const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(debouncedSearchTerm))); + const parsedPhoneNumber = parsePhoneNumber(appendCountryCode(Str.removeSMSDomain(debouncedSearchTerm))); const searchValue = parsedPhoneNumber.possible && parsedPhoneNumber.number ? parsedPhoneNumber.number.e164 : debouncedSearchTerm.toLowerCase(); const isPartOfSearchTerm = (option.text?.toLowerCase() ?? '').includes(searchValue) || (option.login?.toLowerCase() ?? '').includes(searchValue); return isPartOfSearchTerm || isOptionInPersonalDetails; }); } - const filterSelectedOptionsFormatted = filterSelectedOptions.map((selectedOption) => OptionsListUtils.formatMemberForList(selectedOption)); + const filterSelectedOptionsFormatted = filterSelectedOptions.map((selectedOption) => formatMemberForList(selectedOption)); sectionsArr.push({ title: undefined, @@ -143,7 +145,7 @@ function RoomInvitePage({ // Filtering out selected users from the search results const selectedLogins = selectedOptions.map(({login}) => login); const personalDetailsWithoutSelected = personalDetails ? personalDetails.filter(({login}) => !selectedLogins.includes(login)) : []; - const personalDetailsFormatted = personalDetailsWithoutSelected.map((personalDetail) => OptionsListUtils.formatMemberForList(personalDetail)); + const personalDetailsFormatted = personalDetailsWithoutSelected.map((personalDetail) => formatMemberForList(personalDetail)); const hasUnselectedUserToInvite = userToInvite && !selectedLogins.includes(userToInvite.login); sectionsArr.push({ @@ -154,7 +156,7 @@ function RoomInvitePage({ if (hasUnselectedUserToInvite) { sectionsArr.push({ title: undefined, - data: [OptionsListUtils.formatMemberForList(userToInvite)], + data: [formatMemberForList(userToInvite)], }); } @@ -162,10 +164,10 @@ function RoomInvitePage({ }, [inviteOptions, areOptionsInitialized, selectedOptions, debouncedSearchTerm, translate]); const toggleOption = useCallback( - (option: OptionsListUtils.MemberForList) => { + (option: MemberForList) => { const isOptionInList = selectedOptions.some((selectedOption) => selectedOption.login === option.login); - let newSelectedOptions: ReportUtils.OptionData[]; + let newSelectedOptions: OptionData[]; if (isOptionInList) { newSelectedOptions = selectedOptions.filter((selectedOption) => selectedOption.login !== option.login); } else { @@ -181,21 +183,21 @@ function RoomInvitePage({ // Non policy members should not be able to view the participants of a room const reportID = report?.reportID; - const isPolicyEmployee = useMemo(() => (report?.policyID ? PolicyUtils.isPolicyEmployee(report.policyID, policies as Record) : false), [report?.policyID, policies]); + const isPolicyEmployeeValue = useMemo(() => (report?.policyID ? isPolicyEmployee(report.policyID, policies as Record) : false), [report?.policyID, policies]); const backRoute = useMemo(() => { if (role === CONST.IOU.SHARE.ROLE.ACCOUNTANT) { return ROUTES.REPORT_WITH_ID.getRoute(reportID); } - return reportID && (isPolicyEmployee ? ROUTES.ROOM_MEMBERS.getRoute(reportID, backTo) : ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID, backTo)); - }, [isPolicyEmployee, reportID, role, backTo]); - const reportName = useMemo(() => ReportUtils.getReportName(report), [report]); + return reportID && (isPolicyEmployeeValue ? ROUTES.ROOM_MEMBERS.getRoute(reportID, backTo) : ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID, backTo)); + }, [isPolicyEmployeeValue, reportID, role, backTo]); + const reportName = useMemo(() => getReportName(report), [report]); const inviteUsers = useCallback(() => { HttpUtils.cancelPendingRequests(READ_COMMANDS.SEARCH_FOR_REPORTS); if (!validate()) { return; } - const invitedEmailsToAccountIDs: PolicyUtils.MemberEmailsToAccountIDs = {}; + const invitedEmailsToAccountIDs: MemberEmailsToAccountIDs = {}; selectedOptions.forEach((option) => { const login = option.login ?? ''; const accountID = option.accountID; @@ -205,9 +207,9 @@ function RoomInvitePage({ invitedEmailsToAccountIDs[login] = Number(accountID); }); if (reportID) { - Report.inviteToRoom(reportID, invitedEmailsToAccountIDs); + inviteToRoom(reportID, invitedEmailsToAccountIDs); } - UserSearchPhraseActions.clearUserSearchPhrase(); + clearUserSearchPhrase(); Navigation.navigate(backRoute); }, [selectedOptions, backRoute, reportID, validate]); @@ -227,20 +229,16 @@ function RoomInvitePage({ } if ( !inviteOptions.userToInvite && - excludedUsers[ - PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(searchValue)).possible - ? PhoneNumber.addSMSDomainIfPhoneNumber(LoginUtils.appendCountryCode(searchValue)) - : searchValue - ] + excludedUsers[parsePhoneNumber(appendCountryCode(searchValue)).possible ? addSMSDomainIfPhoneNumber(appendCountryCode(searchValue)) : searchValue] ) { return translate('messages.userIsAlreadyMember', {login: searchValue, name: reportName}); } - return OptionsListUtils.getHeaderMessage((inviteOptions.personalDetails ?? []).length !== 0, !!inviteOptions.userToInvite, debouncedSearchTerm); + return getHeaderMessage((inviteOptions.personalDetails ?? []).length !== 0, !!inviteOptions.userToInvite, debouncedSearchTerm); }, [debouncedSearchTerm, inviteOptions.userToInvite, inviteOptions.personalDetails, excludedUsers, translate, reportName]); useEffect(() => { - UserSearchPhraseActions.updateUserSearchPhrase(debouncedSearchTerm); - ReportActions.searchInServer(debouncedSearchTerm); + updateUserSearchPhrase(debouncedSearchTerm); + searchInServer(debouncedSearchTerm); }, [debouncedSearchTerm]); return ( @@ -272,7 +270,7 @@ function RoomInvitePage({ onSelectRow={toggleOption} onConfirm={inviteUsers} showScrollIndicator - shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} + shouldPreventDefaultFocusOnSelectRow={!canUseTouchScreen()} showLoadingPlaceholder={!areOptionsInitialized} isLoadingNewOptions={!!isSearchingForReports} /> diff --git a/src/pages/tasks/TaskAssigneeSelectorModal.tsx b/src/pages/tasks/TaskAssigneeSelectorModal.tsx index fbfefaefec8c..7611f448dd7c 100644 --- a/src/pages/tasks/TaskAssigneeSelectorModal.tsx +++ b/src/pages/tasks/TaskAssigneeSelectorModal.tsx @@ -18,15 +18,15 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ReportActions from '@libs/actions/Report'; +import {searchInServer} from '@libs/actions/Report'; +import {canModifyTask, editTaskAssignee, setAssigneeValue} from '@libs/actions/Task'; import {READ_COMMANDS} from '@libs/API/types'; import HttpUtils from '@libs/HttpUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; -import * as OptionsListUtils from '@libs/OptionsListUtils'; -import * as ReportUtils from '@libs/ReportUtils'; +import {filterAndOrderOptions, getHeaderMessage, getValidOptions, isCurrentUser} from '@libs/OptionsListUtils'; +import {isOpenTaskReport, isTaskReport} from '@libs/ReportUtils'; import type {TaskDetailsNavigatorParamList} from '@navigation/types'; -import * as TaskActions from '@userActions/Task'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -40,7 +40,7 @@ function useOptions() { const {options: optionsList, areOptionsInitialized} = useOptionsList(); const defaultOptions = useMemo(() => { - const {recentReports, personalDetails, userToInvite, currentUserOption} = OptionsListUtils.getValidOptions( + const {recentReports, personalDetails, userToInvite, currentUserOption} = getValidOptions( { reports: optionsList.reports, personalDetails: optionsList.personalDetails, @@ -51,7 +51,7 @@ function useOptions() { }, ); - const headerMessage = OptionsListUtils.getHeaderMessage((recentReports?.length || 0) + (personalDetails?.length || 0) !== 0 || !!currentUserOption, !!userToInvite, ''); + const headerMessage = getHeaderMessage((recentReports?.length || 0) + (personalDetails?.length || 0) !== 0 || !!currentUserOption, !!userToInvite, ''); if (isLoading) { // eslint-disable-next-line react-compiler/react-compiler @@ -68,11 +68,11 @@ function useOptions() { }, [optionsList.reports, optionsList.personalDetails, betas, isLoading]); const options = useMemo(() => { - const filteredOptions = OptionsListUtils.filterAndOrderOptions(defaultOptions, debouncedSearchValue.trim(), { + const filteredOptions = filterAndOrderOptions(defaultOptions, debouncedSearchValue.trim(), { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, }); - const headerMessage = OptionsListUtils.getHeaderMessage( + const headerMessage = getHeaderMessage( (filteredOptions.recentReports?.length || 0) + (filteredOptions.personalDetails?.length || 0) !== 0 || !!filteredOptions.currentUserOption, !!filteredOptions.userToInvite, debouncedSearchValue, @@ -104,7 +104,7 @@ function TaskAssigneeSelectorModal() { return; } const reportOnyx = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${route.params?.reportID}`]; - if (reportOnyx && !ReportUtils.isTaskReport(reportOnyx)) { + if (reportOnyx && !isTaskReport(reportOnyx)) { Navigation.isNavigationReady().then(() => { Navigation.dismissModalWithReport({reportID: reportOnyx.reportID}); }); @@ -167,27 +167,27 @@ function TaskAssigneeSelectorModal() { // Check to see if we're editing a task and if so, update the assignee if (report) { if (option.accountID !== report.managerID) { - const assigneeChatReport = TaskActions.setAssigneeValue( + const assigneeChatReport = setAssigneeValue( option?.login ?? '', - option?.accountID ?? -1, + option?.accountID ?? CONST.DEFAULT_NUMBER_ID, report.reportID, undefined, // passing null as report because for editing task the report will be task details report page not the actual report where task was created - OptionsListUtils.isCurrentUser({...option, accountID: option?.accountID ?? -1, login: option?.login ?? ''}), + isCurrentUser({...option, accountID: option?.accountID ?? CONST.DEFAULT_NUMBER_ID, login: option?.login ?? ''}), ); // Pass through the selected assignee - TaskActions.editTaskAssignee(report, session?.accountID ?? -1, option?.login ?? '', option?.accountID, assigneeChatReport); + editTaskAssignee(report, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, option?.login ?? '', option?.accountID, assigneeChatReport); } InteractionManager.runAfterInteractions(() => { Navigation.dismissModalWithReport({reportID: report?.reportID}); }); // If there's no report, we're creating a new task } else if (option.accountID) { - TaskActions.setAssigneeValue( + setAssigneeValue( option?.login ?? '', - option.accountID ?? -1, + option.accountID ?? CONST.DEFAULT_NUMBER_ID, task?.shareDestination ?? '', undefined, // passing null as report is null in this condition - OptionsListUtils.isCurrentUser({...option, accountID: option?.accountID ?? -1, login: option?.login ?? undefined}), + isCurrentUser({...option, accountID: option?.accountID ?? CONST.DEFAULT_NUMBER_ID, login: option?.login ?? undefined}), ); InteractionManager.runAfterInteractions(() => { Navigation.goBack(ROUTES.NEW_TASK.getRoute(backTo)); @@ -199,12 +199,12 @@ function TaskAssigneeSelectorModal() { const handleBackButtonPress = useCallback(() => Navigation.goBack(!route.params?.reportID ? ROUTES.NEW_TASK.getRoute(backTo) : backTo), [route.params, backTo]); - const isOpen = ReportUtils.isOpenTaskReport(report); - const canModifyTask = TaskActions.canModifyTask(report, currentUserPersonalDetails.accountID); - const isTaskNonEditable = ReportUtils.isTaskReport(report) && (!canModifyTask || !isOpen); + const isOpen = isOpenTaskReport(report); + const canModifyTaskValue = canModifyTask(report, currentUserPersonalDetails.accountID); + const isTaskNonEditable = isTaskReport(report) && (!canModifyTaskValue || !isOpen); useEffect(() => { - ReportActions.searchInServer(debouncedSearchValue); + searchInServer(debouncedSearchValue); }, [debouncedSearchValue]); return ( diff --git a/src/pages/workspace/WorkspaceOverviewSharePage.tsx b/src/pages/workspace/WorkspaceOverviewSharePage.tsx index a01acab81542..a2a84a496e48 100644 --- a/src/pages/workspace/WorkspaceOverviewSharePage.tsx +++ b/src/pages/workspace/WorkspaceOverviewSharePage.tsx @@ -20,9 +20,9 @@ import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import Clipboard from '@libs/Clipboard'; import Navigation from '@libs/Navigation/Navigation'; -import * as ReportUtils from '@libs/ReportUtils'; +import {getDefaultWorkspaceAvatar, getRoom} from '@libs/ReportUtils'; import shouldAllowDownloadQRCode from '@libs/shouldAllowDownloadQRCode'; -import * as Url from '@libs/Url'; +import {addTrailingForwardSlash} from '@libs/Url'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import AccessOrNotFoundWrapper from './AccessOrNotFoundWrapper'; @@ -39,17 +39,17 @@ function WorkspaceOverviewSharePage({policy}: WithPolicyProps) { const session = useSession(); const policyName = policy?.name ?? ''; - const policyID = policy?.id ?? '-1'; + const policyID = policy?.id; const adminEmail = session?.email ?? ''; - const urlWithTrailingSlash = Url.addTrailingForwardSlash(environmentURL); + const urlWithTrailingSlash = addTrailingForwardSlash(environmentURL); - const url = `${urlWithTrailingSlash}${ROUTES.WORKSPACE_JOIN_USER.getRoute(policyID, adminEmail)}`; + const url = `${urlWithTrailingSlash}${ROUTES.WORKSPACE_JOIN_USER.getRoute(policyID ?? '', adminEmail)}`; const hasAvatar = !!policy?.avatarURL; const logo = hasAvatar ? (policy?.avatarURL as ImageSourcePropType) : undefined; - const defaultWorkspaceAvatar = ReportUtils.getDefaultWorkspaceAvatar(policyName) || Expensicons.FallbackAvatar; - const defaultWorkspaceAvatarColors = StyleUtils.getDefaultWorkspaceAvatarColor(policyID); + const defaultWorkspaceAvatar = getDefaultWorkspaceAvatar(policyName) || Expensicons.FallbackAvatar; + const defaultWorkspaceAvatarColors = StyleUtils.getDefaultWorkspaceAvatarColor(policyID ?? ''); const svgLogo = !hasAvatar ? defaultWorkspaceAvatar : undefined; const logoBackgroundColor = !hasAvatar ? defaultWorkspaceAvatarColors.backgroundColor?.toString() : undefined; @@ -59,7 +59,7 @@ function WorkspaceOverviewSharePage({policy}: WithPolicyProps) { if (!policy?.id) { return undefined; } - return ReportUtils.getRoom(CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, policy?.id); + return getRoom(CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, policy?.id); }, [policy?.id]); return ( From cf93159af1efaf59e4cc075fdd55ff1d9e479c28 Mon Sep 17 00:00:00 2001 From: Wojciech Boman Date: Wed, 12 Mar 2025 09:30:07 +0100 Subject: [PATCH 6/6] Fix default policyID values in WorkspaceOverviewSharePage --- src/pages/workspace/WorkspaceOverviewSharePage.tsx | 4 ++-- src/styles/utils/index.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/WorkspaceOverviewSharePage.tsx b/src/pages/workspace/WorkspaceOverviewSharePage.tsx index a2a84a496e48..fe8d87f73e85 100644 --- a/src/pages/workspace/WorkspaceOverviewSharePage.tsx +++ b/src/pages/workspace/WorkspaceOverviewSharePage.tsx @@ -43,13 +43,13 @@ function WorkspaceOverviewSharePage({policy}: WithPolicyProps) { const adminEmail = session?.email ?? ''; const urlWithTrailingSlash = addTrailingForwardSlash(environmentURL); - const url = `${urlWithTrailingSlash}${ROUTES.WORKSPACE_JOIN_USER.getRoute(policyID ?? '', adminEmail)}`; + const url = policyID ? `${urlWithTrailingSlash}${ROUTES.WORKSPACE_JOIN_USER.getRoute(policyID, adminEmail)}` : ''; const hasAvatar = !!policy?.avatarURL; const logo = hasAvatar ? (policy?.avatarURL as ImageSourcePropType) : undefined; const defaultWorkspaceAvatar = getDefaultWorkspaceAvatar(policyName) || Expensicons.FallbackAvatar; - const defaultWorkspaceAvatarColors = StyleUtils.getDefaultWorkspaceAvatarColor(policyID ?? ''); + const defaultWorkspaceAvatarColors = StyleUtils.getDefaultWorkspaceAvatarColor(policyID); const svgLogo = !hasAvatar ? defaultWorkspaceAvatar : undefined; const logoBackgroundColor = !hasAvatar ? defaultWorkspaceAvatarColors.backgroundColor?.toString() : undefined; diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts index 39d5e5ca959a..16ce1caf630a 100644 --- a/src/styles/utils/index.ts +++ b/src/styles/utils/index.ts @@ -275,8 +275,8 @@ function getAvatarBorderStyle(size: AvatarSizeName, type: string): ViewStyle { /** * Helper method to return workspace avatar color styles */ -function getDefaultWorkspaceAvatarColor(text: string): ViewStyle { - const colorHash = hashText(text.trim(), workspaceColorOptions.length); +function getDefaultWorkspaceAvatarColor(text?: string): ViewStyle { + const colorHash = hashText((text ?? '').trim(), workspaceColorOptions.length); return workspaceColorOptions.at(colorHash) ?? {backgroundColor: colors.blue200, fill: colors.blue700}; }