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: WS switcher blank screen, keep workspace history #54030

Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,5 1,5 @@
diff --git a/node_modules/react-native-screens/ios/RNSScreenStackAnimator.mm b/node_modules/react-native-screens/ios/RNSScreenStackAnimator.mm
index abb2cf6..fb81d52 100644
index abb2cf6..c21b3e9 100644
--- a/node_modules/react-native-screens/ios/RNSScreenStackAnimator.mm
b/node_modules/react-native-screens/ios/RNSScreenStackAnimator.mm
@@ -5,13 5,14 @@
Expand Down Expand Up @@ -32,7 32,7 @@ index abb2cf6..fb81d52 100644
}
@@ -129,6 130,8 @@ - (void)animateSimplePushWithShadowEnabled:(BOOL)shadowEnabled
}

[UIView animateWithDuration:[self transitionDuration:transitionContext]
delay:0
options:UIViewAnimationOptionCurveDefaultTransition
Expand Down Expand Up @@ -66,25 66,7 @@ index abb2cf6..fb81d52 100644
animations:animationBlock
completion:completionBlock];
} else {
@@ -251,6 260,8 @@ - (void)animateFadeWithTransitionContext:(id<UIViewControllerContextTransitionin
[[transitionContext containerView] addSubview:toViewController.view];
toViewController.view.alpha = 0.0;
[UIView animateWithDuration:[self transitionDuration:transitionContext]
delay:0
options:UIViewAnimationOptionCurveDefaultTransition
animations:^{
toViewController.view.alpha = 1.0;
}
@@ -262,6 273,8 @@ - (void)animateFadeWithTransitionContext:(id<UIViewControllerContextTransitionin
[[transitionContext containerView] insertSubview:toViewController.view belowSubview:fromViewController.view];

[UIView animateWithDuration:[self transitionDuration:transitionContext]
delay:0
options:UIViewAnimationOptionCurveDefaultTransition
animations:^{
fromViewController.view.alpha = 0.0;
}
@@ -284,6 297,8 @@ - (void)animateSlideFromBottomWithTransitionContext:(id<UIViewControllerContextT
@@ -284,6 293,8 @@ - (void)animateSlideFromBottomWithTransitionContext:(id<UIViewControllerContextT
toViewController.view.transform = topBottomTransform;
[[transitionContext containerView] addSubview:toViewController.view];
[UIView animateWithDuration:[self transitionDuration:transitionContext]
Expand All @@ -93,7 75,7 @@ index abb2cf6..fb81d52 100644
animations:^{
fromViewController.view.transform = CGAffineTransformIdentity;
toViewController.view.transform = CGAffineTransformIdentity;
@@ -309,6 324,8 @@ - (void)animateSlideFromBottomWithTransitionContext:(id<UIViewControllerContextT
@@ -309,6 320,8 @@ - (void)animateSlideFromBottomWithTransitionContext:(id<UIViewControllerContextT

if (!transitionContext.isInteractive) {
[UIView animateWithDuration:[self transitionDuration:transitionContext]
Expand Down
10 changes: 2 additions & 8 deletions src/components/WorkspaceSwitcherButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 18,9 @@
policy: OnyxEntry<Policy>;
};

type WorkspaceSwitcherButtonProps = WorkspaceSwitcherButtonOnyxProps & {
/**
* Callback used to keep track of the workspace switching process in the BaseSidebarScreen.
*/
onSwitchWorkspace?: () => void;
};
type WorkspaceSwitcherButtonProps = WorkspaceSwitcherButtonOnyxProps;

function WorkspaceSwitcherButton({policy, onSwitchWorkspace}: WorkspaceSwitcherButtonProps) {
function WorkspaceSwitcherButton({policy}: WorkspaceSwitcherButtonProps) {
const {translate} = useLocalize();
const theme = useTheme();

Expand All @@ -41,7 36,7 @@
source: avatar,
name: policy?.name ?? '',
type: CONST.ICON_TYPE_WORKSPACE,
id: policy?.id ?? '-1',

Check failure on line 39 in src/components/WorkspaceSwitcherButton.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

};
}, [policy]);

Expand All @@ -54,7 49,6 @@
accessible
testID="WorkspaceSwitcherButton"
onPress={() => {
onSwitchWorkspace?.();
pressableRef?.current?.blur();
interceptAnonymousUser(() => {
Navigation.navigate(ROUTES.WORKSPACE_SWITCHER);
Expand Down
3 changes: 2 additions & 1 deletion src/libs/Navigation/AppNavigator/AuthScreens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 25,7 @@
import NavBarManager from '@libs/NavBarManager';
import getCurrentUrl from '@libs/Navigation/currentUrl';
import Navigation, {navigationRef} from '@libs/Navigation/Navigation';
import Animations from '@libs/Navigation/PlatformStackNavigation/navigationOptions/animation';
import Presentation from '@libs/Navigation/PlatformStackNavigation/navigationOptions/presentation';
import type {PlatformStackNavigationOptions} from '@libs/Navigation/PlatformStackNavigation/types';
import shouldOpenOnAdminRoom from '@libs/Navigation/shouldOpenOnAdminRoom';
Expand Down Expand Up @@ -147,7 148,7 @@
return;
}

currentAccountID = value.accountID ?? -1;

Check failure on line 151 in src/libs/Navigation/AppNavigator/AuthScreens.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check


if (Navigation.isActiveRoute(ROUTES.SIGN_IN_MODAL)) {
// This means sign in in RHP was successful, so we can subscribe to user events
Expand Down Expand Up @@ -249,7 250,7 @@
}

const initialReport = ReportUtils.findLastAccessedReport(!canUseDefaultRooms, shouldOpenOnAdminRoom(), activeWorkspaceID);
return initialReport?.reportID ?? '';

Check failure on line 253 in src/libs/Navigation/AppNavigator/AuthScreens.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

});

useEffect(() => {
Expand Down Expand Up @@ -464,7 465,7 @@
options={{
headerShown: false,
presentation: Presentation.TRANSPARENT_MODAL,
animation: 'none',
animation: Animations.NONE,
}}
getComponent={loadProfileAvatar}
listeners={modalScreenListeners}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 22,9 @@ type TopBarProps = {
activeWorkspaceID?: string;
shouldDisplaySearch?: boolean;
shouldDisplayCancelSearch?: boolean;

/**
* Callback used to keep track of the workspace switching process in the BaseSidebarScreen.
* Passed to the WorkspaceSwitcherButton component.
*/
onSwitchWorkspace?: () => void;
};

function TopBar({breadcrumbLabel, activeWorkspaceID, shouldDisplaySearch = true, shouldDisplayCancelSearch = false, onSwitchWorkspace}: TopBarProps) {
function TopBar({breadcrumbLabel, activeWorkspaceID, shouldDisplaySearch = true, shouldDisplayCancelSearch = false}: TopBarProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const policy = usePolicy(activeWorkspaceID);
Expand All @@ -53,10 47,7 @@ function TopBar({breadcrumbLabel, activeWorkspaceID, shouldDisplaySearch = true,
dataSet={{dragArea: true}}
>
<View style={[styles.flex1, styles.flexRow, styles.alignItemsCenter, styles.ml2]}>
<WorkspaceSwitcherButton
policy={policy}
onSwitchWorkspace={onSwitchWorkspace}
/>
<WorkspaceSwitcherButton policy={policy} />

<View style={[styles.ml3, styles.flex1]}>
<Breadcrumbs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 2,14 @@ import type {ParamListBase} from '@react-navigation/native';
import {createNavigatorFactory} from '@react-navigation/native';
import React from 'react';
import createPlatformStackNavigatorComponent from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent';
import Animations from '@libs/Navigation/PlatformStackNavigation/navigationOptions/animation';
import type {ExtraContentProps, PlatformStackNavigationEventMap, PlatformStackNavigationOptions, PlatformStackNavigationState} from '@libs/Navigation/PlatformStackNavigation/types';
import BottomTabBar from './BottomTabBar';
import BottomTabNavigationContentWrapper from './BottomTabNavigationContentWrapper';
import useCustomState from './useCustomState';

const defaultScreenOptions: PlatformStackNavigationOptions = {
animation: 'none',
animation: Animations.NONE,
};

function ExtraContent({state}: ExtraContentProps) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@ const InternalPlatformAnimations = {
IOS_FROM_LEFT: 'ios_from_left',
IOS_FROM_RIGHT: 'ios_from_right',
SIMPLE_PUSH: 'simple_push',
NONE: 'none',
} as const;

const Animations = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 1,10 @@
import type {NativeStackNavigationOptions} from '@react-navigation/native-stack';
import Animations from '..';
import {InternalPlatformAnimations} from '..';
import type NoneTransitionNavigationOptions from './types';

const none: NoneTransitionNavigationOptions = {animation: Animations.NONE, gestureEnabled: false} satisfies NativeStackNavigationOptions;
const none: NoneTransitionNavigationOptions = {
animation: InternalPlatformAnimations.NONE,
gestureEnabled: false,
} satisfies NativeStackNavigationOptions;

export default none;
13 changes: 1 addition & 12 deletions src/libs/Navigation/switchPolicyID.ts
Original file line number Diff line number Diff line change
@@ -1,4 1,4 @@
import {CommonActions, getActionFromState} from '@react-navigation/core';
import {getActionFromState} from '@react-navigation/core';
import type {NavigationAction, NavigationContainerRef, NavigationState, PartialState} from '@react-navigation/native';
import {getPathFromState} from '@react-navigation/native';
import type {Writable} from 'type-fest';
Expand Down Expand Up @@ -52,17 52,6 @@ function getActionForBottomTabNavigator(action: StackNavigationAction, state: Na
params.policyID = policyID;
}

// If the last route in the BottomTabNavigator is already a 'Home' route, we want to change the params rather than pushing a new 'Home' route,
// so that the screen does not get re-mounted. This would cause an empty screen/white flash when navigating back from the workspace switcher.
const homeRoute = bottomTabNavigatorRoute.state.routes.at(-1);
if (homeRoute && homeRoute.name === SCREENS.HOME) {
return {
...CommonActions.setParams(params),
source: homeRoute?.key,
};
}

// If there is no 'Home' route in the BottomTabNavigator or if we are updating a different navigator, we want to push a new route.
return {
type: CONST.NAVIGATION.ACTION_TYPE.PUSH,
payload: {
Expand Down
5 changes: 4 additions & 1 deletion src/pages/WorkspaceSwitcherPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 20,7 @@
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import switchPolicyAfterInteractions from './switchPolicyAfterInteractions';
import WorkspaceCardCreateAWorkspace from './WorkspaceCardCreateAWorkspace';

type WorkspaceListItem = {
Expand Down Expand Up @@ -87,7 88,9 @@
setActiveWorkspaceID(newPolicyID);
Navigation.goBack();
if (newPolicyID !== activeWorkspaceID) {
Navigation.navigateWithSwitchPolicyID({policyID: newPolicyID});
// On native platforms, we will see a blank screen if we navigate to a new HomeScreen route while navigating back at the same time.
// Therefore we delay switching the workspace until after back navigation, using the InteractionManager.
switchPolicyAfterInteractions(newPolicyID);
}
},
[activeWorkspaceID, setActiveWorkspaceID, isFocused],
Expand All @@ -102,7 105,7 @@
.filter((policy) => PolicyUtils.shouldShowPolicy(policy, !!isOffline, currentUserLogin) && !policy?.isJoinRequestPending)
.map((policy) => ({
text: policy?.name ?? '',
policyID: policy?.id ?? '-1',

Check failure on line 108 in src/pages/WorkspaceSwitcherPage/index.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

brickRoadIndicator: getIndicatorTypeForPolicy(policy?.id),
icons: [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 1,10 @@
import {InteractionManager} from 'react-native';
import Navigation from '@libs/Navigation/Navigation';

function switchPolicyAfterInteractions(newPolicyID: string | undefined) {
InteractionManager.runAfterInteractions(() => {
Navigation.navigateWithSwitchPolicyID({policyID: newPolicyID});
});
}

export default switchPolicyAfterInteractions;
Original file line number Diff line number Diff line change
@@ -0,0 1,7 @@
import Navigation from '@libs/Navigation/Navigation';

function switchPolicyAfterInteractions(newPolicyID: string | undefined) {
Navigation.navigateWithSwitchPolicyID({policyID: newPolicyID});
}

export default switchPolicyAfterInteractions;
19 changes: 2 additions & 17 deletions src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,4 1,4 @@
import React, {useEffect, useRef} from 'react';
import React, {useEffect} from 'react';
import {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import ScreenWrapper from '@components/ScreenWrapper';
Expand All @@ -21,32 21,18 @@
const activeWorkspaceID = useActiveWorkspaceFromNavigationState();
const {translate} = useLocalize();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const [activeWorkspace] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activeWorkspaceID ?? -1}`);

Check failure on line 24 in src/pages/home/sidebar/SidebarScreen/BaseSidebarScreen.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check


useEffect(() => {
Performance.markStart(CONST.TIMING.SIDEBAR_LOADED);
Timing.start(CONST.TIMING.SIDEBAR_LOADED);
}, []);

const isSwitchingWorkspace = useRef(false);
useEffect(() => {
// Whether the active workspace or the "Everything" page is loaded
const isWorkspaceOrEverythingLoaded = !!activeWorkspace || activeWorkspaceID === undefined;

// If we are currently switching workspaces, we don't want to do anything until the target workspace is loaded
if (isSwitchingWorkspace.current) {
if (isWorkspaceOrEverythingLoaded) {
isSwitchingWorkspace.current = false;
}
return;
}

// Otherwise, if the workspace is already loaded, we don't need to do anything
if (isWorkspaceOrEverythingLoaded) {
if (!!activeWorkspace || activeWorkspaceID === undefined) {
return;
}

isSwitchingWorkspace.current = true;
Navigation.navigateWithSwitchPolicyID({policyID: undefined});
updateLastAccessedWorkspace(undefined);
}, [activeWorkspace, activeWorkspaceID]);
Expand All @@ -67,7 53,6 @@
breadcrumbLabel={translate('common.inbox')}
activeWorkspaceID={activeWorkspaceID}
shouldDisplaySearch={shouldDisplaySearch}
onSwitchWorkspace={() => (isSwitchingWorkspace.current = true)}
/>
<View style={[styles.flex1]}>
<SidebarLinksData insets={insets} />
Expand Down
Loading