From a29d34e8188f1d1f349dde3b6ba51b4fe61ac8be Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:58:09 +0200 Subject: [PATCH] Revert "[Revert] #36409 "Fix: three not found view"" This reverts commit 0237f277c0d3c363ee1b20115df440f63da0b538. --- src/libs/Navigation/Navigation.ts | 7 + src/libs/Navigation/dismissRHP.ts | 25 ++++ src/pages/workspace/WorkspaceInitialPage.tsx | 14 ++ .../workspace/WorkspaceInviteMessagePage.tsx | 3 + src/pages/workspace/WorkspaceMembersPage.tsx | 121 ++++++++---------- .../workspace/WorkspacePageWithSections.tsx | 14 +- 6 files changed, 116 insertions(+), 68 deletions(-) create mode 100644 src/libs/Navigation/dismissRHP.ts diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts index 6f5e86f057d8..de45f27022d2 100644 --- a/src/libs/Navigation/Navigation.ts +++ b/src/libs/Navigation/Navigation.ts @@ -14,6 +14,7 @@ import type {EmptyObject} from '@src/types/utils/EmptyObject'; import originalCloseRHPFlow from './closeRHPFlow'; import originalDismissModal from './dismissModal'; import originalDismissModalWithReport from './dismissModalWithReport'; +import originalDismissRHP from './dismissRHP'; import originalGetTopmostReportActionId from './getTopmostReportActionID'; import originalGetTopmostReportId from './getTopmostReportId'; import linkingConfig from './linkingConfig'; @@ -64,6 +65,11 @@ const dismissModal = (reportID?: string, ref = navigationRef) => { // Re-exporting the closeRHPFlow here to fill in default value for navigationRef. The closeRHPFlow isn't defined in this file to avoid cyclic dependencies. const closeRHPFlow = (ref = navigationRef) => originalCloseRHPFlow(ref); +// Re-exporting the dismissRHP here to fill in default value for navigationRef. The dismissRHP isn't defined in this file to avoid cyclic dependencies. +const dismissRHP = (ref = navigationRef) => { + originalDismissRHP(ref); +}; + // Re-exporting the dismissModalWithReport here to fill in default value for navigationRef. The dismissModalWithReport isn't defined in this file to avoid cyclic dependencies. // This method is needed because it allows to dismiss the modal and then open the report. Within this method is checked whether the report belongs to a specific workspace. Sometimes the report we want to check, hasn't been added to the Onyx yet. // Then we can pass the report as a param without getting it from the Onyx. @@ -367,6 +373,7 @@ export default { setShouldPopAllStateOnUP, navigate, setParams, + dismissRHP, dismissModal, dismissModalWithReport, isActiveRoute, diff --git a/src/libs/Navigation/dismissRHP.ts b/src/libs/Navigation/dismissRHP.ts new file mode 100644 index 000000000000..1c497a79600c --- /dev/null +++ b/src/libs/Navigation/dismissRHP.ts @@ -0,0 +1,25 @@ +import type {NavigationContainerRef} from '@react-navigation/native'; +import {StackActions} from '@react-navigation/native'; +import NAVIGATORS from '@src/NAVIGATORS'; +import type {RootStackParamList} from './types'; + +// This function is in a separate file than Navigation.ts to avoid cyclic dependency. + +/** + * Dismisses the RHP modal stack if there is any + * + * @param targetReportID - The reportID to navigate to after dismissing the modal + */ +function dismissRHP(navigationRef: NavigationContainerRef) { + if (!navigationRef.isReady()) { + return; + } + + const state = navigationRef.getState(); + const lastRoute = state.routes.at(-1); + if (lastRoute?.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR) { + navigationRef.dispatch({...StackActions.pop(), target: state.key}); + } +} + +export default dismissRHP; diff --git a/src/pages/workspace/WorkspaceInitialPage.tsx b/src/pages/workspace/WorkspaceInitialPage.tsx index 1c861d510a85..bea849954631 100644 --- a/src/pages/workspace/WorkspaceInitialPage.tsx +++ b/src/pages/workspace/WorkspaceInitialPage.tsx @@ -305,6 +305,20 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, reimbursementAcc PolicyUtils.goBackFromInvalidPolicy(); }, [policy, prevPolicy]); + // We are checking if the user can access the route. + // If user can't access the route, we are dismissing any modals that are open when the NotFound view is shown + const canAccessRoute = activeRoute && menuItems.some((item) => item.routeName === activeRoute); + + useEffect(() => { + if (!shouldShowNotFoundPage && canAccessRoute) { + return; + } + // We are dismissing any modals that are open when the NotFound view is shown + Navigation.isNavigationReady().then(() => { + Navigation.dismissRHP(); + }); + }, [canAccessRoute, policy, shouldShowNotFoundPage]); + const policyAvatar = useMemo(() => { if (!policy) { return {source: Expensicons.ExpensifyAppIcon, name: CONST.WORKSPACE_SWITCHER.NAME, type: CONST.ICON_TYPE_AVATAR}; diff --git a/src/pages/workspace/WorkspaceInviteMessagePage.tsx b/src/pages/workspace/WorkspaceInviteMessagePage.tsx index 2eaa38b865e6..a5c39cd92fe5 100644 --- a/src/pages/workspace/WorkspaceInviteMessagePage.tsx +++ b/src/pages/workspace/WorkspaceInviteMessagePage.tsx @@ -97,6 +97,9 @@ function WorkspaceInviteMessagePage({ setWelcomeNote(parser.htmlToMarkdown(getDefaultWelcomeNote())); return; } + if (isEmptyObject(policy)) { + return; + } Navigation.goBack(ROUTES.WORKSPACE_INVITE.getRoute(route.params.policyID), true); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index 0d723961a29e..ff47af2a0dde 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -7,16 +7,13 @@ import {InteractionManager, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import Badge from '@components/Badge'; -import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import Button from '@components/Button'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; import type {DropdownOption, WorkspaceMemberBulkActionType} from '@components/ButtonWithDropdownMenu/types'; import ConfirmModal from '@components/ConfirmModal'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; import * as Illustrations from '@components/Icon/Illustrations'; import MessagesRow from '@components/MessagesRow'; -import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; import TableListItem from '@components/SelectionList/TableListItem'; import type {ListItem, SelectionListHandle} from '@components/SelectionList/types'; @@ -47,6 +44,7 @@ import type {Errors, PendingAction} from '@src/types/onyx/OnyxCommon'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; +import WorkspacePageWithSections from './WorkspacePageWithSections'; type WorkspaceMembersPageOnyxProps = { /** Session info for the currently logged in user. */ @@ -59,7 +57,6 @@ type WorkspaceMembersPageProps = WithPolicyAndFullscreenLoadingProps & WithCurrentUserPersonalDetailsProps & WorkspaceMembersPageOnyxProps & StackScreenProps; - /** * Inverts an object, equivalent of _.invert */ @@ -71,7 +68,7 @@ function invertObject(object: Record): Record { type MemberOption = Omit & {accountID: number}; -function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, route, policy, session, currentUserPersonalDetails, isLoadingReportData = true}: WorkspaceMembersPageProps) { +function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, route, policy, session, currentUserPersonalDetails}: WorkspaceMembersPageProps) { const policyMemberEmailsToAccountIDs = useMemo(() => PolicyUtils.getMemberAccountIDsForWorkspace(policy?.employeeList), [policy?.employeeList]); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); @@ -524,71 +521,63 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, }; return ( - - - { - Navigation.goBack(); - }} - shouldShowBackButton={isSmallScreenWidth} - guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_MEMBERS} - > - {!isSmallScreenWidth && getHeaderButtons()} - - {isSmallScreenWidth && {getHeaderButtons()}} - setRemoveMembersConfirmModalVisible(false)} - prompt={translate('workspace.people.removeMembersPrompt')} - confirmText={translate('common.remove')} - cancelText={translate('common.cancel')} - onModalHide={() => { - InteractionManager.runAfterInteractions(() => { - if (!textInputRef.current) { - return; - } - textInputRef.current.focus(); - }); - }} - /> - - toggleUser(item.accountID)} - onSelectAll={() => toggleAllUsers(data)} - onDismissError={dismissError} - showLoadingPlaceholder={isLoading} - showScrollIndicator - shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} - textInputRef={textInputRef} - customListHeader={getCustomListHeader()} - listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]} + {() => ( + <> + {isSmallScreenWidth && {getHeaderButtons()}} + setRemoveMembersConfirmModalVisible(false)} + prompt={translate('workspace.people.removeMembersPrompt')} + confirmText={translate('common.remove')} + cancelText={translate('common.cancel')} + onModalHide={() => { + InteractionManager.runAfterInteractions(() => { + if (!textInputRef.current) { + return; + } + textInputRef.current.focus(); + }); + }} /> - - - + + + toggleUser(item.accountID)} + onSelectAll={() => toggleAllUsers(data)} + onDismissError={dismissError} + showLoadingPlaceholder={isLoading} + showScrollIndicator + shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} + textInputRef={textInputRef} + customListHeader={getCustomListHeader()} + listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]} + /> + + + )} + ); } diff --git a/src/pages/workspace/WorkspacePageWithSections.tsx b/src/pages/workspace/WorkspacePageWithSections.tsx index 58288f213818..b1ecc8124488 100644 --- a/src/pages/workspace/WorkspacePageWithSections.tsx +++ b/src/pages/workspace/WorkspacePageWithSections.tsx @@ -82,6 +82,12 @@ type WorkspacePageWithSectionsProps = WithPolicyAndFullscreenLoadingProps & * */ icon?: IconAsset; + /** Content to be added to the header */ + headerContent?: ReactNode; + + /** TestID of the component */ + testID?: string; + /** Whether the page is loading, example any other API call in progres */ isLoading?: boolean; }; @@ -112,6 +118,8 @@ function WorkspacePageWithSections({ shouldShowLoading = true, shouldShowOfflineIndicatorInWideScreen = false, shouldShowNonAdmin = false, + headerContent, + testID, shouldShowNotFoundPage = false, isLoading: isPageLoading = false, }: WorkspacePageWithSectionsProps) { @@ -160,7 +168,7 @@ function WorkspacePageWithSections({ includeSafeAreaPaddingBottom={false} shouldEnablePickerAvoiding={false} shouldEnableMaxHeight - testID={WorkspacePageWithSections.displayName} + testID={testID ?? WorkspacePageWithSections.displayName} shouldShowOfflineIndicatorInWideScreen={shouldShowOfflineIndicatorInWideScreen && !shouldShow} > Navigation.goBack(backButtonRoute)} icon={icon ?? undefined} style={styles.headerBarDesktopHeight} - /> + > + {headerContent} + {(isLoading || firstRender.current) && shouldShowLoading && isFocused ? ( ) : (