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 long loading from public and redirect to last accessed report #50278

Merged
38 changes: 9 additions & 29 deletions src/libs/Navigation/AppNavigator/AuthScreens.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, {memo, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import Onyx, {withOnyx} from 'react-native-onyx';
import Onyx, {useOnyx} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import ActiveGuidesEventListener from '@components/ActiveGuidesEventListener';
import ComposeProviders from '@components/ComposeProviders';
import {useSession} from '@components/OnyxProvider';
import OptionsListContextProvider from '@components/OptionListContextProvider';
import {SearchContextProvider} from '@components/Search/SearchContext';
import SearchRouterModal from '@components/Search/SearchRouter/SearchRouterModal';
Expand All @@ -22,6 +23,7 @@ import Log from '@libs/Log';
import getCurrentUrl from '@libs/Navigation/currentUrl';
import getOnboardingModalScreenOptions from '@libs/Navigation/getOnboardingModalScreenOptions';
import Navigation from '@libs/Navigation/Navigation';
import shouldOpenOnAdminRoom from '@libs/Navigation/shouldOpenOnAdminRoom';
import type {AuthScreensParamList, CentralPaneName, CentralPaneScreensParamList} from '@libs/Navigation/types';
import NetworkConnection from '@libs/NetworkConnection';
import onyxSubscribe from '@libs/onyxSubscribe';
Expand Down Expand Up @@ -67,17 +69,6 @@ import OnboardingModalNavigator from './Navigators/OnboardingModalNavigator';
import RightModalNavigator from './Navigators/RightModalNavigator';
import WelcomeVideoModalNavigator from './Navigators/WelcomeVideoModalNavigator';

type AuthScreensProps = {
/** Session of currently logged in user */
session: OnyxEntry<OnyxTypes.Session>;

/** The report ID of the last opened public room as anonymous user */
lastOpenedPublicRoomID: OnyxEntry<string>;

/** The last Onyx update ID was applied to the client */
initialLastUpdateIDAppliedToClient: OnyxEntry<number>;
};

const loadReportAttachments = () => require<ReactComponentModule>('../../../pages/home/report/ReportAttachments').default;
const loadValidateLoginPage = () => require<ReactComponentModule>('../../../pages/ValidateLoginPage').default;
const loadLogOutPreviousUserPage = () => require<ReactComponentModule>('../../../pages/LogOutPreviousUserPage').default;
Expand All @@ -90,11 +81,6 @@ const loadReportAvatar = () => require<ReactComponentModule>('../../../pages/Rep
const loadReceiptView = () => require<ReactComponentModule>('../../../pages/TransactionReceiptPage').default;
const loadWorkspaceJoinUser = () => require<ReactComponentModule>('@pages/workspace/WorkspaceJoinUserPage').default;

function shouldOpenOnAdminRoom() {
const url = getCurrentUrl();
return url ? new URL(url).searchParams.get('openOnAdminRoom') === 'true' : false;
}

function getCentralPaneScreenInitialParams(screenName: CentralPaneName, initialReportID?: string): Partial<ValueOf<CentralPaneScreensParamList>> {
if (screenName === SCREENS.SEARCH.CENTRAL_PANE) {
// Generate default query string with buildSearchQueryString without argument.
Expand Down Expand Up @@ -226,7 +212,7 @@ const modalScreenListenersWithCancelSearch = {
},
};

function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDAppliedToClient}: AuthScreensProps) {
function AuthScreens() {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, isSmallScreenWidth} = useResponsiveLayout();
Expand All @@ -243,6 +229,10 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
const {isOnboardingCompleted} = useOnboardingFlowRouter();
let initialReportID: string | undefined;
const isInitialRender = useRef(true);
const session = useSession();
const [lastOpenedPublicRoomID] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID);
const [initialLastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT);

if (isInitialRender.current) {
Timing.start(CONST.TIMING.HOMEPAGE_INITIAL_RENDER);

Expand Down Expand Up @@ -602,14 +592,4 @@ AuthScreens.displayName = 'AuthScreens';

const AuthScreensMemoized = memo(AuthScreens, () => true);

export default withOnyx<AuthScreensProps, AuthScreensProps>({
session: {
key: ONYXKEYS.SESSION,
},
lastOpenedPublicRoomID: {
key: ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID,
},
initialLastUpdateIDAppliedToClient: {
key: ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT,
},
})(AuthScreensMemoized);
export default AuthScreensMemoized;
6 changes: 6 additions & 0 deletions src/libs/Navigation/shouldOpenOnAdminRoom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import getCurrentUrl from './currentUrl';

export default function shouldOpenOnAdminRoom() {
const url = getCurrentUrl();
return url ? new URL(url).searchParams.get('openOnAdminRoom') === 'true' : false;
}
7 changes: 0 additions & 7 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ import * as CurrencyUtils from './CurrencyUtils';
import DateUtils from './DateUtils';
import {hasValidDraftComment} from './DraftCommentUtils';
import getAttachmentDetails from './fileDownload/getAttachmentDetails';
import getIsSmallScreenWidth from './getIsSmallScreenWidth';
import isReportMessageAttachment from './isReportMessageAttachment';
import localeCompare from './LocaleCompare';
import * as LocalePhoneNumber from './LocalePhoneNumber';
Expand Down Expand Up @@ -1360,12 +1359,6 @@ function findLastAccessedReport(ignoreDomainRooms: boolean, openOnAdminRoom = fa
});
}

// if the user hasn't completed the onboarding flow, whether the user should be in the concierge chat or system chat
// should be consistent with what chat the user will land after onboarding flow
if (!getIsSmallScreenWidth() && !Array.isArray(onboarding) && !onboarding?.hasCompletedGuidedSetupFlow) {
return reportsValues.find(isChatUsedForOnboarding);
}

// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const shouldFilter = excludeReportID || ignoreDomainRooms;
if (shouldFilter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,40 @@ import ScreenWrapper from '@components/ScreenWrapper';
import Text from '@components/Text';
import TextInput from '@components/TextInput';
import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import usePermissions from '@hooks/usePermissions';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import * as ErrorUtils from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import shouldOpenOnAdminRoom from '@libs/Navigation/shouldOpenOnAdminRoom';
import * as ReportUtils from '@libs/ReportUtils';
import * as ValidationUtils from '@libs/ValidationUtils';
import * as PersonalDetails from '@userActions/PersonalDetails';
import * as Report from '@userActions/Report';
import * as Welcome from '@userActions/Welcome';
import * as OnboardingFlow from '@userActions/Welcome/OnboardingFlow';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import INPUT_IDS from '@src/types/form/DisplayNameForm';
import type {BaseOnboardingPersonalDetailsProps} from './types';

function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNativeStyles, route}: BaseOnboardingPersonalDetailsProps) {
function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNativeStyles}: BaseOnboardingPersonalDetailsProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const [onboardingPurposeSelected] = useOnyx(ONYXKEYS.ONBOARDING_PURPOSE_SELECTED);
const [onboardingAdminsChatReportID] = useOnyx(ONYXKEYS.ONBOARDING_ADMINS_CHAT_REPORT_ID);
const [onboardingPolicyID] = useOnyx(ONYXKEYS.ONBOARDING_POLICY_ID);
const {shouldUseNarrowLayout, isSmallScreenWidth, onboardingIsMediumOrLargerScreenWidth} = useResponsiveLayout();
const {isSmallScreenWidth, onboardingIsMediumOrLargerScreenWidth} = useResponsiveLayout();
const {inputCallbackRef} = useAutoFocusInput();
const [shouldValidateOnChange, setShouldValidateOnChange] = useState(false);
const {isOffline} = useNetwork();
const {canUseDefaultRooms} = usePermissions();
const {activeWorkspaceID} = useActiveWorkspace();

useEffect(() => {
Welcome.setOnboardingErrorMessage('');
Expand Down Expand Up @@ -69,13 +76,20 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat

Navigation.dismissModal();

// Only navigate to concierge chat when central pane is visible
// Otherwise stay on the chats screen.
if (!shouldUseNarrowLayout && !route.params?.backTo) {
Report.navigateToConciergeChat();
// When hasCompletedGuidedSetupFlow is true, OnboardingModalNavigator in AuthScreen is removed from the navigation stack.
// On small screens, this removal redirects navigation to HOME. Dismissing the modal doesn't work properly,
// so we need to specifically navigate to the last accessed report.
if (!isSmallScreenWidth) {
return;
}
const lastAccessedReportID = ReportUtils.findLastAccessedReport(!canUseDefaultRooms, shouldOpenOnAdminRoom(), activeWorkspaceID)?.reportID;
if (!lastAccessedReportID) {
return;
}
const lastAccessedReportRoute = ROUTES.REPORT_WITH_ID.getRoute(lastAccessedReportID ?? '-1');
Navigation.navigate(lastAccessedReportRoute);
},
[onboardingPurposeSelected, onboardingAdminsChatReportID, onboardingPolicyID, shouldUseNarrowLayout, route.params?.backTo],
[onboardingPurposeSelected, onboardingAdminsChatReportID, onboardingPolicyID, activeWorkspaceID, canUseDefaultRooms, isSmallScreenWidth],
);

const validate = (values: FormOnyxValues<'onboardingPersonalDetailsForm'>) => {
Expand Down
27 changes: 12 additions & 15 deletions src/pages/signin/SignInModal.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@
import React, {useEffect, useRef} from 'react';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import {useSession} from '@components/OnyxProvider';
import ScreenWrapper from '@components/ScreenWrapper';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import Navigation from '@libs/Navigation/Navigation';
import {waitForIdle} from '@libs/Network/SequentialQueue';
import * as App from '@userActions/App';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import SCREENS from '@src/SCREENS';
import type {Session} from '@src/types/onyx';
import SignInPage from './SignInPage';
import type {SignInPageRef} from './SignInPage';

type SignInModalOnyxProps = {
session: OnyxEntry<Session>;
};

type SignInModalProps = SignInModalOnyxProps;

function SignInModal({session}: SignInModalProps) {
function SignInModal() {
const theme = useTheme();
const StyleUtils = useStyleUtils();
const siginPageRef = useRef<SignInPageRef | null>(null);
const session = useSession();

useEffect(() => {
const isAnonymousUser = session?.authTokenType === CONST.AUTH_TOKEN_TYPES.ANONYMOUS;
if (!isAnonymousUser) {
// Signing in RHP is only for anonymous users
Navigation.isNavigationReady().then(() => Navigation.dismissModal());
App.openApp();

// To prevent deadlock when OpenReport and OpenApp overlap, wait for the queue to be idle before calling openApp.
// This ensures that any communication gaps between the client and server during OpenReport processing do not cause the queue to pause,
// which would prevent us from processing or clearing the queue.
waitForIdle().then(() => {
App.openApp();
});
}
}, [session?.authTokenType]);

Expand Down Expand Up @@ -61,6 +60,4 @@ function SignInModal({session}: SignInModalProps) {

SignInModal.displayName = 'SignInModal';

export default withOnyx<SignInModalProps, SignInModalOnyxProps>({
session: {key: ONYXKEYS.SESSION},
})(SignInModal);
export default SignInModal;
Loading