Skip to content

Commit

Permalink
Merge pull request #192 from software-mansion-labs/splits/goBackToHome
Browse files Browse the repository at this point in the history
Fix issue: Android - Chat - "Go back to homepage" link, leads to chat again and not to inbox
  • Loading branch information
adamgrzybowski authored Jan 31, 2025
2 parents 445f747 + 38c0fd1 commit 007b1ff
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 14 deletions.
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ComposeProviders from './components/ComposeProviders';
import CustomStatusBarAndBackground from './components/CustomStatusBarAndBackground';
import CustomStatusBarAndBackgroundContextProvider from './components/CustomStatusBarAndBackground/CustomStatusBarAndBackgroundContextProvider';
import ErrorBoundary from './components/ErrorBoundary';
import FullScreenBlockingViewContextProvider from './components/FullScreenBlockingViewContextProvider';
import HTMLEngineProvider from './components/HTMLEngineProvider';
import InitialURLContextProvider from './components/InitialURLContextProvider';
import {InputBlurContextProvider} from './components/InputBlurContext';
Expand Down Expand Up @@ -96,6 +97,7 @@ function App({url}: AppProps) {
SearchRouterContextProvider,
ProductTrainingContextProvider,
InputBlurContextProvider,
FullScreenBlockingViewContextProvider,
]}
>
<CustomStatusBarAndBackground />
Expand Down
14 changes: 13 additions & 1 deletion src/components/BlockingViews/ForceFullScreenView/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import React from 'react';
import {useRoute} from '@react-navigation/native';
import React, {useContext, useEffect} from 'react';
import {View} from 'react-native';
import {FullScreenBlockingViewContext} from '@components/FullScreenBlockingViewContextProvider';
import useThemeStyles from '@hooks/useThemeStyles';
import type ForceFullScreenViewProps from './types';

function ForceFullScreenView({children, shouldForceFullScreen = false}: ForceFullScreenViewProps) {
const route = useRoute();
const styles = useThemeStyles();
const {addRouteKey, removeRouteKey} = useContext(FullScreenBlockingViewContext);

useEffect(() => {
if (!shouldForceFullScreen) {
addRouteKey(route.key);
}

return () => removeRouteKey(route.key);
}, [addRouteKey, removeRouteKey, route, shouldForceFullScreen]);

if (shouldForceFullScreen) {
return <View style={styles.forcedBlockingViewContainer}>{children}</View>;
Expand Down
2 changes: 1 addition & 1 deletion src/components/BlockingViews/FullPageNotFoundView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function FullPageNotFoundView({
onBackButtonPress = () => Navigation.goBack(),
shouldShowLink = true,
shouldShowBackButton = true,
onLinkPress = () => Navigation.dismissModal(),
onLinkPress = () => Navigation.goBackToHome(),
shouldForceFullScreen = false,
}: FullPageNotFoundViewProps) {
const styles = useThemeStyles();
Expand Down
54 changes: 54 additions & 0 deletions src/components/FullScreenBlockingViewContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, {createContext, useCallback, useMemo, useState} from 'react';

type FullScreenBlockingViewContextValue = {
addRouteKey: (key: string) => void;
removeRouteKey: (key: string) => void;
isBlockingViewVisible: boolean;
};

type FullScreenBlockingViewContextProviderProps = {
children: React.ReactNode;
};

const defaultValue: FullScreenBlockingViewContextValue = {
addRouteKey: () => {},
removeRouteKey: () => {},
isBlockingViewVisible: false,
};

const FullScreenBlockingViewContext = createContext<FullScreenBlockingViewContextValue>(defaultValue);

function FullScreenBlockingViewContextProvider({children}: FullScreenBlockingViewContextProviderProps) {
const [routeKeys, setRouteKeys] = useState<Set<string>>(new Set());

const addRouteKey = useCallback((key: string) => {
setRouteKeys((prevKeys) => new Set(prevKeys).add(key));
}, []);

const removeRouteKey = useCallback((key: string) => {
setRouteKeys((prevKeys) => {
const newKeys = new Set(prevKeys);
newKeys.delete(key);
return newKeys;
});
}, []);

const isBlockingViewVisible = useMemo(() => routeKeys.size > 0, [routeKeys]);

const contextValue = useMemo(
() => ({
addRouteKey,
removeRouteKey,
isBlockingViewVisible,
}),
[addRouteKey, removeRouteKey, isBlockingViewVisible],
);

return <FullScreenBlockingViewContext.Provider value={contextValue}>{children}</FullScreenBlockingViewContext.Provider>;
}

export default FullScreenBlockingViewContextProvider;

export {FullScreenBlockingViewContext};

export type {FullScreenBlockingViewContextProviderProps, FullScreenBlockingViewContextValue};
6 changes: 4 additions & 2 deletions src/components/Navigation/TopLevelBottomTabBar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {findFocusedRoute, useNavigationState} from '@react-navigation/native';
import React, {useEffect, useRef, useState} from 'react';
import React, {useContext, useEffect, useRef, useState} from 'react';
import {InteractionManager, View} from 'react-native';
import {FullScreenBlockingViewContext} from '@components/FullScreenBlockingViewContextProvider';
import BottomTabBar from '@components/Navigation/BottomTabBar';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useStyledSafeAreaInsets from '@hooks/useStyledSafeAreaInsets';
Expand Down Expand Up @@ -29,6 +30,7 @@ function TopLevelBottomTabBar() {
const {paddingBottom} = useStyledSafeAreaInsets();
const [isAfterClosingTransition, setIsAfterClosingTransition] = useState(false);
const cancelAfterInteractions = useRef<ReturnType<typeof InteractionManager.runAfterInteractions> | undefined>();
const {isBlockingViewVisible} = useContext(FullScreenBlockingViewContext);

const selectedTab = useNavigationState((state) => {
const topmostFullScreenRoute = state?.routes.findLast((route) => isFullScreenName(route.name));
Expand All @@ -48,7 +50,7 @@ function TopLevelBottomTabBar() {
const isBottomTabVisibleDirectly = useIsBottomTabVisibleDirectly();

const shouldDisplayBottomBar = shouldUseNarrowLayout ? isScreenWithBottomTabFocused : isBottomTabVisibleDirectly;
const isReadyToDisplayBottomBar = isAfterClosingTransition && shouldDisplayBottomBar;
const isReadyToDisplayBottomBar = isAfterClosingTransition && shouldDisplayBottomBar && !isBlockingViewVisible;

useEffect(() => {
cancelAfterInteractions.current?.cancel();
Expand Down
35 changes: 28 additions & 7 deletions src/libs/Navigation/Navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,32 +250,31 @@ const defaultGoBackOptions: Required<GoBackOptions> = {
* @param options - Optional configuration that affects navigation logic, such as parameter comparison.
*/
function goUp(fallbackRoute: Route, options?: GoBackOptions) {
if (!canNavigate('goUp')) {
if (!canNavigate('goUp') || !navigationRef.current) {
Log.hmmm(`[Navigation] Unable to go up. Can't navigate.`);
return;
}

if (!navigationRef.current) {
Log.hmmm('[Navigation] Unable to go up');
return;
}
const compareParams = options?.compareParams ?? defaultGoBackOptions.compareParams;

const rootState = navigationRef.current.getRootState();
const stateFromPath = getStateFromPath(fallbackRoute);

const action = getActionFromState(stateFromPath, linkingConfig.config);

if (!action) {
Log.hmmm(`[Navigation] Unable to go up. Action is undefined.`);
return;
}

const {action: minimalAction, targetState} = getMinimalAction(action, rootState);

if (minimalAction.type !== CONST.NAVIGATION.ACTION_TYPE.NAVIGATE || !targetState) {
Log.hmmm('[Navigation] Unable to go up. Minimal action type is wrong.');
return;
}

const compareParams = options?.compareParams ?? defaultGoBackOptions.compareParams;
const indexOfFallbackRoute = targetState.routes.findLastIndex((route) => doesRouteMatchToMinimalActionPayload(route, minimalAction, compareParams));

const distanceToPop = targetState.routes.length - indexOfFallbackRoute - 1;

// If we need to pop more than one route from rootState, we replace the current route to not lose visited routes from the navigation state
Expand Down Expand Up @@ -343,6 +342,27 @@ function resetToHome() {
navigationRef.dispatch({payload, type: CONST.NAVIGATION.ACTION_TYPE.REPLACE, target: rootState.key});
}

/**
* The goBack function doesn't support recursive pop e.g. pop route from root and then from nested navigator.
* There is only one case where recursive pop is needed which is going back to home.
* This function will cover this case.
* We will implement recursive pop if more use cases will appear.
*/
function goBackToHome() {
const isNarrowLayout = getIsNarrowLayout();

// This set the right split navigator.
goBack(ROUTES.HOME);

// We want to keep the report screen in the split navigator on wide layout.
if (!isNarrowLayout) {
return;
}

// This set the right route in this split navigator.
goBack(ROUTES.HOME);
}

/**
* Update route params for the specified route.
*/
Expand Down Expand Up @@ -550,6 +570,7 @@ export default {
waitForProtectedRoutes,
parseHybridAppUrl,
resetToHome,
goBackToHome,
closeRHPFlow,
setNavigationActionToMicrotaskQueue,
navigateToReportWithPolicyCheck,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function CardSection() {
const requestRefund = useCallback(() => {
requestRefundByUser();
setIsRequestRefundModalVisible(false);
Navigation.goBack(ROUTES.HOME);
Navigation.goBackToHome();
}, []);

const viewPurchases = useCallback(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/workspace/WorkspaceInitialPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac
>
<FullPageNotFoundView
onBackButtonPress={Navigation.dismissModal}
onLinkPress={() => Navigation.goBack(ROUTES.HOME)}
onLinkPress={Navigation.goBackToHome}
shouldShow={shouldShowNotFoundPage}
subtitleKey={shouldShowPolicy ? 'workspace.common.notAuthorized' : undefined}
>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/workspace/WorkspacePageWithSections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ function WorkspacePageWithSections({
>
<FullPageNotFoundView
onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)}
onLinkPress={() => Navigation.goBack(ROUTES.HOME)}
onLinkPress={Navigation.goBackToHome}
shouldShow={shouldShow}
subtitleKey={shouldShowPolicy ? 'workspace.common.notAuthorized' : undefined}
shouldForceFullScreen
Expand Down

0 comments on commit 007b1ff

Please sign in to comment.