Skip to content

Commit

Permalink
Merge pull request Expensify#47310 from dominictb/fix/46916-default-scan
Browse files Browse the repository at this point in the history
  • Loading branch information
mountiny authored Aug 20, 2024
2 parents 80236f5 + 1ea06e8 commit 0e4f02e
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 35 deletions.
66 changes: 31 additions & 35 deletions src/libs/Navigation/OnyxTabNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs
import type {EventMapCore, NavigationState, ScreenListeners} from '@react-navigation/native';
import {useRoute} from '@react-navigation/native';
import React, {useCallback, useContext, useEffect, useState} from 'react';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import {useOnyx} from 'react-native-onyx';
import FocusTrapContainerElement from '@components/FocusTrap/FocusTrapContainerElement';
import type {TabSelectorProps} from '@components/TabSelector/TabSelector';
import useThemeStyles from '@hooks/useThemeStyles';
Expand All @@ -13,40 +12,36 @@ import Tab from '@userActions/Tab';
import ONYXKEYS from '@src/ONYXKEYS';
import type {SelectedTabRequest} from '@src/types/onyx';
import type ChildrenProps from '@src/types/utils/ChildrenProps';
import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
import {defaultScreenOptions} from './OnyxTabNavigatorConfig';

type OnyxTabNavigatorOnyxProps = {
selectedTab: OnyxEntry<SelectedTabRequest>;
};

type OnyxTabNavigatorProps = OnyxTabNavigatorOnyxProps &
ChildrenProps & {
/** ID of the tab component to be saved in onyx */
id: string;
type OnyxTabNavigatorProps = ChildrenProps & {
/** ID of the tab component to be saved in onyx */
id: string;

/** Name of the selected tab */
selectedTab?: SelectedTabRequest;
/** Name of the selected tab */
defaultSelectedTab?: SelectedTabRequest;

/** A function triggered when a tab has been selected */
onTabSelected?: (newIouType: IOURequestType) => void;
/** A function triggered when a tab has been selected */
onTabSelected?: (newIouType: IOURequestType) => void;

tabBar: (props: TabSelectorProps) => React.ReactNode;
tabBar: (props: TabSelectorProps) => React.ReactNode;

screenListeners?: ScreenListeners<NavigationState, MaterialTopTabNavigationEventMap>;
screenListeners?: ScreenListeners<NavigationState, MaterialTopTabNavigationEventMap>;

/** Callback to register the focus trap container elements of the current active tab.
* Use this in the parent component to get the focus trap container element of the active tab,
* then pass it to the ScreenWrapper so that only focusable elements of the active tab are included in the focus trap
* Check the `IOURequestStartPage.tsx` and `NewChatSelectorPage.tsx` components for example usage
*/
onActiveTabFocusTrapContainerElementChanged?: (containerElement: HTMLElement | null) => void;
/** Callback to register the focus trap container elements of the current active tab.
* Use this in the parent component to get the focus trap container element of the active tab,
* then pass it to the ScreenWrapper so that only focusable elements of the active tab are included in the focus trap
* Check the `IOURequestStartPage.tsx` and `NewChatSelectorPage.tsx` components for example usage
*/
onActiveTabFocusTrapContainerElementChanged?: (containerElement: HTMLElement | null) => void;

/** Callback to register the focus trap container elements of the tab bar.
* This callback is useful when the custom-rendered tab bar is supporting the focus trap container element registration (which is the case of `TabSelector.tsx` component).
* Together, with the `onActiveTabFocusTrapContainerElementChanged` callback, we can manage the focus trap of the tab navigator in the parent component.
*/
onTabBarFocusTrapContainerElementChanged?: (containerElement: HTMLElement | null) => void;
};
/** Callback to register the focus trap container elements of the tab bar.
* This callback is useful when the custom-rendered tab bar is supporting the focus trap container element registration (which is the case of `TabSelector.tsx` component).
* Together, with the `onActiveTabFocusTrapContainerElementChanged` callback, we can manage the focus trap of the tab navigator in the parent component.
*/
onTabBarFocusTrapContainerElementChanged?: (containerElement: HTMLElement | null) => void;
};

// eslint-disable-next-line rulesdir/no-inline-named-export
const TopTab = createMaterialTopTabNavigator();
Expand All @@ -60,7 +55,7 @@ const TabFocusTrapContext = React.createContext<(tabName: string, containerEleme
// It also takes 2 more optional callbacks to manage the focus trap container elements of the tab bar and the active tab
function OnyxTabNavigator({
id,
selectedTab,
defaultSelectedTab,
tabBar: TabBar,
children,
onTabBarFocusTrapContainerElementChanged,
Expand All @@ -71,6 +66,7 @@ function OnyxTabNavigator({
}: OnyxTabNavigatorProps) {
// Mapping of tab name to focus trap container element
const [focusTrapContainerElementMapping, setFocusTrapContainerElementMapping] = useState<Record<string, HTMLElement>>({});
const [selectedTab, selectedTabResult] = useOnyx(`${ONYXKEYS.COLLECTION.SELECTED_TAB}${id}`);

// This callback is used to register the focus trap container element of each avaiable tab screen
const setTabFocusTrapContainerElement = useCallback((tabName: string, containerElement: HTMLElement | null) => {
Expand Down Expand Up @@ -107,13 +103,17 @@ function OnyxTabNavigator({
onActiveTabFocusTrapContainerElementChanged?.(selectedTab ? focusTrapContainerElementMapping[selectedTab] : null);
}, [selectedTab, focusTrapContainerElementMapping, onActiveTabFocusTrapContainerElementChanged]);

if (isLoadingOnyxValue(selectedTabResult)) {
return null;
}

return (
<TabFocusTrapContext.Provider value={setTabFocusTrapContainerElement}>
<TopTab.Navigator
/* eslint-disable-next-line react/jsx-props-no-spreading */
{...rest}
id={id}
initialRouteName={selectedTab}
initialRouteName={selectedTab ?? defaultSelectedTab}
backBehavior="initialRoute"
keyboardDismissMode="none"
tabBar={TabBarWithFocusTrapInclusion}
Expand Down Expand Up @@ -176,10 +176,6 @@ function TabScreenWithFocusTrapWrapper({children}: {children?: React.ReactNode})

OnyxTabNavigator.displayName = 'OnyxTabNavigator';

export default withOnyx<OnyxTabNavigatorProps, OnyxTabNavigatorOnyxProps>({
selectedTab: {
key: ({id}) => `${ONYXKEYS.COLLECTION.SELECTED_TAB}${id}`,
},
})(OnyxTabNavigator);
export default OnyxTabNavigator;

export {TabScreenWithFocusTrapWrapper, TopTab};
1 change: 1 addition & 0 deletions src/pages/iou/request/IOURequestStartPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ function IOURequestStartPage({
{iouType !== CONST.IOU.TYPE.SEND && iouType !== CONST.IOU.TYPE.PAY && iouType !== CONST.IOU.TYPE.INVOICE ? (
<OnyxTabNavigator
id={CONST.TAB.IOU_REQUEST_TYPE}
defaultSelectedTab={CONST.TAB_REQUEST.SCAN}
onTabSelected={resetIOUTypeIfChanged}
tabBar={TabSelector}
onTabBarFocusTrapContainerElementChanged={setTabBarContainerElement}
Expand Down

0 comments on commit 0e4f02e

Please sign in to comment.