Skip to content

Commit

Permalink
Merge pull request #55816 from Expensify/yuwenmemon-cherry-pick-stagi…
Browse files Browse the repository at this point in the history
…ng-55815-1

🍒 Cherry pick PR #55815 to staging 🍒
  • Loading branch information
yuwenmemon authored Jan 27, 2025
2 parents 0a211a2 + 38ca5c7 commit b08a281
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 71 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1009008906
versionName "9.0.89-6"
versionCode 1009008907
versionName "9.0.89-7"
// Supported language variants must be declared here to avoid from being removed during the compilation.
// This also helps us to not include unnecessary language variants in the APK.
resConfigs "en", "es"
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>9.0.89.6</string>
<string>9.0.89.7</string>
<key>FullStory</key>
<dict>
<key>OrgId</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensifyTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>9.0.89.6</string>
<string>9.0.89.7</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion ios/NotificationServiceExtension/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<key>CFBundleShortVersionString</key>
<string>9.0.89</string>
<key>CFBundleVersion</key>
<string>9.0.89.6</string>
<string>9.0.89.7</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
"version": "9.0.89-6",
"version": "9.0.89-7",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
Expand Down
89 changes: 46 additions & 43 deletions src/libs/Navigation/AppNavigator/AuthScreens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {findFocusedRoute} from '@react-navigation/native';
import React, {memo, useEffect, useMemo, useRef, useState} from 'react';
import {NativeModules, View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import Onyx, {useOnyx} from 'react-native-onyx';
import Onyx, {withOnyx} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import ActiveGuidesEventListener from '@components/ActiveGuidesEventListener';
import ComposeProviders from '@components/ComposeProviders';
Expand Down Expand Up @@ -60,7 +60,6 @@ import SCREENS from '@src/SCREENS';
import type * as OnyxTypes from '@src/types/onyx';
import type {SelectedTimezone, Timezone} from '@src/types/onyx/PersonalDetails';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
import type ReactComponentModule from '@src/types/utils/ReactComponentModule';
import beforeRemoveReportOpenedFromSearchRHP from './beforeRemoveReportOpenedFromSearchRHP';
import CENTRAL_PANE_SCREENS from './CENTRAL_PANE_SCREENS';
Expand All @@ -78,6 +77,17 @@ import RightModalNavigator from './Navigators/RightModalNavigator';
import WelcomeVideoModalNavigator from './Navigators/WelcomeVideoModalNavigator';
import useRootNavigatorOptions from './useRootNavigatorOptions';

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 Down Expand Up @@ -229,10 +239,7 @@ const modalScreenListenersWithCancelSearch = {
},
};

function AuthScreens() {
const [session] = useOnyx(ONYXKEYS.SESSION);
const [lastOpenedPublicRoomID, lastOpenedPublicRoomIDStatus] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID);
const [initialLastUpdateIDAppliedToClient, initialLastUpdateIDAppliedToClientStatus] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT);
function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDAppliedToClient}: AuthScreensProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {shouldUseNarrowLayout} = useResponsiveLayout();
Expand All @@ -244,10 +251,6 @@ function AuthScreens() {

const modal = useRef<OnyxTypes.Modal>({});
const {isOnboardingCompleted} = useOnboardingFlowRouter();
const isLastOpenedPublicRoomIDLoading = isLoadingOnyxValue(lastOpenedPublicRoomIDStatus);
const isInitialLastUpdateIDAppliedToClientLoading = isLoadingOnyxValue(initialLastUpdateIDAppliedToClientStatus);
const isLastOpenedPublicRoomIDLoadedRef = useRef(false);
const isInitialLastUpdateIDAppliedToClientLoadedRef = useRef(false);

// On HybridApp we need to prevent flickering during transition to OldDot
const shouldRenderOnboardingExclusivelyOnHybridApp = useMemo(() => {
Expand All @@ -273,37 +276,6 @@ function AuthScreens() {
};
}, [theme]);

useEffect(() => {
if (isLastOpenedPublicRoomIDLoading || isLastOpenedPublicRoomIDLoadedRef.current) {
return;
}

isLastOpenedPublicRoomIDLoadedRef.current = true;
if (lastOpenedPublicRoomID) {
// Re-open the last opened public room if the user logged in from a public room link
Report.openLastOpenedPublicRoom(lastOpenedPublicRoomID);
}
}, [isLastOpenedPublicRoomIDLoading, lastOpenedPublicRoomID]);

useEffect(() => {
if (isInitialLastUpdateIDAppliedToClientLoading || isInitialLastUpdateIDAppliedToClientLoadedRef.current) {
return;
}

isInitialLastUpdateIDAppliedToClientLoadedRef.current = true;
// In Hybrid App we decide to call one of those method when booting ND and we don't want to duplicate calls
if (!NativeModules.HybridAppModule) {
// If we are on this screen then we are "logged in", but the user might not have "just logged in". They could be reopening the app
// or returning from background. If so, we'll assume they have some app data already and we can call reconnectApp() instead of openApp().
if (SessionUtils.didUserLogInDuringSession()) {
App.openApp();
} else {
Log.info('[AuthScreens] Sending ReconnectApp');
App.reconnectApp(initialLastUpdateIDAppliedToClient);
}
}
}, [initialLastUpdateIDAppliedToClient, isInitialLastUpdateIDAppliedToClientLoading]);

useEffect(() => {
const shortcutsOverviewShortcutConfig = CONST.KEYBOARD_SHORTCUTS.SHORTCUTS;
const searchShortcutConfig = CONST.KEYBOARD_SHORTCUTS.SEARCH;
Expand All @@ -324,12 +296,28 @@ function AuthScreens() {
PusherConnectionManager.init();
initializePusher();

// In Hybrid App we decide to call one of those method when booting ND and we don't want to duplicate calls
if (!NativeModules.HybridAppModule) {
// If we are on this screen then we are "logged in", but the user might not have "just logged in". They could be reopening the app
// or returning from background. If so, we'll assume they have some app data already and we can call reconnectApp() instead of openApp().
if (SessionUtils.didUserLogInDuringSession()) {
App.openApp();
} else {
Log.info('[AuthScreens] Sending ReconnectApp');
App.reconnectApp(initialLastUpdateIDAppliedToClient);
}
}

PriorityMode.autoSwitchToFocusMode();

App.setUpPoliciesAndNavigate(session);

App.redirectThirdPartyDesktopSignIn();

if (lastOpenedPublicRoomID) {
// Re-open the last opened public room if the user logged in from a public room link
Report.openLastOpenedPublicRoom(lastOpenedPublicRoomID);
}
Download.clearDownloads();

const unsubscribeOnyxModal = onyxSubscribe({
Expand Down Expand Up @@ -655,5 +643,20 @@ function AuthScreens() {

AuthScreens.displayName = 'AuthScreens';

// This memo is needed because <AuthScreens> is one of the main components in the app and navigation root and is relevant for the app performance.
export default memo(AuthScreens);
const AuthScreensMemoized = memo(AuthScreens, () => true);

// Migration to useOnyx cause re-login if logout from deeplinked report in desktop app
// Further analysis required and more details can be seen here:
// https://github.com/Expensify/App/issues/50560
// eslint-disable-next-line
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);
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {isCentralPaneName, isOnboardingFlowName} from '@libs/NavigationUtils';
import * as Welcome from '@userActions/Welcome';
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
import syncBrowserHistory from './syncBrowserHistory';

Expand Down Expand Up @@ -41,8 +40,13 @@ function insertRootRoute(state: State<RootStackParamList>, routeToInsert: Naviga
}

function compareAndAdaptState(state: StackNavigationState<RootStackParamList>) {
// If the state of the last path is not defined the getPathFromState won't work correctly.
if (!state?.routes.at(-1)?.state) {
return;
}

// We need to be sure that the bottom tab state is defined.
const topmostBottomTabRoute = getTopmostBottomTabRoute(state) ?? {name: SCREENS.HOME};
const topmostBottomTabRoute = getTopmostBottomTabRoute(state);
const isNarrowLayout = getIsNarrowLayout();

// This solutions is heuristics and will work for our cases. We may need to improve it in the future if we will have more cases to handle.
Expand All @@ -57,9 +61,7 @@ function compareAndAdaptState(state: StackNavigationState<RootStackParamList>) {
// We will generate a template state and compare the current state with it.
// If there is a difference in the screens that should be visible under the overlay, we will add the screen from templateState to the current state.
const pathFromCurrentState = getPathFromState(state, linkingConfig.config);
// If the state of the bottom tab has not been fully initialized, the generated path must be adjusted
const adjustedPath = pathFromCurrentState === `/${ROUTES.ROOT}` ? `/${ROUTES.REPORT}` : pathFromCurrentState;
const {adaptedState: templateState} = getAdaptedStateFromPath(adjustedPath, linkingConfig.config);
const {adaptedState: templateState} = getAdaptedStateFromPath(pathFromCurrentState, linkingConfig.config);

if (!templateState) {
return;
Expand Down
12 changes: 1 addition & 11 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,7 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
[SCREENS.REPORT_AVATAR]: ROUTES.REPORT_AVATAR.route,
[SCREENS.TRANSACTION_RECEIPT]: ROUTES.TRANSACTION_RECEIPT.route,
[SCREENS.WORKSPACE_JOIN_USER]: ROUTES.WORKSPACE_JOIN_USER.route,
[SCREENS.REPORT]: {
path: ROUTES.REPORT_WITH_ID.route,
// If params are defined, but reportID is explicitly undefined, we will get the url /r/undefined.
// We want to avoid that situation, so we will return an empty string instead.
parse: {
reportID: (reportID: string | undefined) => reportID ?? CONST.EMPTY_STRING,
},
stringify: {
reportID: (reportID: string | undefined) => reportID ?? CONST.EMPTY_STRING,
},
},
[SCREENS.REPORT]: ROUTES.REPORT_WITH_ID.route,
[SCREENS.SETTINGS.PROFILE.ROOT]: {
path: ROUTES.SETTINGS_PROFILE,
exact: true,
Expand Down
18 changes: 14 additions & 4 deletions src/libs/actions/Session/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {HybridAppRoute, Route} from '@src/ROUTES';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
import type Credentials from '@src/types/onyx/Credentials';
import type Session from '@src/types/onyx/Session';
import type {AutoAuthState} from '@src/types/onyx/Session';
Expand Down Expand Up @@ -825,11 +826,20 @@ function clearSignInData() {
}

/**
* Reset navigation state after logout
* Reset all current params of the Home route
*/
function resetNavigationState() {
function resetHomeRouteParams() {
Navigation.isNavigationReady().then(() => {
navigationRef.resetRoot(navigationRef.getRootState());
const routes = navigationRef.current?.getState()?.routes;
const homeRoute = routes?.find((route) => route.name === SCREENS.HOME);

const emptyParams: Record<string, undefined> = {};
Object.keys(homeRoute?.params ?? {}).forEach((paramKey) => {
emptyParams[paramKey] = undefined;
});

Navigation.setParams(emptyParams, homeRoute?.key ?? '');
Onyx.set(ONYXKEYS.IS_CHECKING_PUBLIC_ROOM, false);
});
}

Expand All @@ -848,7 +858,7 @@ function cleanupSession() {
PersistedRequests.clear();
NetworkConnection.clearReconnectionCallbacks();
SessionUtils.resetDidUserLogInDuringSession();
resetNavigationState();
resetHomeRouteParams();
clearCache().then(() => {
Log.info('Cleared all cache data', true, {}, true);
});
Expand Down

0 comments on commit b08a281

Please sign in to comment.