Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: three not found view v2 #41665

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a29d34e
Revert "[Revert] #36409 "Fix: three not found view""
kosmydel Apr 22, 2024
a535acb
fix #40509
kosmydel May 6, 2024
adf1ca4
fix one more issue on android
kosmydel May 6, 2024
c034221
Merge branch 'main' into @kosmydel/not-found-view-v2
kosmydel May 8, 2024
b513239
fix comment
kosmydel May 8, 2024
ce12e86
change type
kosmydel May 8, 2024
d175fb5
Merge branch 'main' into @kosmydel/not-found-view-v2
kosmydel May 15, 2024
4a9a77c
Merge branch 'main' into @kosmydel/not-found-view-v2
kosmydel May 28, 2024
16ca1c0
Merge branch 'main' into @kosmydel/not-found-view-v2
kosmydel May 29, 2024
35f21ea
Merge branch 'Expensify:main' into @kosmydel/not-found-view-v2
kosmydel Jun 13, 2024
92015a6
fix: empty ProfilePage
kosmydel Jun 14, 2024
54f1cff
Merge branch 'main' into @kosmydel/not-found-view-v2
kosmydel Jun 18, 2024
fcbe4ff
Merge branch 'Expensify:main' into @kosmydel/not-found-view-v2
kosmydel Jun 20, 2024
ffa8cf7
Merge branch 'main' into @kosmydel/not-found-view-v2
kosmydel Jun 26, 2024
145513d
Merge branch 'main' into @kosmydel/not-found-view-v2
kosmydel Jun 27, 2024
001a36b
fix: add concurrent mode support
kosmydel Jun 27, 2024
e76dd16
fix: double navigation
kosmydel Jun 27, 2024
04c420b
Merge branch 'main' into @kosmydel/not-found-view-v2
kosmydel Jul 2, 2024
6cca6df
fix: double navigation when selecting workspace in settings
kosmydel Jul 2, 2024
9487f61
continue previous commit
kosmydel Jul 2, 2024
9ec0333
refactor: WorkspaceMoreFeaturesPage and WorkspaceReportFieldsPage
kosmydel Jul 2, 2024
ad96e9e
fix
kosmydel Jul 3, 2024
37fc8c7
Merge branch 'main' into @kosmydel/not-found-view-v2
kosmydel Jul 3, 2024
6d269c3
modify AccessOrNotFoundWrapper
kosmydel Jul 3, 2024
4c50c13
small fix
kosmydel Jul 3, 2024
e8c80a3
Merge branch 'Expensify:main' into @kosmydel/not-found-view-v2
kosmydel Jul 4, 2024
ebfd706
Merge branch 'main' into @kosmydel/not-found-view-v2
kosmydel Jul 9, 2024
2a00bb9
remove flag
BrtqKr Jul 16, 2024
1488a51
Merge remote-tracking branch 'origin/main' into @kosmydel/not-found-v…
BrtqKr Jul 16, 2024
e60668b
prettier
kosmydel Jul 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,7 @@ const CONST = {
WORKSPACE_WORKFLOWS: 'WorkspaceWorkflows',
WORKSPACE_BANK_ACCOUNT: 'WorkspaceBankAccount',
WORKSPACE_SETTINGS: 'WorkspaceSettings',
WORKSPACE_FEATURES: 'WorkspaceFeatures',
},
get EXPENSIFY_EMAILS() {
return [
Expand Down
2 changes: 1 addition & 1 deletion src/libs/Navigation/linkTo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export default function linkTo(navigation: NavigationContainerRef<RootStackParam
}
}
// All actions related to FullScreenNavigator on wide screen are pushed when comparing differences between rootState and adaptedState.
if (action.payload.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR && !isNarrowLayout) {
if (action.payload.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR) {
return;
}
action.type = CONST.NAVIGATION.ACTION_TYPE.PUSH;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as ReportConnection from '@libs/ReportConnection';
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Screen} from '@src/SCREENS';
import SCREENS from '@src/SCREENS';
import CENTRAL_PANE_TO_RHP_MAPPING from './CENTRAL_PANE_TO_RHP_MAPPING';
import config from './config';
Expand All @@ -19,7 +20,7 @@ import getMatchingBottomTabRouteForState from './getMatchingBottomTabRouteForSta
import getMatchingCentralPaneRouteForState from './getMatchingCentralPaneRouteForState';
import replacePathInNestedState from './replacePathInNestedState';

const RHP_SCREENS_OPENED_FROM_LHN = [SCREENS.SETTINGS.SHARE_CODE, SCREENS.SETTINGS.PROFILE.STATUS] as const;
const RHP_SCREENS_OPENED_FROM_LHN = [SCREENS.SETTINGS.SHARE_CODE, SCREENS.SETTINGS.PROFILE.STATUS, SCREENS.SETTINGS.PREFERENCES.PRIORITY_MODE] satisfies Screen[];

type RHPScreenOpenedFromLHN = TupleToUnion<typeof RHP_SCREENS_OPENED_FROM_LHN>;

Expand Down Expand Up @@ -168,11 +169,6 @@ function getAdaptedState(state: PartialState<NavigationState<RootStackParamList>
const attachmentsScreen = state.routes.find((route) => route.name === SCREENS.ATTACHMENTS);
const featureTrainingModalNavigator = state.routes.find((route) => route.name === NAVIGATORS.FEATURE_TRANING_MODAL_NAVIGATOR);

if (isNarrowLayout) {
metainfo.isFullScreenNavigatorMandatory = false;
metainfo.isCentralPaneAndBottomTabMandatory = false;
}

if (rhpNavigator) {
// Routes
// - matching bottom tab
Expand Down
4 changes: 2 additions & 2 deletions src/pages/workspace/AccessOrNotFoundWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ function PageNotFoundFallback({policyID, shouldShowFullScreenFallback, fullPageN
return shouldShowFullScreenFallback ? (
<FullPageNotFoundView
shouldShow
onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)}
onBackButtonPress={() => Navigation.dismissModal()}
shouldForceFullScreen
// eslint-disable-next-line react/jsx-props-no-spreading
{...fullPageNotFoundViewProps}
Expand Down Expand Up @@ -155,7 +155,7 @@ function AccessOrNotFoundWrapper({accessVariants = [], fullPageNotFoundViewProps
return (
<PageNotFoundFallback
policyID={policyID}
shouldShowFullScreenFallback={!isFeatureEnabled}
shouldShowFullScreenFallback={!isFeatureEnabled || isPolicyNotAccessible}
fullPageNotFoundViewProps={fullPageNotFoundViewProps}
/>
);
Expand Down
21 changes: 20 additions & 1 deletion src/pages/workspace/WorkspaceInitialPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {useFocusEffect, useNavigationState} from '@react-navigation/native';
import type {StackScreenProps} from '@react-navigation/stack';
import React, {useCallback, useEffect, useMemo, useState} from 'react';
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
Expand Down Expand Up @@ -97,6 +97,7 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, reimbursementAcc
const activeRoute = useNavigationState(getTopmostRouteName);
const {translate} = useLocalize();
const {isOffline} = useNetwork();
const wasRendered = useRef(false);

const prevPendingFields = usePrevious(policy?.pendingFields);
const policyFeatureStates = useMemo(
Expand Down Expand Up @@ -347,6 +348,24 @@ 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;
}
if (wasRendered.current) {
return;
}
wasRendered.current = true;
// We are dismissing any modals that are open when the NotFound view is shown
Navigation.isNavigationReady().then(() => {
Navigation.closeRHPFlow();
});
}, [canAccessRoute, shouldShowNotFoundPage]);
Comment on lines +351 to +367
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workspace’s initial route (Workspace_Initial) wasn’t recognized as valid in canAccessRoute, causing premature RHP dismissal. This caused this issue: #53600
More details in this proposal: #53600 (comment)


const policyAvatar = useMemo(() => {
if (!policy) {
return {source: Expensicons.ExpensifyAppIcon, name: CONST.WORKSPACE_SWITCHER.NAME, type: CONST.ICON_TYPE_AVATAR};
Expand Down
3 changes: 3 additions & 0 deletions src/pages/workspace/WorkspaceInviteMessagePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,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-compiler/react-compiler, react-hooks/exhaustive-deps
}, []);
Expand Down
125 changes: 57 additions & 68 deletions src/pages/workspace/WorkspaceMembersPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -48,6 +45,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. */
Expand All @@ -71,7 +69,7 @@ function invertObject(object: Record<string, string>): Record<string, string> {

type MemberOption = Omit<ListItem, 'accountID'> & {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, true), [policy?.employeeList]);
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
Expand Down Expand Up @@ -526,74 +524,65 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft,
};

return (
<ScreenWrapper
includeSafeAreaPaddingBottom={false}
style={[styles.defaultModalContainer]}
<WorkspacePageWithSections
headerText={translate('workspace.common.members')}
route={route}
guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_MEMBERS}
headerContent={!isSmallScreenWidth && getHeaderButtons()}
icon={Illustrations.ReceiptWrangler}
testID={WorkspaceMembersPage.displayName}
shouldShowLoading={false}
shouldShowOfflineIndicatorInWideScreen
shouldShowNonAdmin
>
<FullPageNotFoundView
shouldShow={(isEmptyObject(policy) && !isLoadingReportData) || PolicyUtils.isPendingDeletePolicy(policy)}
subtitleKey={isEmptyObject(policy) ? undefined : 'workspace.common.notAuthorized'}
onBackButtonPress={PolicyUtils.goBackFromInvalidPolicy}
onLinkPress={PolicyUtils.goBackFromInvalidPolicy}
>
<HeaderWithBackButton
title={translate('workspace.common.members')}
icon={Illustrations.ReceiptWrangler}
onBackButtonPress={() => {
Navigation.goBack();
}}
shouldShowBackButton={isSmallScreenWidth}
guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_MEMBERS}
>
{!isSmallScreenWidth && getHeaderButtons()}
</HeaderWithBackButton>
{isSmallScreenWidth && <View style={[styles.pl5, styles.pr5]}>{getHeaderButtons()}</View>}
<ConfirmModal
danger
title={translate('workspace.people.removeMembersTitle')}
isVisible={removeMembersConfirmModalVisible}
onConfirm={removeUsers}
onCancel={() => setRemoveMembersConfirmModalVisible(false)}
prompt={confirmModalPrompt}
confirmText={translate('common.remove')}
cancelText={translate('common.cancel')}
onModalHide={() => {
InteractionManager.runAfterInteractions(() => {
if (!textInputRef.current) {
return;
}
textInputRef.current.focus();
});
}}
/>
<View style={[styles.w100, styles.flex1]}>
<SelectionList
ref={selectionListRef}
canSelectMultiple={isPolicyAdmin}
sections={[{data, isDisabled: false}]}
ListItem={TableListItem}
shouldUseUserSkeletonView
disableKeyboardShortcuts={removeMembersConfirmModalVisible}
headerMessage={getHeaderMessage()}
headerContent={!isSmallScreenWidth && getHeaderContent()}
onSelectRow={openMemberDetails}
shouldDebounceRowSelect={!isPolicyAdmin}
onCheckboxPress={(item) => toggleUser(item.accountID)}
onSelectAll={() => toggleAllUsers(data)}
onDismissError={dismissError}
showLoadingPlaceholder={isLoading}
shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()}
textInputRef={textInputRef}
customListHeader={getCustomListHeader()}
listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]}
listHeaderContent={isSmallScreenWidth ? <View style={[styles.pl5, styles.pr5]}>{getHeaderContent()}</View> : null}
showScrollIndicator={false}
{() => (
<>
{isSmallScreenWidth && <View style={[styles.pl5, styles.pr5]}>{getHeaderButtons()}</View>}
<ConfirmModal
danger
title={translate('workspace.people.removeMembersTitle')}
isVisible={removeMembersConfirmModalVisible}
onConfirm={removeUsers}
onCancel={() => setRemoveMembersConfirmModalVisible(false)}
prompt={confirmModalPrompt}
confirmText={translate('common.remove')}
cancelText={translate('common.cancel')}
onModalHide={() => {
InteractionManager.runAfterInteractions(() => {
if (!textInputRef.current) {
return;
}
textInputRef.current.focus();
});
}}
/>
</View>
</FullPageNotFoundView>
</ScreenWrapper>
<View style={[styles.w100, styles.flex1]}>
<SelectionList
ref={selectionListRef}
canSelectMultiple={isPolicyAdmin}
sections={[{data, isDisabled: false}]}
ListItem={TableListItem}
shouldUseUserSkeletonView
disableKeyboardShortcuts={removeMembersConfirmModalVisible}
headerMessage={getHeaderMessage()}
headerContent={!isSmallScreenWidth && getHeaderContent()}
onSelectRow={openMemberDetails}
shouldDebounceRowSelect={!isPolicyAdmin}
onCheckboxPress={(item) => toggleUser(item.accountID)}
onSelectAll={() => toggleAllUsers(data)}
onDismissError={dismissError}
showLoadingPlaceholder={isLoading}
shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()}
textInputRef={textInputRef}
customListHeader={getCustomListHeader()}
listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]}
listHeaderContent={isSmallScreenWidth ? <View style={[styles.pl5, styles.pr5]}>{getHeaderContent()}</View> : null}
showScrollIndicator={false}
/>
</View>
</>
)}
</WorkspacePageWithSections>
);
}

Expand Down
14 changes: 12 additions & 2 deletions src/pages/workspace/WorkspacePageWithSections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -112,6 +118,8 @@ function WorkspacePageWithSections({
shouldShowLoading = true,
shouldShowOfflineIndicatorInWideScreen = false,
shouldShowNonAdmin = false,
headerContent,
testID,
shouldShowNotFoundPage = false,
isLoading: isPageLoading = false,
}: WorkspacePageWithSectionsProps) {
Expand Down Expand Up @@ -160,7 +168,7 @@ function WorkspacePageWithSections({
includeSafeAreaPaddingBottom={false}
shouldEnablePickerAvoiding={false}
shouldEnableMaxHeight
testID={WorkspacePageWithSections.displayName}
testID={testID ?? WorkspacePageWithSections.displayName}
shouldShowOfflineIndicatorInWideScreen={shouldShowOfflineIndicatorInWideScreen && !shouldShow}
>
<FullPageNotFoundView
Expand All @@ -177,7 +185,9 @@ function WorkspacePageWithSections({
onBackButtonPress={() => Navigation.goBack(backButtonRoute)}
icon={icon ?? undefined}
style={styles.headerBarDesktopHeight}
/>
>
{headerContent}
</HeaderWithBackButton>
{(isLoading || firstRender.current) && shouldShowLoading && isFocused ? (
<FullScreenLoadingIndicator style={[styles.flex1, styles.pRelative]} />
) : (
Expand Down
4 changes: 3 additions & 1 deletion src/pages/workspace/WorkspaceProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,13 @@ function WorkspaceProfilePage({policyDraft, policy: policyProp, currencyList = {
headerText={translate('workspace.common.profile')}
route={route}
guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_PROFILE}
shouldShowLoading={false}
// When we create a new workspaces, the policy prop will not be set on the first render. Therefore, we have to delay rendering until it has been set in Onyx.
shouldShowLoading={policy === undefined}
shouldUseScrollView
shouldShowOfflineIndicatorInWideScreen
shouldShowNonAdmin
icon={Illustrations.House}
shouldShowNotFoundPage={policy === undefined}
>
{(hasVBA?: boolean) => (
<View style={[styles.flex1, styles.mt3, isSmallScreenWidth ? styles.workspaceSectionMobile : styles.workspaceSection]}>
Expand Down
Loading