From 9117c61bae77f3cd18e3d7668bbd4e800bc60b42 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 10 Oct 2023 09:22:16 +0200 Subject: [PATCH 01/23] [TS migration] Migrate 'AppNavigator' lib --- src/ONYXKEYS.ts | 1 + src/SCREENS.ts | 148 ++++++++++++ .../{AuthScreens.js => AuthScreens.tsx} | 123 +++++----- .../AppNavigator/ModalStackNavigators.js | 226 ------------------ .../AppNavigator/ModalStackNavigators.tsx | 226 ++++++++++++++++++ ...eNavigator.js => CentralPaneNavigator.tsx} | 5 +- .../Navigators/{Overlay.js => Overlay.tsx} | 25 +- ...alNavigator.js => RightModalNavigator.tsx} | 18 +- .../{PublicScreens.js => PublicScreens.tsx} | 11 +- ...HPScreenOptions.js => RHPScreenOptions.ts} | 4 +- ...eenIDSetter.js => ReportScreenIDSetter.ts} | 88 +++---- .../AppNavigator/ReportScreenWrapper.js | 43 ---- .../AppNavigator/ReportScreenWrapper.tsx | 25 ++ .../{CustomRouter.js => CustomRouter.ts} | 27 ++- .../createCustomStackNavigator/index.js | 60 ----- .../createCustomStackNavigator/index.tsx | 46 ++++ ...reenOptions.js => defaultScreenOptions.ts} | 4 +- ...ns.js => getRootNavigatorScreenOptions.ts} | 22 +- .../AppNavigator/{index.js => index.tsx} | 8 +- ...lator.js => modalCardStyleInterpolator.ts} | 3 +- src/libs/Navigation/AppNavigator/types.ts | 87 +++++++ src/libs/Navigation/Navigation.js | 2 +- src/libs/compose.ts | 27 +-- src/styles/cardStyles/types.ts | 2 +- src/styles/getModalStyles.ts | 1 + src/types/onyx/Report.ts | 3 + 26 files changed, 714 insertions(+), 521 deletions(-) rename src/libs/Navigation/AppNavigator/{AuthScreens.js => AuthScreens.tsx} (82%) delete mode 100644 src/libs/Navigation/AppNavigator/ModalStackNavigators.js create mode 100644 src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx rename src/libs/Navigation/AppNavigator/Navigators/{CentralPaneNavigator.js => CentralPaneNavigator.tsx} (89%) rename src/libs/Navigation/AppNavigator/Navigators/{Overlay.js => Overlay.tsx} (67%) rename src/libs/Navigation/AppNavigator/Navigators/{RightModalNavigator.js => RightModalNavigator.tsx} (88%) rename src/libs/Navigation/AppNavigator/{PublicScreens.js => PublicScreens.tsx} (84%) rename src/libs/Navigation/AppNavigator/{RHPScreenOptions.js => RHPScreenOptions.ts} (72%) rename src/libs/Navigation/AppNavigator/{ReportScreenIDSetter.js => ReportScreenIDSetter.ts} (54%) delete mode 100644 src/libs/Navigation/AppNavigator/ReportScreenWrapper.js create mode 100644 src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx rename src/libs/Navigation/AppNavigator/createCustomStackNavigator/{CustomRouter.js => CustomRouter.ts} (60%) delete mode 100644 src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js create mode 100644 src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx rename src/libs/Navigation/AppNavigator/{defaultScreenOptions.js => defaultScreenOptions.ts} (68%) rename src/libs/Navigation/AppNavigator/{getRootNavigatorScreenOptions.js => getRootNavigatorScreenOptions.ts} (71%) rename src/libs/Navigation/AppNavigator/{index.js => index.tsx} (73%) rename src/libs/Navigation/AppNavigator/{modalCardStyleInterpolator.js => modalCardStyleInterpolator.ts} (70%) create mode 100644 src/libs/Navigation/AppNavigator/types.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 0a17d3a1d2f7..6685dd29a9c7 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -353,6 +353,7 @@ type OnyxValues = { [ONYXKEYS.IS_LOADING_REPORT_DATA]: boolean; [ONYXKEYS.IS_SHORTCUTS_MODAL_OPEN]: boolean; [ONYXKEYS.IS_TEST_TOOLS_MODAL_OPEN]: boolean; + [ONYXKEYS.IS_LOADING_APP]: boolean; [ONYXKEYS.WALLET_TRANSFER]: OnyxTypes.WalletTransfer; [ONYXKEYS.LAST_ACCESSED_WORKSPACE_POLICY_ID]: string; [ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT]: boolean; diff --git a/src/SCREENS.ts b/src/SCREENS.ts index eb125a43c239..1320d2541d93 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -10,6 +10,7 @@ export default { NOT_FOUND: 'not-found', TRANSITION_BETWEEN_APPS: 'TransitionBetweenApps', VALIDATE_LOGIN: 'ValidateLogin', + UNLINK_LOGIN: 'UnlinkLogin', CONCIERGE: 'Concierge', SETTINGS: { ROOT: 'Settings_Root', @@ -17,11 +18,158 @@ export default { WORKSPACES: 'Settings_Workspaces', SECURITY: 'Settings_Security', STATUS: 'Settings_Status', + PROFILE: 'Settings_Profile', + PRONOUNS: 'Settings_Pronouns', + DISPLAY_NAME: 'Settings_Display_Name', + TIMEZONE: 'Settings_Timezone', + TIMEZONE_SELECT: 'Settings_Timezone_Select', + PERSONAL_DETAILS_INITIAL: 'Settings_PersonalDetails_Initial', + PERSONAL_DETAILS_LEGAL_NAME: 'Settings_PersonalDetails_LegalName', + PERSONAL_DETAILS_DATE_OF_BIRTH: 'Settings_PersonalDetails_DateOfBirth', + PERSONAL_DETAILS_ADDRESS: 'Settings_PersonalDetails_Address', + PERSONAL_DETAILS_ADDRESS_COUNTRY: 'Settings_PersonalDetails_Address_Country', + CONTACT_METHODS: 'Settings_ContactMethods', + CONTACT_METHOD_DETAILS: 'Settings_ContactMethodDetails', + NEW_CONTACT_METHOD: 'Settings_NewContactMethod', + SHARE_CODE: 'Settings_Share_Code', + ABOUT: 'Settings_About', + APP_DOWNLOAD_LINKS: 'Settings_App_Download_Links', + LOUNGE_ACCESS: 'Settings_Lounge_Access', + WALLET: 'Settings_Wallet', + WALLET_DOMAIN_CARDS: 'Settings_Wallet_DomainCards', + WALLET_TRANSFER_BALANCE: 'Settings_Wallet_Transfer_Balance', + WALLET_CHOOSE_TRANSFER_ACCOUNT: 'Settings_Wallet_Choose_Transfer_Account', + WALLET_ENABLE_PAYMENTS: 'Settings_Wallet_EnablePayments', + ADD_DEBIT_CARD: 'Settings_Add_Debit_Card', + ADD_BANK_ACCOUNT: 'Settings_Add_Bank_Account', + PREFERENCES_PRIORITY_MODE: 'Settings_Preferences_PriorityMode', + PREFERENCES_LANGUAGE: 'Settings_Preferences_Language', + CLOSE: 'Settings_Close', + STATUS_SET: 'Settings_Status_Set', + TWO_FACTOR_AUTH: 'Settings_TwoFactorAuth', }, SAVE_THE_WORLD: { ROOT: 'SaveTheWorld_Root', }, + RIGHT_MODAL: { + SETTINGS: 'Settings', + NEW_CHAT: 'NewChat', + SEARCH: 'Search', + DETAILS: 'Details', + PROFILE: 'Profile', + REPORT_DETAILS: 'Report_Details', + REPORT_SETTINGS: 'Report_Settings', + REPORT_WELCOME_MESSAGE: 'Report_WelcomeMessage', + PARTICIPANTS: 'Participants', + MONEY_REQUEST: 'MoneyRequest', + NEW_TASK: 'NewTask', + TEACHERS_UNITE: 'TeachersUnite', + TASK_DETAILS: 'Task_Details', + ENABLE_PAYMENTS: 'EnablePayments', + SPLIT_DETAILS: 'SplitDetails', + ADD_PERSONAL_BANK_ACCOUNT: 'AddPersonalBankAccount', + WALLET_STATEMENT: 'Wallet_Statement', + FLAG_COMMENT: 'Flag_Comment', + EDIT_REQUEST: 'EditRequest', + SIGN_IN: 'SignIn', + PRIVATE_NOTES: 'Private_Notes', + }, SIGN_IN_WITH_APPLE_DESKTOP: 'AppleSignInDesktop', SIGN_IN_WITH_GOOGLE_DESKTOP: 'GoogleSignInDesktop', DESKTOP_SIGN_IN_REDIRECT: 'DesktopSignInRedirect', + + MONEY_REQUEST: { + ROOT: 'Money_Request', + AMOUNT: 'Money_Request_Amount', + PARTICIPANTS: 'Money_Request_Participants', + CONFIRMATION: 'Money_Request_Confirmation', + CURRENCY: 'Money_Request_Currency', + DATE: 'Money_Request_Date', + DESCRIPTION: 'Money_Request_Description', + CATEGORY: 'Money_Request_Category', + TAG: 'Money_Request_Tag', + MERCHANT: 'Money_Request_Merchant', + WAYPOINT: 'Money_Request_Waypoint', + EDIT_WAYPOINT: 'Money_Request_Edit_Waypoint', + DISTANCE: 'Money_Request_Distance', + RECEIPT: 'Money_Request_Receipt', + }, + + IOU_SEND: { + ADD_BANK_ACCOUNT: 'IOU_Send_Add_Bank_Account', + ADD_DEBIT_CARD: 'IOU_Send_Add_Debit_Card', + ENABLE_PAYMENTS: 'IOU_Send_Enable_Payments', + }, + + REPORT_SETTINGS: { + ROOT: 'Report_Settings_Root', + ROOM_NAME: 'Report_Settings_Room_Name', + NOTIFICATION_PREFERENCES: 'Report_Settings_Notification_Preferences', + WRITE_CAPABILITY: 'Report_Settings_Write_Capability', + }, + + NEW_TASK: { + ROOT: 'NewTask_Root', + TASK_ASSIGNEE_SELECTOR: 'NewTask_TaskAssigneeSelector', + TASK_SHARE_DESTINATION_SELECTOR: 'NewTask_TaskShareDestinationSelector', + DETAILS: 'NewTask_Details', + TITLE: 'NewTask_Title', + DESCRIPTION: 'NewTask_Description', + }, + + TASK: { + TITLE: 'Task_Title', + DESCRIPTION: 'Task_Description', + ASSIGNEE: 'Task_Assignee', + }, + + PRIVATE_NOTES: { + VIEW: 'PrivateNotes_View', + LIST: 'PrivateNotes_List', + EDIT: 'PrivateNotes_Edit', + }, + + REPORT_DETAILS: { + ROOT: 'Report_Details_Root', + SHARE_CODE: 'Report_Details_Share_Code', + }, + + WORKSPACE: { + INITIAL: 'Workspace_Initial', + SETTINGS: 'Workspace_Settings', + CARD: 'Workspace_Card', + REIMBURSE: 'Workspace_Reimburse', + RATE_AND_UNIT: 'Workspace_RateAndUnit', + BILLS: 'Workspace_Bills', + INVOICES: 'Workspace_Invoices', + TRAVEL: 'Workspace_Travel', + MEMBERS: 'Workspace_Members', + INVITE: 'Workspace_Invite', + INVITE_MESSAGE: 'Workspace_Invite_Message', + }, + + EDIT_REQUEST: { + ROOT: 'EditRequest_Root', + CURRENCY: 'EditRequest_Currency', + }, + + I_KNOW_A_TEACHER: 'I_Know_A_Teacher', + INTRO_SCHOOL_PRINCIPAL: 'Intro_School_Principal', + I_AM_A_TEACHER: 'I_Am_A_Teacher', + + ENABLE_PAYMENTS_ROOT: 'EnablePayments_Root', + ADD_PERSONAL_BANK_ACCOUNT_ROOT: 'AddPersonalBankAccount_Root', + REIMBURSEMENT_ACCOUNT_ROOT: 'Reimbursement_Account_Root', + WALLET_STATEMENT_ROOT: 'WalletStatement_Root', + SIGN_IN_ROOT: 'SignIn_Root', + SPLIT_DETAILS_ROOT: 'SplitDetails_Root', + DETAILS_ROOT: 'Details_Root', + PROFILE_ROOT: 'Profile_Root', + REPORT_WELCOME_MESSAGE_ROOT: 'Report_WelcomeMessage_Root', + REPORT_PARTICIPANTS_ROOT: 'ReportParticipants_Root', + SEARCH_ROOT: 'Search_Root', + NEW_CHAT_ROOT: 'NewChat_Root', + FLAG_COMMENT_ROOT: 'FlagComment_Root', + REIMBURSEMENT_ACCOUNT: 'ReimbursementAccount', + GET_ASSISTANCE: 'GetAssistance', } as const; diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.tsx similarity index 82% rename from src/libs/Navigation/AppNavigator/AuthScreens.js rename to src/libs/Navigation/AppNavigator/AuthScreens.tsx index 428550a43aa8..5e8f471d4a79 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -1,10 +1,7 @@ import React from 'react'; -import Onyx, {withOnyx} from 'react-native-onyx'; -import PropTypes from 'prop-types'; -import _ from 'underscore'; -import lodashGet from 'lodash/get'; +import Onyx, {OnyxEntry, withOnyx} from 'react-native-onyx'; import {View} from 'react-native'; -import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; +import withWindowDimensions from '../../../components/withWindowDimensions'; import CONST from '../../../CONST'; import compose from '../../compose'; import * as PersonalDetails from '../../actions/PersonalDetails'; @@ -35,16 +32,43 @@ import * as SessionUtils from '../../SessionUtils'; import NotFoundPage from '../../../pages/ErrorPage/NotFoundPage'; import getRootNavigatorScreenOptions from './getRootNavigatorScreenOptions'; import DemoSetupPage from '../../../pages/DemoSetupPage'; +import * as OnyxTypes from '../../../types/onyx'; +import type {WindowDimensions} from '../../../styles/getModalStyles'; +import type {AuthScreensStackParamList} from './types'; -let timezone; -let currentAccountID; -let isLoadingApp; +type AuthScreensOnyxProps = { + /** Session of currently logged in user */ + session: OnyxEntry; + + /** The report ID of the last opened public room as anonymous user */ + lastOpenedPublicRoomID: OnyxEntry; + + /** Opt-in experimental mode that prevents certain Onyx keys from persisting to disk */ + isUsingMemoryOnlyKeys: OnyxEntry; + + /** The last Onyx update ID was applied to the client */ + lastUpdateIDAppliedToClient: OnyxEntry; +}; + +type AuthScreensProps = WindowDimensions & AuthScreensOnyxProps; + +type Timezone = { + automatic?: boolean; + selected?: string; +}; + +type UnsubscribeChatShortcut = () => void; +type UnsubscribeSearchShortcut = () => void; + +let timezone: Timezone | null; +let currentAccountID: number; +let isLoadingApp: boolean; Onyx.connect({ key: ONYXKEYS.SESSION, callback: (val) => { // When signed out, val hasn't accountID - if (!_.has(val, 'accountID')) { + if (!val?.accountID) { timezone = null; return; } @@ -52,7 +76,7 @@ Onyx.connect({ currentAccountID = val.accountID; if (Navigation.isActiveRoute(ROUTES.SIGN_IN_MODAL)) { // This means sign in in RHP was successful, so we can dismiss the modal and subscribe to user events - Navigation.dismissModal(); + Navigation.dismissModal(undefined); User.subscribeToUserEvents(); } }, @@ -65,12 +89,12 @@ Onyx.connect({ return; } - timezone = lodashGet(val, [currentAccountID, 'timezone'], {}); + timezone = val?.[currentAccountID]?.timezone ?? {}; const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone; // If the current timezone is different than the user's timezone, and their timezone is set to automatic // then update their timezone. - if (_.isObject(timezone) && timezone.automatic && timezone.selected !== currentTimezone) { + if (timezone !== null && timezone.automatic && timezone.selected !== currentTimezone) { timezone.selected = currentTimezone; PersonalDetails.updateAutomaticTimezone({ automatic: true, @@ -83,11 +107,11 @@ Onyx.connect({ Onyx.connect({ key: ONYXKEYS.IS_LOADING_APP, callback: (val) => { - isLoadingApp = val; + isLoadingApp = !!val; }, }); -const RootStack = createCustomStackNavigator(); +const RootStack = createCustomStackNavigator(); // We want to delay the re-rendering for components(e.g. ReportActionCompose) // that depends on modal visibility until Modal is completely closed and its focused @@ -102,35 +126,14 @@ const modalScreenListeners = { }, }; -const propTypes = { - /** Session of currently logged in user */ - session: PropTypes.shape({ - email: PropTypes.string.isRequired, - }), - - /** The report ID of the last opened public room as anonymous user */ - lastOpenedPublicRoomID: PropTypes.string, +class AuthScreens extends React.Component { + unsubscribeSearchShortcut?: UnsubscribeSearchShortcut; - /** Opt-in experimental mode that prevents certain Onyx keys from persisting to disk */ - isUsingMemoryOnlyKeys: PropTypes.bool, + unsubscribeChatShortcut?: UnsubscribeChatShortcut; - /** The last Onyx update ID was applied to the client */ - lastUpdateIDAppliedToClient: PropTypes.number, - - ...windowDimensionsPropTypes, -}; + interval?: number; -const defaultProps = { - isUsingMemoryOnlyKeys: false, - session: { - email: null, - }, - lastOpenedPublicRoomID: null, - lastUpdateIDAppliedToClient: null, -}; - -class AuthScreens extends React.Component { - constructor(props) { + constructor(props: AuthScreensProps) { super(props); Timing.start(CONST.TIMING.HOMEPAGE_INITIAL_RENDER); @@ -142,7 +145,7 @@ class AuthScreens extends React.Component { if (isLoadingApp) { App.openApp(); } else { - App.reconnectApp(this.props.lastUpdateIDAppliedToClient); + App.reconnectApp(this.props.lastUpdateIDAppliedToClient ?? 0); } }); PusherConnectionManager.init(); @@ -159,14 +162,16 @@ class AuthScreens extends React.Component { // Note: If a Guide has enabled the memory only key mode then we do want to run OpenApp as their app will not be rehydrated with // the correct state on refresh. They are explicitly opting out of storing data they would need (i.e. reports_) to take advantage of // the optimizations performed during ReconnectApp. - const shouldGetAllData = this.props.isUsingMemoryOnlyKeys || SessionUtils.didUserLogInDuringSession(); + const shouldGetAllData = !!this.props.isUsingMemoryOnlyKeys || SessionUtils.didUserLogInDuringSession(); if (shouldGetAllData) { App.openApp(); } else { - App.reconnectApp(this.props.lastUpdateIDAppliedToClient); + App.reconnectApp(this.props.lastUpdateIDAppliedToClient ?? 0); } - App.setUpPoliciesAndNavigate(this.props.session, !this.props.isSmallScreenWidth); + if (this.props.session) { + App.setUpPoliciesAndNavigate(this.props.session, !this.props.isSmallScreenWidth); + } App.redirectThirdPartyDesktopSignIn(); if (this.props.lastOpenedPublicRoomID) { @@ -193,9 +198,9 @@ class AuthScreens extends React.Component { }); }, searchShortcutConfig.descriptionKey, - searchShortcutConfig.modifiers, + [...searchShortcutConfig.modifiers], true, - ); + ) as UnsubscribeSearchShortcut; this.unsubscribeChatShortcut = KeyboardShortcut.subscribe( chatShortcutConfig.shortcutKey, () => { @@ -207,12 +212,12 @@ class AuthScreens extends React.Component { }); }, chatShortcutConfig.descriptionKey, - chatShortcutConfig.modifiers, + [...chatShortcutConfig.modifiers], true, - ); + ) as UnsubscribeChatShortcut; } - shouldComponentUpdate(nextProps) { + shouldComponentUpdate(nextProps: AuthScreensProps) { return nextProps.windowHeight !== this.props.windowHeight || nextProps.isSmallScreenWidth !== this.props.isSmallScreenWidth; } @@ -225,7 +230,7 @@ class AuthScreens extends React.Component { } Session.cleanupSession(); clearInterval(this.interval); - this.interval = null; + this.interval = undefined; } render() { @@ -235,18 +240,16 @@ class AuthScreens extends React.Component { { - const SidebarScreen = require('../../../pages/home/sidebar/SidebarScreen').default; + const SidebarScreen = require('../../../pages/home/sidebar/SidebarScreen').default as React.ComponentType; return SidebarScreen; }} /> @@ -263,7 +266,7 @@ class AuthScreens extends React.Component { title: 'New Expensify', }} getComponent={() => { - const ValidateLoginPage = require('../../../pages/ValidateLoginPage').default; + const ValidateLoginPage = require('../../../pages/ValidateLoginPage').default as React.ComponentType; return ValidateLoginPage; }} /> @@ -271,7 +274,7 @@ class AuthScreens extends React.Component { name={SCREENS.TRANSITION_BETWEEN_APPS} options={defaultScreenOptions} getComponent={() => { - const LogOutPreviousUserPage = require('../../../pages/LogOutPreviousUserPage').default; + const LogOutPreviousUserPage = require('../../../pages/LogOutPreviousUserPage').default as React.ComponentType; return LogOutPreviousUserPage; }} /> @@ -279,7 +282,7 @@ class AuthScreens extends React.Component { name={SCREENS.CONCIERGE} options={defaultScreenOptions} getComponent={() => { - const ConciergePage = require('../../../pages/ConciergePage').default; + const ConciergePage = require('../../../pages/ConciergePage').default as React.ComponentType; return ConciergePage; }} /> @@ -300,7 +303,7 @@ class AuthScreens extends React.Component { presentation: 'transparentModal', }} getComponent={() => { - const ReportAttachments = require('../../../pages/home/report/ReportAttachments').default; + const ReportAttachments = require('../../../pages/home/report/ReportAttachments').default as React.ComponentType; return ReportAttachments; }} listeners={modalScreenListeners} @@ -327,11 +330,9 @@ class AuthScreens extends React.Component { } } -AuthScreens.propTypes = propTypes; -AuthScreens.defaultProps = defaultProps; export default compose( withWindowDimensions, - withOnyx({ + withOnyx({ session: { key: ONYXKEYS.SESSION, }, diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js deleted file mode 100644 index 6636702592c0..000000000000 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ /dev/null @@ -1,226 +0,0 @@ -import _ from 'underscore'; -import React from 'react'; -import {createStackNavigator, CardStyleInterpolators} from '@react-navigation/stack'; -import styles from '../../../styles/styles'; -import SCREENS from '../../../SCREENS'; - -const defaultSubRouteOptions = { - cardStyle: styles.navigationScreenCardStyle, - headerShown: false, - cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, -}; - -/** - * Create a modal stack navigator with an array of sub-screens. - * - * @param {Object} screens key/value pairs where the key is the name of the screen and the value is a functon that returns the lazy-loaded component - * @returns {Function} - */ -function createModalStackNavigator(screens) { - const ModalStackNavigator = createStackNavigator(); - return () => ( - - {_.map(screens, (getComponent, name) => ( - - ))} - - ); -} - -const MoneyRequestModalStackNavigator = createModalStackNavigator({ - Money_Request: () => require('../../../pages/iou/MoneyRequestSelectorPage').default, - Money_Request_Amount: () => require('../../../pages/iou/steps/NewRequestAmountPage').default, - Money_Request_Participants: () => require('../../../pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage').default, - Money_Request_Confirmation: () => require('../../../pages/iou/steps/MoneyRequestConfirmPage').default, - Money_Request_Currency: () => require('../../../pages/iou/IOUCurrencySelection').default, - Money_Request_Date: () => require('../../../pages/iou/MoneyRequestDatePage').default, - Money_Request_Description: () => require('../../../pages/iou/MoneyRequestDescriptionPage').default, - Money_Request_Category: () => require('../../../pages/iou/MoneyRequestCategoryPage').default, - Money_Request_Tag: () => require('../../../pages/iou/MoneyRequestTagPage').default, - Money_Request_Merchant: () => require('../../../pages/iou/MoneyRequestMerchantPage').default, - IOU_Send_Add_Bank_Account: () => require('../../../pages/AddPersonalBankAccountPage').default, - IOU_Send_Add_Debit_Card: () => require('../../../pages/settings/Wallet/AddDebitCardPage').default, - IOU_Send_Enable_Payments: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default, - Money_Request_Waypoint: () => require('../../../pages/iou/NewDistanceRequestWaypointEditorPage').default, - Money_Request_Edit_Waypoint: () => require('../../../pages/iou/MoneyRequestEditWaypointPage').default, - Money_Request_Distance: () => require('../../../pages/iou/NewDistanceRequestPage').default, - Money_Request_Receipt: () => require('../../../pages/EditRequestReceiptPage').default, -}); - -const SplitDetailsModalStackNavigator = createModalStackNavigator({ - SplitDetails_Root: () => require('../../../pages/iou/SplitBillDetailsPage').default, -}); - -const DetailsModalStackNavigator = createModalStackNavigator({ - Details_Root: () => require('../../../pages/DetailsPage').default, -}); - -const ProfileModalStackNavigator = createModalStackNavigator({ - Profile_Root: () => require('../../../pages/ProfilePage').default, -}); - -const ReportDetailsModalStackNavigator = createModalStackNavigator({ - Report_Details_Root: () => require('../../../pages/ReportDetailsPage').default, - Report_Details_Share_Code: () => require('../../../pages/home/report/ReportDetailsShareCodePage').default, -}); - -const ReportSettingsModalStackNavigator = createModalStackNavigator({ - Report_Settings_Root: () => require('../../../pages/settings/Report/ReportSettingsPage').default, - Report_Settings_Room_Name: () => require('../../../pages/settings/Report/RoomNamePage').default, - Report_Settings_Notification_Preferences: () => require('../../../pages/settings/Report/NotificationPreferencePage').default, - Report_Settings_Write_Capability: () => require('../../../pages/settings/Report/WriteCapabilityPage').default, -}); - -const TaskModalStackNavigator = createModalStackNavigator({ - Task_Title: () => require('../../../pages/tasks/TaskTitlePage').default, - Task_Description: () => require('../../../pages/tasks/TaskDescriptionPage').default, - Task_Assignee: () => require('../../../pages/tasks/TaskAssigneeSelectorModal').default, -}); - -const ReportWelcomeMessageModalStackNavigator = createModalStackNavigator({ - Report_WelcomeMessage_Root: () => require('../../../pages/ReportWelcomeMessagePage').default, -}); - -const ReportParticipantsModalStackNavigator = createModalStackNavigator({ - ReportParticipants_Root: () => require('../../../pages/ReportParticipantsPage').default, -}); - -const SearchModalStackNavigator = createModalStackNavigator({ - Search_Root: () => require('../../../pages/SearchPage').default, -}); - -const NewChatModalStackNavigator = createModalStackNavigator({ - NewChat_Root: () => require('../../../pages/NewChatSelectorPage').default, -}); - -const NewTaskModalStackNavigator = createModalStackNavigator({ - NewTask_Root: () => require('../../../pages/tasks/NewTaskPage').default, - NewTask_TaskAssigneeSelector: () => require('../../../pages/tasks/TaskAssigneeSelectorModal').default, - NewTask_TaskShareDestinationSelector: () => require('../../../pages/tasks/TaskShareDestinationSelectorModal').default, - NewTask_Details: () => require('../../../pages/tasks/NewTaskDetailsPage').default, - NewTask_Title: () => require('../../../pages/tasks/NewTaskTitlePage').default, - NewTask_Description: () => require('../../../pages/tasks/NewTaskDescriptionPage').default, -}); - -const NewTeachersUniteNavigator = createModalStackNavigator({ - [SCREENS.SAVE_THE_WORLD.ROOT]: () => require('../../../pages/TeachersUnite/SaveTheWorldPage').default, - I_Know_A_Teacher: () => require('../../../pages/TeachersUnite/KnowATeacherPage').default, - Intro_School_Principal: () => require('../../../pages/TeachersUnite/ImTeacherPage').default, - I_Am_A_Teacher: () => require('../../../pages/TeachersUnite/ImTeacherPage').default, -}); - -const SettingsModalStackNavigator = createModalStackNavigator({ - [SCREENS.SETTINGS.ROOT]: () => require('../../../pages/settings/InitialSettingsPage').default, - Settings_Share_Code: () => require('../../../pages/ShareCodePage').default, - [SCREENS.SETTINGS.WORKSPACES]: () => require('../../../pages/workspace/WorkspacesListPage').default, - Settings_Profile: () => require('../../../pages/settings/Profile/ProfilePage').default, - Settings_Pronouns: () => require('../../../pages/settings/Profile/PronounsPage').default, - Settings_Display_Name: () => require('../../../pages/settings/Profile/DisplayNamePage').default, - Settings_Timezone: () => require('../../../pages/settings/Profile/TimezoneInitialPage').default, - Settings_Timezone_Select: () => require('../../../pages/settings/Profile/TimezoneSelectPage').default, - Settings_PersonalDetails_Initial: () => require('../../../pages/settings/Profile/PersonalDetails/PersonalDetailsInitialPage').default, - Settings_PersonalDetails_LegalName: () => require('../../../pages/settings/Profile/PersonalDetails/LegalNamePage').default, - Settings_PersonalDetails_DateOfBirth: () => require('../../../pages/settings/Profile/PersonalDetails/DateOfBirthPage').default, - Settings_PersonalDetails_Address: () => require('../../../pages/settings/Profile/PersonalDetails/AddressPage').default, - Settings_PersonalDetails_Address_Country: () => require('../../../pages/settings/Profile/PersonalDetails/CountrySelectionPage').default, - Settings_ContactMethods: () => require('../../../pages/settings/Profile/Contacts/ContactMethodsPage').default, - Settings_ContactMethodDetails: () => require('../../../pages/settings/Profile/Contacts/ContactMethodDetailsPage').default, - Settings_NewContactMethod: () => require('../../../pages/settings/Profile/Contacts/NewContactMethodPage').default, - [SCREENS.SETTINGS.PREFERENCES]: () => require('../../../pages/settings/Preferences/PreferencesPage').default, - Settings_Preferences_PriorityMode: () => require('../../../pages/settings/Preferences/PriorityModePage').default, - Settings_Preferences_Language: () => require('../../../pages/settings/Preferences/LanguagePage').default, - // Will be uncommented as part of https://github.com/Expensify/App/issues/21670 - // Settings_Preferences_Theme: () => require('../../../pages/settings/Preferences/ThemePage').default, - Settings_Close: () => require('../../../pages/settings/Security/CloseAccountPage').default, - [SCREENS.SETTINGS.SECURITY]: () => require('../../../pages/settings/Security/SecuritySettingsPage').default, - Settings_About: () => require('../../../pages/settings/AboutPage/AboutPage').default, - Settings_App_Download_Links: () => require('../../../pages/settings/AppDownloadLinks').default, - Settings_Lounge_Access: () => require('../../../pages/settings/Profile/LoungeAccessPage').default, - Settings_Wallet: () => require('../../../pages/settings/Wallet/WalletPage').default, - Settings_Wallet_DomainCards: () => require('../../../pages/settings/Wallet/ExpensifyCardPage').default, - Settings_Wallet_Transfer_Balance: () => require('../../../pages/settings/Wallet/TransferBalancePage').default, - Settings_Wallet_Choose_Transfer_Account: () => require('../../../pages/settings/Wallet/ChooseTransferAccountPage').default, - Settings_Wallet_EnablePayments: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default, - Settings_Add_Debit_Card: () => require('../../../pages/settings/Wallet/AddDebitCardPage').default, - Settings_Add_Bank_Account: () => require('../../../pages/AddPersonalBankAccountPage').default, - [SCREENS.SETTINGS.STATUS]: () => require('../../../pages/settings/Profile/CustomStatus/StatusPage').default, - Settings_Status_Set: () => require('../../../pages/settings/Profile/CustomStatus/StatusSetPage').default, - Workspace_Initial: () => require('../../../pages/workspace/WorkspaceInitialPage').default, - Workspace_Settings: () => require('../../../pages/workspace/WorkspaceSettingsPage').default, - Workspace_Card: () => require('../../../pages/workspace/card/WorkspaceCardPage').default, - Workspace_Reimburse: () => require('../../../pages/workspace/reimburse/WorkspaceReimbursePage').default, - Workspace_RateAndUnit: () => require('../../../pages/workspace/reimburse/WorkspaceRateAndUnitPage').default, - Workspace_Bills: () => require('../../../pages/workspace/bills/WorkspaceBillsPage').default, - Workspace_Invoices: () => require('../../../pages/workspace/invoices/WorkspaceInvoicesPage').default, - Workspace_Travel: () => require('../../../pages/workspace/travel/WorkspaceTravelPage').default, - Workspace_Members: () => require('../../../pages/workspace/WorkspaceMembersPage').default, - Workspace_Invite: () => require('../../../pages/workspace/WorkspaceInvitePage').default, - Workspace_Invite_Message: () => require('../../../pages/workspace/WorkspaceInviteMessagePage').default, - ReimbursementAccount: () => require('../../../pages/ReimbursementAccount/ReimbursementAccountPage').default, - GetAssistance: () => require('../../../pages/GetAssistancePage').default, - Settings_TwoFactorAuth: () => require('../../../pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage').default, -}); - -const EnablePaymentsStackNavigator = createModalStackNavigator({ - EnablePayments_Root: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default, -}); - -const AddPersonalBankAccountModalStackNavigator = createModalStackNavigator({ - AddPersonalBankAccount_Root: () => require('../../../pages/AddPersonalBankAccountPage').default, -}); - -const ReimbursementAccountModalStackNavigator = createModalStackNavigator({ - ReimbursementAccount_Root: () => require('../../../pages/ReimbursementAccount/ReimbursementAccountPage').default, -}); - -const WalletStatementStackNavigator = createModalStackNavigator({ - WalletStatement_Root: () => require('../../../pages/wallet/WalletStatementPage').default, -}); - -const FlagCommentStackNavigator = createModalStackNavigator({ - FlagComment_Root: () => require('../../../pages/FlagCommentPage').default, -}); - -const EditRequestStackNavigator = createModalStackNavigator({ - EditRequest_Root: () => require('../../../pages/EditRequestPage').default, - EditRequest_Currency: () => require('../../../pages/iou/IOUCurrencySelection').default, -}); - -const PrivateNotesModalStackNavigator = createModalStackNavigator({ - PrivateNotes_View: () => require('../../../pages/PrivateNotes/PrivateNotesViewPage').default, - PrivateNotes_List: () => require('../../../pages/PrivateNotes/PrivateNotesListPage').default, - PrivateNotes_Edit: () => require('../../../pages/PrivateNotes/PrivateNotesEditPage').default, -}); - -const SignInModalStackNavigator = createModalStackNavigator({ - SignIn_Root: () => require('../../../pages/signin/SignInModal').default, -}); - -export { - MoneyRequestModalStackNavigator, - SplitDetailsModalStackNavigator, - DetailsModalStackNavigator, - ProfileModalStackNavigator, - ReportDetailsModalStackNavigator, - TaskModalStackNavigator, - ReportSettingsModalStackNavigator, - ReportWelcomeMessageModalStackNavigator, - ReportParticipantsModalStackNavigator, - SearchModalStackNavigator, - NewChatModalStackNavigator, - NewTaskModalStackNavigator, - SettingsModalStackNavigator, - EnablePaymentsStackNavigator, - AddPersonalBankAccountModalStackNavigator, - ReimbursementAccountModalStackNavigator, - WalletStatementStackNavigator, - FlagCommentStackNavigator, - EditRequestStackNavigator, - PrivateNotesModalStackNavigator, - NewTeachersUniteNavigator, - SignInModalStackNavigator, -}; diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx new file mode 100644 index 000000000000..9e8cf9680e73 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -0,0 +1,226 @@ +import React from 'react'; +import {createStackNavigator, CardStyleInterpolators} from '@react-navigation/stack'; +import styles from '../../../styles/styles'; +import SCREENS from '../../../SCREENS'; + +const defaultSubRouteOptions = { + cardStyle: styles.navigationScreenCardStyle, + headerShown: false, + cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, +}; + +type Screens = Record React.ComponentType>; + +/** + * Create a modal stack navigator with an array of sub-screens. + * + * @param screens key/value pairs where the key is the name of the screen and the value is a functon that returns the lazy-loaded component + */ +function createModalStackNavigator(screens: Screens): () => React.JSX.Element { + const ModalStackNavigator = createStackNavigator(); + return () => ( + + {Object.keys(screens).map((name) => ( + + ))} + + ); +} + +const MoneyRequestModalStackNavigator = createModalStackNavigator({ + [SCREENS.MONEY_REQUEST.ROOT]: () => require('../../../pages/iou/MoneyRequestSelectorPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.AMOUNT]: () => require('../../../pages/iou/steps/NewRequestAmountPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.PARTICIPANTS]: () => require('../../../pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.CONFIRMATION]: () => require('../../../pages/iou/steps/MoneyRequestConfirmPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.CURRENCY]: () => require('../../../pages/iou/IOUCurrencySelection').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.DATE]: () => require('../../../pages/iou/MoneyRequestDatePage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.DESCRIPTION]: () => require('../../../pages/iou/MoneyRequestDescriptionPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.CATEGORY]: () => require('../../../pages/iou/MoneyRequestCategoryPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.TAG]: () => require('../../../pages/iou/MoneyRequestTagPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.MERCHANT]: () => require('../../../pages/iou/MoneyRequestMerchantPage').default as React.ComponentType, + [SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: () => require('../../../pages/AddPersonalBankAccountPage').default as React.ComponentType, + [SCREENS.IOU_SEND.ADD_DEBIT_CARD]: () => require('../../../pages/settings/Wallet/AddDebitCardPage').default as React.ComponentType, + [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.WAYPOINT]: () => require('../../../pages/iou/NewDistanceRequestWaypointEditorPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.EDIT_WAYPOINT]: () => require('../../../pages/iou/MoneyRequestEditWaypointPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.DISTANCE]: () => require('../../../pages/iou/NewDistanceRequestPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.RECEIPT]: () => require('../../../pages/EditRequestReceiptPage').default as React.ComponentType, +}); + +const SplitDetailsModalStackNavigator = createModalStackNavigator({ + [SCREENS.SPLIT_DETAILS_ROOT]: () => require('../../../pages/iou/SplitBillDetailsPage').default as React.ComponentType, +}); + +const DetailsModalStackNavigator = createModalStackNavigator({ + [SCREENS.DETAILS_ROOT]: () => require('../../../pages/DetailsPage').default as React.ComponentType, +}); + +const ProfileModalStackNavigator = createModalStackNavigator({ + [SCREENS.PROFILE_ROOT]: () => require('../../../pages/ProfilePage').default as React.ComponentType, +}); + +const ReportDetailsModalStackNavigator = createModalStackNavigator({ + [SCREENS.REPORT_DETAILS.ROOT]: () => require('../../../pages/ReportDetailsPage').default as React.ComponentType, + [SCREENS.REPORT_DETAILS.SHARE_CODE]: () => require('../../../pages/home/report/ReportDetailsShareCodePage').default as React.ComponentType, +}); + +const ReportSettingsModalStackNavigator = createModalStackNavigator({ + [SCREENS.REPORT_SETTINGS.ROOT]: () => require('../../../pages/settings/Report/ReportSettingsPage').default as React.ComponentType, + [SCREENS.REPORT_SETTINGS.ROOM_NAME]: () => require('../../../pages/settings/Report/RoomNamePage').default as React.ComponentType, + [SCREENS.REPORT_SETTINGS.NOTIFICATION_PREFERENCES]: () => require('../../../pages/settings/Report/NotificationPreferencePage').default as React.ComponentType, + [SCREENS.REPORT_SETTINGS.WRITE_CAPABILITY]: () => require('../../../pages/settings/Report/WriteCapabilityPage').default as React.ComponentType, +}); + +const TaskModalStackNavigator = createModalStackNavigator({ + [SCREENS.TASK.TITLE]: () => require('../../../pages/tasks/TaskTitlePage').default as React.ComponentType, + [SCREENS.TASK.DESCRIPTION]: () => require('../../../pages/tasks/TaskDescriptionPage').default as React.ComponentType, + [SCREENS.TASK.ASSIGNEE]: () => require('../../../pages/tasks/TaskAssigneeSelectorModal').default as React.ComponentType, +}); + +const ReportWelcomeMessageModalStackNavigator = createModalStackNavigator({ + [SCREENS.REPORT_WELCOME_MESSAGE_ROOT]: () => require('../../../pages/ReportWelcomeMessagePage').default as React.ComponentType, +}); + +const ReportParticipantsModalStackNavigator = createModalStackNavigator({ + [SCREENS.REPORT_PARTICIPANTS_ROOT]: () => require('../../../pages/ReportParticipantsPage').default as React.ComponentType, +}); + +const SearchModalStackNavigator = createModalStackNavigator({ + [SCREENS.SEARCH_ROOT]: () => require('../../../pages/SearchPage').default as React.ComponentType, +}); + +const NewChatModalStackNavigator = createModalStackNavigator({ + [SCREENS.NEW_CHAT_ROOT]: () => require('../../../pages/NewChatSelectorPage').default as React.ComponentType, +}); + +const NewTaskModalStackNavigator = createModalStackNavigator({ + [SCREENS.NEW_TASK.ROOT]: () => require('../../../pages/tasks/NewTaskPage').default as React.ComponentType, + [SCREENS.NEW_TASK.TASK_ASSIGNEE_SELECTOR]: () => require('../../../pages/tasks/TaskAssigneeSelectorModal').default as React.ComponentType, + [SCREENS.NEW_TASK.TASK_SHARE_DESTINATION_SELECTOR]: () => require('../../../pages/tasks/TaskShareDestinationSelectorModal').default as React.ComponentType, + [SCREENS.NEW_TASK.DETAILS]: () => require('../../../pages/tasks/NewTaskDetailsPage').default as React.ComponentType, + [SCREENS.NEW_TASK.TITLE]: () => require('../../../pages/tasks/NewTaskTitlePage').default as React.ComponentType, + [SCREENS.NEW_TASK.DESCRIPTION]: () => require('../../../pages/tasks/NewTaskDescriptionPage').default as React.ComponentType, +}); + +const NewTeachersUniteNavigator = createModalStackNavigator({ + [SCREENS.SAVE_THE_WORLD.ROOT]: () => require('../../../pages/TeachersUnite/SaveTheWorldPage').default as React.ComponentType, + [SCREENS.I_KNOW_A_TEACHER]: () => require('../../../pages/TeachersUnite/KnowATeacherPage').default as React.ComponentType, + [SCREENS.INTRO_SCHOOL_PRINCIPAL]: () => require('../../../pages/TeachersUnite/ImTeacherPage').default as React.ComponentType, + [SCREENS.I_AM_A_TEACHER]: () => require('../../../pages/TeachersUnite/ImTeacherPage').default as React.ComponentType, +}); + +const SettingsModalStackNavigator = createModalStackNavigator({ + [SCREENS.SETTINGS.ROOT]: () => require('../../../pages/settings/InitialSettingsPage').default as React.ComponentType, + [SCREENS.SETTINGS.SHARE_CODE]: () => require('../../../pages/ShareCodePage').default as React.ComponentType, + [SCREENS.SETTINGS.WORKSPACES]: () => require('../../../pages/workspace/WorkspacesListPage').default as React.ComponentType, + [SCREENS.SETTINGS.PROFILE]: () => require('../../../pages/settings/Profile/ProfilePage').default as React.ComponentType, + [SCREENS.SETTINGS.PRONOUNS]: () => require('../../../pages/settings/Profile/PronounsPage').default as React.ComponentType, + [SCREENS.SETTINGS.DISPLAY_NAME]: () => require('../../../pages/settings/Profile/DisplayNamePage').default as React.ComponentType, + [SCREENS.SETTINGS.TIMEZONE]: () => require('../../../pages/settings/Profile/TimezoneInitialPage').default as React.ComponentType, + [SCREENS.SETTINGS.TIMEZONE_SELECT]: () => require('../../../pages/settings/Profile/TimezoneSelectPage').default as React.ComponentType, + [SCREENS.SETTINGS.PERSONAL_DETAILS_INITIAL]: () => require('../../../pages/settings/Profile/PersonalDetails/PersonalDetailsInitialPage').default as React.ComponentType, + [SCREENS.SETTINGS.PERSONAL_DETAILS_LEGAL_NAME]: () => require('../../../pages/settings/Profile/PersonalDetails/LegalNamePage').default as React.ComponentType, + [SCREENS.SETTINGS.PERSONAL_DETAILS_DATE_OF_BIRTH]: () => require('../../../pages/settings/Profile/PersonalDetails/DateOfBirthPage').default as React.ComponentType, + [SCREENS.SETTINGS.PERSONAL_DETAILS_ADDRESS]: () => require('../../../pages/settings/Profile/PersonalDetails/AddressPage').default as React.ComponentType, + [SCREENS.SETTINGS.PERSONAL_DETAILS_ADDRESS_COUNTRY]: () => require('../../../pages/settings/Profile/PersonalDetails/CountrySelectionPage').default as React.ComponentType, + [SCREENS.SETTINGS.CONTACT_METHODS]: () => require('../../../pages/settings/Profile/Contacts/ContactMethodsPage').default as React.ComponentType, + [SCREENS.SETTINGS.CONTACT_METHOD_DETAILS]: () => require('../../../pages/settings/Profile/Contacts/ContactMethodDetailsPage').default as React.ComponentType, + [SCREENS.SETTINGS.NEW_CONTACT_METHOD]: () => require('../../../pages/settings/Profile/Contacts/NewContactMethodPage').default as React.ComponentType, + [SCREENS.SETTINGS.PREFERENCES]: () => require('../../../pages/settings/Preferences/PreferencesPage').default as React.ComponentType, + [SCREENS.SETTINGS.PREFERENCES_PRIORITY_MODE]: () => require('../../../pages/settings/Preferences/PriorityModePage').default as React.ComponentType, + [SCREENS.SETTINGS.PREFERENCES_LANGUAGE]: () => require('../../../pages/settings/Preferences/LanguagePage').default as React.ComponentType, + // Will be uncommented as part of https://github.com/Expensify/App/issues/21670 + // Settings_Preferences_Theme: () => require('../../../pages/settings/Preferences/ThemePage').default as React.ComponentType, + [SCREENS.SETTINGS.CLOSE]: () => require('../../../pages/settings/Security/CloseAccountPage').default as React.ComponentType, + [SCREENS.SETTINGS.SECURITY]: () => require('../../../pages/settings/Security/SecuritySettingsPage').default as React.ComponentType, + [SCREENS.SETTINGS.ABOUT]: () => require('../../../pages/settings/AboutPage/AboutPage').default as React.ComponentType, + [SCREENS.SETTINGS.APP_DOWNLOAD_LINKS]: () => require('../../../pages/settings/AppDownloadLinks').default as React.ComponentType, + [SCREENS.SETTINGS.LOUNGE_ACCESS]: () => require('../../../pages/settings/Profile/LoungeAccessPage').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET]: () => require('../../../pages/settings/Wallet/WalletPage').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_DOMAIN_CARDS]: () => require('../../../pages/settings/Wallet/ExpensifyCardPage').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_TRANSFER_BALANCE]: () => require('../../../pages/settings/Wallet/TransferBalancePage').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_CHOOSE_TRANSFER_ACCOUNT]: () => require('../../../pages/settings/Wallet/ChooseTransferAccountPage').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_ENABLE_PAYMENTS]: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default as React.ComponentType, + [SCREENS.SETTINGS.ADD_DEBIT_CARD]: () => require('../../../pages/settings/Wallet/AddDebitCardPage').default as React.ComponentType, + [SCREENS.SETTINGS.ADD_BANK_ACCOUNT]: () => require('../../../pages/AddPersonalBankAccountPage').default as React.ComponentType, + [SCREENS.SETTINGS.STATUS]: () => require('../../../pages/settings/Profile/CustomStatus/StatusPage').default as React.ComponentType, + [SCREENS.SETTINGS.STATUS_SET]: () => require('../../../pages/settings/Profile/CustomStatus/StatusSetPage').default as React.ComponentType, + [SCREENS.WORKSPACE.INITIAL]: () => require('../../../pages/workspace/WorkspaceInitialPage').default as React.ComponentType, + [SCREENS.WORKSPACE.SETTINGS]: () => require('../../../pages/workspace/WorkspaceSettingsPage').default as React.ComponentType, + [SCREENS.WORKSPACE.CARD]: () => require('../../../pages/workspace/card/WorkspaceCardPage').default as React.ComponentType, + [SCREENS.WORKSPACE.REIMBURSE]: () => require('../../../pages/workspace/reimburse/WorkspaceReimbursePage').default as React.ComponentType, + [SCREENS.WORKSPACE.RATE_AND_UNIT]: () => require('../../../pages/workspace/reimburse/WorkspaceRateAndUnitPage').default as React.ComponentType, + [SCREENS.WORKSPACE.BILLS]: () => require('../../../pages/workspace/bills/WorkspaceBillsPage').default as React.ComponentType, + [SCREENS.WORKSPACE.INVOICES]: () => require('../../../pages/workspace/invoices/WorkspaceInvoicesPage').default as React.ComponentType, + [SCREENS.WORKSPACE.TRAVEL]: () => require('../../../pages/workspace/travel/WorkspaceTravelPage').default as React.ComponentType, + [SCREENS.WORKSPACE.MEMBERS]: () => require('../../../pages/workspace/WorkspaceMembersPage').default as React.ComponentType, + [SCREENS.WORKSPACE.INVITE]: () => require('../../../pages/workspace/WorkspaceInvitePage').default as React.ComponentType, + [SCREENS.WORKSPACE.INVITE_MESSAGE]: () => require('../../../pages/workspace/WorkspaceInviteMessagePage').default as React.ComponentType, + [SCREENS.REIMBURSEMENT_ACCOUNT]: () => require('../../../pages/ReimbursementAccount/ReimbursementAccountPage').default as React.ComponentType, + [SCREENS.GET_ASSISTANCE]: () => require('../../../pages/GetAssistancePage').default as React.ComponentType, + [SCREENS.SETTINGS.TWO_FACTOR_AUTH]: () => require('../../../pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage').default as React.ComponentType, +}); + +const EnablePaymentsStackNavigator = createModalStackNavigator({ + [SCREENS.ENABLE_PAYMENTS_ROOT]: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default as React.ComponentType, +}); + +const AddPersonalBankAccountModalStackNavigator = createModalStackNavigator({ + [SCREENS.ADD_PERSONAL_BANK_ACCOUNT_ROOT]: () => require('../../../pages/AddPersonalBankAccountPage').default as React.ComponentType, +}); + +const ReimbursementAccountModalStackNavigator = createModalStackNavigator({ + [SCREENS.REIMBURSEMENT_ACCOUNT_ROOT]: () => require('../../../pages/ReimbursementAccount/ReimbursementAccountPage').default as React.ComponentType, +}); + +const WalletStatementStackNavigator = createModalStackNavigator({ + [SCREENS.WALLET_STATEMENT_ROOT]: () => require('../../../pages/wallet/WalletStatementPage').default as React.ComponentType, +}); + +const FlagCommentStackNavigator = createModalStackNavigator({ + [SCREENS.FLAG_COMMENT_ROOT]: () => require('../../../pages/FlagCommentPage').default as React.ComponentType, +}); + +const EditRequestStackNavigator = createModalStackNavigator({ + [SCREENS.EDIT_REQUEST.ROOT]: () => require('../../../pages/EditRequestPage').default as React.ComponentType, + [SCREENS.EDIT_REQUEST.CURRENCY]: () => require('../../../pages/iou/IOUCurrencySelection').default as React.ComponentType, +}); + +const PrivateNotesModalStackNavigator = createModalStackNavigator({ + [SCREENS.PRIVATE_NOTES.VIEW]: () => require('../../../pages/PrivateNotes/PrivateNotesViewPage').default as React.ComponentType, + [SCREENS.PRIVATE_NOTES.LIST]: () => require('../../../pages/PrivateNotes/PrivateNotesListPage').default as React.ComponentType, + [SCREENS.PRIVATE_NOTES.EDIT]: () => require('../../../pages/PrivateNotes/PrivateNotesEditPage').default as React.ComponentType, +}); + +const SignInModalStackNavigator = createModalStackNavigator({ + [SCREENS.SIGN_IN_ROOT]: () => require('../../../pages/signin/SignInModal').default as React.ComponentType, +}); + +export { + MoneyRequestModalStackNavigator, + SplitDetailsModalStackNavigator, + DetailsModalStackNavigator, + ProfileModalStackNavigator, + ReportDetailsModalStackNavigator, + TaskModalStackNavigator, + ReportSettingsModalStackNavigator, + ReportWelcomeMessageModalStackNavigator, + ReportParticipantsModalStackNavigator, + SearchModalStackNavigator, + NewChatModalStackNavigator, + NewTaskModalStackNavigator, + SettingsModalStackNavigator, + EnablePaymentsStackNavigator, + AddPersonalBankAccountModalStackNavigator, + ReimbursementAccountModalStackNavigator, + WalletStatementStackNavigator, + FlagCommentStackNavigator, + EditRequestStackNavigator, + PrivateNotesModalStackNavigator, + NewTeachersUniteNavigator, + SignInModalStackNavigator, +}; diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.tsx similarity index 89% rename from src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js rename to src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.tsx index 64eadcbe06c3..49c880bb2252 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.tsx @@ -5,8 +5,9 @@ import ReportScreenWrapper from '../ReportScreenWrapper'; import getCurrentUrl from '../../currentUrl'; import styles from '../../../../styles/styles'; import FreezeWrapper from '../../FreezeWrapper'; +import type {CentralPaneStackParamList} from '../types'; -const Stack = createStackNavigator(); +const Stack = createStackNavigator(); const url = getCurrentUrl(); const openOnAdminRoom = url ? new URL(url).searchParams.get('openOnAdminRoom') : undefined; @@ -18,7 +19,7 @@ function CentralPaneNavigator() { unknown; }; -function Overlay(props) { +function Overlay(props: OverlayProps) { const {current} = useCardAnimation(); - const {translate} = useLocalize(); + // TODO: remove type assertion when useLocalize is migrated + const {translate} = useLocalize() as unknown as {translate: (phrase: string) => string}; return ( - {/* In the latest Electron version buttons can't be both clickable and draggable. - That's why we added this workaround. Because of two Pressable components on the desktop app + {/* In the latest Electron version buttons can't be both clickable and draggable. + That's why we added this workaround. Because of two Pressable components on the desktop app we have 30px draggable ba at the top and the rest of the dimmed area is clickable. On other devices, everything behaves normally like one big pressable */} (); -const propTypes = { - ...withNavigationPropTypes, -}; - -function RightModalNavigator(props) { - const {isSmallScreenWidth} = useWindowDimensions(); +function RightModalNavigator(props: StackScreenProps) { + // TODO: remove type assertion when useWindowDimensions is migrated to TS + const {isSmallScreenWidth} = useWindowDimensions() as WindowDimensions; return ( @@ -118,7 +117,6 @@ function RightModalNavigator(props) { ); } -RightModalNavigator.propTypes = propTypes; RightModalNavigator.displayName = 'RightModalNavigator'; export default RightModalNavigator; diff --git a/src/libs/Navigation/AppNavigator/PublicScreens.js b/src/libs/Navigation/AppNavigator/PublicScreens.tsx similarity index 84% rename from src/libs/Navigation/AppNavigator/PublicScreens.js rename to src/libs/Navigation/AppNavigator/PublicScreens.tsx index 7a87530a2d9e..fa3c9dc8d806 100644 --- a/src/libs/Navigation/AppNavigator/PublicScreens.js +++ b/src/libs/Navigation/AppNavigator/PublicScreens.tsx @@ -8,8 +8,9 @@ import defaultScreenOptions from './defaultScreenOptions'; import UnlinkLoginPage from '../../../pages/UnlinkLoginPage'; import AppleSignInDesktopPage from '../../../pages/signin/AppleSignInDesktopPage'; import GoogleSignInDesktopPage from '../../../pages/signin/GoogleSignInDesktopPage'; +import {PublicScreensStackParamList} from './types'; -const RootStack = createStackNavigator(); +const RootStack = createStackNavigator(); function PublicScreens() { return ( @@ -25,22 +26,22 @@ function PublicScreens() { component={LogInWithShortLivedAuthTokenPage} /> diff --git a/src/libs/Navigation/AppNavigator/RHPScreenOptions.js b/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts similarity index 72% rename from src/libs/Navigation/AppNavigator/RHPScreenOptions.js rename to src/libs/Navigation/AppNavigator/RHPScreenOptions.ts index d7448dcf2314..b21f29fc466e 100644 --- a/src/libs/Navigation/AppNavigator/RHPScreenOptions.js +++ b/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts @@ -1,4 +1,4 @@ -import {CardStyleInterpolators} from '@react-navigation/stack'; +import {CardStyleInterpolators, StackNavigationOptions} from '@react-navigation/stack'; import styles from '../../../styles/styles'; const RHPScreenOptions = { @@ -7,6 +7,6 @@ const RHPScreenOptions = { gestureDirection: 'horizontal', cardStyle: styles.navigationScreenCardStyle, cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, -}; +} as StackNavigationOptions; export default RHPScreenOptions; diff --git a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.js b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts similarity index 54% rename from src/libs/Navigation/AppNavigator/ReportScreenIDSetter.js rename to src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts index 24f855645870..de725a59f42c 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.js +++ b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts @@ -1,91 +1,66 @@ import {useEffect} from 'react'; -import PropTypes from 'prop-types'; -import lodashGet from 'lodash/get'; -import {withOnyx} from 'react-native-onyx'; +import {OnyxCollection, OnyxEntry, withOnyx} from 'react-native-onyx'; import ONYXKEYS from '../../../ONYXKEYS'; import * as ReportUtils from '../../ReportUtils'; -import reportPropTypes from '../../../pages/reportPropTypes'; -import {withNavigationPropTypes} from '../../../components/withNavigation'; import * as App from '../../actions/App'; import usePermissions from '../../../hooks/usePermissions'; import CONST from '../../../CONST'; import Navigation from '../Navigation'; +import {Policy, Report} from '../../../types/onyx'; +import {ReportScreenWrapperProps} from './types'; -const propTypes = { +type ReportScreenIDSetterComponentProps = { /** Available reports that would be displayed in this navigator */ - reports: PropTypes.objectOf(reportPropTypes), + reports: OnyxCollection; /** The policies which the user has access to */ - policies: PropTypes.objectOf( - PropTypes.shape({ - /** The policy name */ - name: PropTypes.string, + policies: OnyxCollection; - /** The type of the policy */ - type: PropTypes.string, - }), - ), - - isFirstTimeNewExpensifyUser: PropTypes.bool, - - /** Navigation route context info provided by react navigation */ - route: PropTypes.shape({ - /** Route specific parameters used on this screen */ - params: PropTypes.shape({ - /** If the admin room should be opened */ - openOnAdminRoom: PropTypes.bool, - - /** The ID of the report this screen should display */ - reportID: PropTypes.string, - }), - }).isRequired, - - ...withNavigationPropTypes, + isFirstTimeNewExpensifyUser: OnyxEntry; }; -const defaultProps = { - reports: {}, - policies: {}, - isFirstTimeNewExpensifyUser: false, -}; +type ReportScreenIDSetterProps = ReportScreenIDSetterComponentProps & ReportScreenWrapperProps; /** * Get the most recently accessed report for the user - * - * @param {Object} reports - * @param {Boolean} ignoreDefaultRooms - * @param {Object} policies - * @param {Boolean} isFirstTimeNewExpensifyUser - * @param {Boolean} openOnAdminRoom - * @returns {Number} */ -const getLastAccessedReportID = (reports, ignoreDefaultRooms, policies, isFirstTimeNewExpensifyUser, openOnAdminRoom) => { +const getLastAccessedReportID = ( + reports: OnyxCollection | Report[], + ignoreDefaultRooms: boolean, + policies: OnyxCollection, + isFirstTimeNewExpensifyUser: OnyxEntry, + openOnAdminRoom: boolean, +): number | string => { // If deeplink url is of an attachment, we should show the report that the attachment comes from. const currentRoute = Navigation.getActiveRoute(); const matches = CONST.REGEX.ATTACHMENT_ROUTE.exec(currentRoute); - const reportID = lodashGet(matches, 1, null); + const reportID = matches?.[1] ?? null; if (reportID) { return reportID; } - const lastReport = ReportUtils.findLastAccessedReport(reports, ignoreDefaultRooms, policies, isFirstTimeNewExpensifyUser, openOnAdminRoom); + // TODO: get rid of ignore when ReportUtils is migrated to TS + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore till ReportUtils file is migrated + const lastReport = ReportUtils.findLastAccessedReport(reports, ignoreDefaultRooms, policies, isFirstTimeNewExpensifyUser, openOnAdminRoom) as Report; - return lodashGet(lastReport, 'reportID'); + return lastReport?.reportID; }; // This wrapper is reponsible for opening the last accessed report if there is no reportID specified in the route params -function ReportScreenIDSetter({route, reports, policies, isFirstTimeNewExpensifyUser, navigation}) { - const {canUseDefaultRooms} = usePermissions(); +function ReportScreenIDSetter({route, reports, policies, isFirstTimeNewExpensifyUser, navigation}: ReportScreenIDSetterProps): null { + // TODO: remove type assertion when usePermissions is migrated + const {canUseDefaultRooms} = usePermissions() as {canUseDefaultRooms: boolean}; useEffect(() => { // Don't update if there is a reportID in the params already - if (lodashGet(route, 'params.reportID', null)) { + if (route?.params?.reportID ?? null) { App.confirmReadyToOpenApp(); return; } // If there is no reportID in route, try to find last accessed and use it for setParams - const reportID = getLastAccessedReportID(reports, !canUseDefaultRooms, policies, isFirstTimeNewExpensifyUser, lodashGet(route, 'params.openOnAdminRoom', false)); + const reportID = getLastAccessedReportID(reports, !canUseDefaultRooms, policies, isFirstTimeNewExpensifyUser, reports?.params?.openOnAdminRoom ?? false); // It's possible that reports aren't fully loaded yet // in that case the reportID is undefined @@ -101,21 +76,26 @@ function ReportScreenIDSetter({route, reports, policies, isFirstTimeNewExpensify return null; } -ReportScreenIDSetter.propTypes = propTypes; -ReportScreenIDSetter.defaultProps = defaultProps; ReportScreenIDSetter.displayName = 'ReportScreenIDSetter'; -export default withOnyx({ +export default withOnyx({ reports: { key: ONYXKEYS.COLLECTION.REPORT, + // TODO: I think we need to update onyx mapping types to include allowStaleData/initialValue keys + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore allowStaleData: true, }, policies: { key: ONYXKEYS.COLLECTION.POLICY, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore allowStaleData: true, }, isFirstTimeNewExpensifyUser: { key: ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore initialValue: false, }, })(ReportScreenIDSetter); diff --git a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.js b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.js deleted file mode 100644 index 767bd9793ac2..000000000000 --- a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.js +++ /dev/null @@ -1,43 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import {withNavigationPropTypes} from '../../../components/withNavigation'; -import ReportScreen from '../../../pages/home/ReportScreen'; -import ReportScreenIDSetter from './ReportScreenIDSetter'; - -const propTypes = { - /** Navigation route context info provided by react navigation */ - route: PropTypes.shape({ - /** Route specific parameters used on this screen */ - params: PropTypes.shape({ - /** If the admin room should be opened */ - openOnAdminRoom: PropTypes.bool, - - /** The ID of the report this screen should display */ - reportID: PropTypes.string, - }), - }).isRequired, - - ...withNavigationPropTypes, -}; - -const defaultProps = {}; - -function ReportScreenWrapper(props) { - // The ReportScreen without the reportID set will display a skeleton - // until the reportID is loaded and set in the route param - return ( - <> - - - - ); -} - -ReportScreenWrapper.propTypes = propTypes; -ReportScreenWrapper.defaultProps = defaultProps; -ReportScreenWrapper.displayName = 'ReportScreenWrapper'; - -export default ReportScreenWrapper; diff --git a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx new file mode 100644 index 000000000000..2c17bf4b2ed0 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import ReportScreen from '../../../pages/home/ReportScreen'; +import ReportScreenIDSetter from './ReportScreenIDSetter'; +import {ReportScreenWrapperProps} from './types'; + +function ReportScreenWrapper(props: ReportScreenWrapperProps) { + // The ReportScreen without the reportID set will display a skeleton + // until the reportID is loaded and set in the route param + return ( + <> + {/* TODO: Remove when ReportScreen is migrated */} + {/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */} + {/* @ts-ignore */} + + + + ); +} + +ReportScreenWrapper.displayName = 'ReportScreenWrapper'; + +export default ReportScreenWrapper; diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts similarity index 60% rename from src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js rename to src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts index a3d8398a22b0..845a37a95c20 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts @@ -1,31 +1,32 @@ -import _ from 'underscore'; -import {StackRouter} from '@react-navigation/native'; +import {StackRouter, RouterConfigOptions, ParamListBase, StackNavigationState, PartialState} from '@react-navigation/native'; import NAVIGATORS from '../../../../NAVIGATORS'; +import {ResponsiveStackNavigatorRouterOptions} from '../types'; -/** - * @param {Object} state - react-navigation state - * @returns {Boolean} - */ -const isAtLeastOneCentralPaneNavigatorInState = (state) => _.find(state.routes, (r) => r.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR); +type MutableState = { + index: number; + stale: true; +}; + +type State = Omit>, 'stale'> & MutableState; + +const isAtLeastOneCentralPaneNavigatorInState = (state: State): boolean => !!state.routes.find((r) => r.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR); /** * Adds report route without any specific reportID to the state. * The report screen will self set proper reportID param based on the helper function findLastAccessedReport (look at ReportScreenWrapper for more info) - * - * @param {Object} state - react-navigation state */ -const addCentralPaneNavigatorRoute = (state) => { +const addCentralPaneNavigatorRoute = (state: State) => { state.routes.splice(1, 0, {name: NAVIGATORS.CENTRAL_PANE_NAVIGATOR}); // eslint-disable-next-line no-param-reassign state.index = state.routes.length - 1; }; -function CustomRouter(options) { +function CustomRouter(options: ResponsiveStackNavigatorRouterOptions) { const stackRouter = StackRouter(options); return { ...stackRouter, - getRehydratedState(partialState, {routeNames, routeParamList}) { + getRehydratedState(partialState: State, {routeNames, routeParamList, routeGetIdList}: RouterConfigOptions) { // Make sure that there is at least one CentralPaneNavigator (ReportScreen by default) in the state if this is a wide layout if (!isAtLeastOneCentralPaneNavigatorInState(partialState) && !options.getIsSmallScreenWidth()) { // If we added a route we need to make sure that the state.stale is true to generate new key for this route @@ -33,7 +34,7 @@ function CustomRouter(options) { partialState.stale = true; addCentralPaneNavigatorRoute(partialState); } - const state = stackRouter.getRehydratedState(partialState, {routeNames, routeParamList}); + const state = stackRouter.getRehydratedState(partialState, {routeNames, routeParamList, routeGetIdList}); return state; }, }; diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js deleted file mode 100644 index 58be3d2af3da..000000000000 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js +++ /dev/null @@ -1,60 +0,0 @@ -import React, {useRef} from 'react'; -import PropTypes from 'prop-types'; -import {useNavigationBuilder, createNavigatorFactory} from '@react-navigation/native'; -import {StackView} from '@react-navigation/stack'; -import CustomRouter from './CustomRouter'; -import useWindowDimensions from '../../../../hooks/useWindowDimensions'; - -const propTypes = { - /* Determines if the navigator should render the StackView (narrow) or ThreePaneView (wide) */ - isSmallScreenWidth: PropTypes.bool.isRequired, - - /* Children for the useNavigationBuilder hook */ - children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired, - - /* initialRouteName for this navigator */ - initialRouteName: PropTypes.oneOf([PropTypes.string, PropTypes.undefined]), - - /* Screen options defined for this navigator */ - // eslint-disable-next-line react/forbid-prop-types - screenOptions: PropTypes.object, -}; - -const defaultProps = { - initialRouteName: undefined, - screenOptions: undefined, -}; - -function ResponsiveStackNavigator(props) { - const {isSmallScreenWidth} = useWindowDimensions(); - - const isSmallScreenWidthRef = useRef(isSmallScreenWidth); - - isSmallScreenWidthRef.current = isSmallScreenWidth; - - const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder(CustomRouter, { - children: props.children, - screenOptions: props.screenOptions, - initialRouteName: props.initialRouteName, - // Options for useNavigationBuilder won't update on prop change, so we need to pass a getter for the router to have the current state of isSmallScreenWidth. - getIsSmallScreenWidth: () => isSmallScreenWidthRef.current, - }); - - return ( - - - - ); -} - -ResponsiveStackNavigator.defaultProps = defaultProps; -ResponsiveStackNavigator.propTypes = propTypes; -ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator'; - -export default createNavigatorFactory(ResponsiveStackNavigator); diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx new file mode 100644 index 000000000000..a97bb3de9611 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx @@ -0,0 +1,46 @@ +import React, {useRef} from 'react'; +import {useNavigationBuilder, createNavigatorFactory, ParamListBase, StackActionHelpers, StackNavigationState} from '@react-navigation/native'; +import {StackNavigationEventMap, StackNavigationOptions, StackView} from '@react-navigation/stack'; +import CustomRouter from './CustomRouter'; +import useWindowDimensions from '../../../../hooks/useWindowDimensions'; +import {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from '../types'; +import type {WindowDimensions} from '../../../../styles/getModalStyles'; + +function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) { + // TODO: remove type assertion when useWindowDimensions is migrated to TS + const {isSmallScreenWidth} = useWindowDimensions() as WindowDimensions; + + const isSmallScreenWidthRef = useRef(isSmallScreenWidth); + + isSmallScreenWidthRef.current = isSmallScreenWidth; + + const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder< + StackNavigationState, + ResponsiveStackNavigatorRouterOptions, + StackActionHelpers, + StackNavigationOptions, + StackNavigationEventMap + >(CustomRouter, { + children: props.children, + screenOptions: props.screenOptions, + initialRouteName: props.initialRouteName, + // Options for useNavigationBuilder won't update on prop change, so we need to pass a getter for the router to have the current state of isSmallScreenWidth. + getIsSmallScreenWidth: () => isSmallScreenWidthRef.current, + }); + + return ( + + + + ); +} + +ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator'; + +export default createNavigatorFactory, StackNavigationOptions, StackNavigationEventMap, typeof ResponsiveStackNavigator>(ResponsiveStackNavigator); diff --git a/src/libs/Navigation/AppNavigator/defaultScreenOptions.js b/src/libs/Navigation/AppNavigator/defaultScreenOptions.ts similarity index 68% rename from src/libs/Navigation/AppNavigator/defaultScreenOptions.js rename to src/libs/Navigation/AppNavigator/defaultScreenOptions.ts index 3ccffb5f09ab..745e66c52e94 100644 --- a/src/libs/Navigation/AppNavigator/defaultScreenOptions.js +++ b/src/libs/Navigation/AppNavigator/defaultScreenOptions.ts @@ -1,3 +1,5 @@ +import {StackNavigationOptions} from '@react-navigation/stack'; + const defaultScreenOptions = { cardStyle: { overflow: 'visible', @@ -5,6 +7,6 @@ const defaultScreenOptions = { }, headerShown: false, animationTypeForReplace: 'push', -}; +} as StackNavigationOptions; export default defaultScreenOptions; diff --git a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts similarity index 71% rename from src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js rename to src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts index a7456fb071b4..48dac2d13051 100644 --- a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js +++ b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts @@ -1,3 +1,4 @@ +import {StackCardInterpolationProps, StackNavigationOptions} from '@react-navigation/stack'; import modalCardStyleInterpolator from './modalCardStyleInterpolator'; import styles from '../../../styles/styles'; import variables from '../../../styles/variables'; @@ -10,12 +11,12 @@ const commonScreenOptions = { animationEnabled: true, cardOverlayEnabled: true, animationTypeForReplace: 'push', -}; +} as StackNavigationOptions; -export default (isSmallScreenWidth) => ({ +export default (isSmallScreenWidth: boolean) => ({ rightModalNavigator: { ...commonScreenOptions, - cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, false, props), + cardStyleInterpolator: (props: StackCardInterpolationProps) => modalCardStyleInterpolator(isSmallScreenWidth, false, props), presentation: 'transparentModal', // We want pop in RHP since there are some flows that would work weird otherwise @@ -28,12 +29,12 @@ export default (isSmallScreenWidth) => ({ // Excess space should be on the left so we need to position from right. right: 0, }, - }, + } as StackNavigationOptions, homeScreen: { title: CONFIG.SITE_TITLE, ...commonScreenOptions, - cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, false, props), + cardStyleInterpolator: (props: StackCardInterpolationProps) => modalCardStyleInterpolator(isSmallScreenWidth, false, props), cardStyle: { ...getNavigationModalCardStyle(), @@ -43,28 +44,27 @@ export default (isSmallScreenWidth) => ({ transform: [{translateX: isSmallScreenWidth ? 0 : -variables.sideBarWidth}], ...(isSmallScreenWidth ? {} : styles.borderRight), }, - }, - // eslint-disable-next-line rulesdir/no-negated-variables + } as StackNavigationOptions, fullScreen: { ...commonScreenOptions, - cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, true, props), + cardStyleInterpolator: (props: StackCardInterpolationProps) => modalCardStyleInterpolator(isSmallScreenWidth, true, props), cardStyle: { ...getNavigationModalCardStyle(), // This is necessary to cover whole screen. Including translated sidebar. marginLeft: isSmallScreenWidth ? 0 : -variables.sideBarWidth, }, - }, + } as StackNavigationOptions, centralPaneNavigator: { title: CONFIG.SITE_TITLE, ...commonScreenOptions, animationEnabled: isSmallScreenWidth, - cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, true, props), + cardStyleInterpolator: (props: StackCardInterpolationProps) => modalCardStyleInterpolator(isSmallScreenWidth, true, props), cardStyle: { ...getNavigationModalCardStyle(), paddingRight: isSmallScreenWidth ? 0 : variables.sideBarWidth, }, - }, + } as StackNavigationOptions, }); diff --git a/src/libs/Navigation/AppNavigator/index.js b/src/libs/Navigation/AppNavigator/index.tsx similarity index 73% rename from src/libs/Navigation/AppNavigator/index.js rename to src/libs/Navigation/AppNavigator/index.tsx index dee8027b2f30..d2cf587b8fa8 100644 --- a/src/libs/Navigation/AppNavigator/index.js +++ b/src/libs/Navigation/AppNavigator/index.tsx @@ -1,12 +1,11 @@ import React from 'react'; -import PropTypes from 'prop-types'; -const propTypes = { +type AppNavigatorProps = { /** If we have an authToken this is true */ - authenticated: PropTypes.bool.isRequired, + authenticated: boolean; }; -function AppNavigator(props) { +function AppNavigator(props: AppNavigatorProps) { if (props.authenticated) { const AuthScreens = require('./AuthScreens').default; @@ -17,6 +16,5 @@ function AppNavigator(props) { return ; } -AppNavigator.propTypes = propTypes; AppNavigator.displayName = 'AppNavigator'; export default AppNavigator; diff --git a/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.js b/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts similarity index 70% rename from src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.js rename to src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts index ec442efbba86..7dd26be93252 100644 --- a/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.js +++ b/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts @@ -1,8 +1,9 @@ import {Animated} from 'react-native'; +import type {StackCardInterpolatedStyle, StackCardInterpolationProps} from '@react-navigation/stack'; import variables from '../../../styles/variables'; import getCardStyles from '../../../styles/cardStyles'; -export default (isSmallScreenWidth, isFullScreenModal, {current: {progress}, inverted, layouts: {screen}}) => { +export default (isSmallScreenWidth: boolean, isFullScreenModal: boolean, {current: {progress}, inverted, layouts: {screen}}: StackCardInterpolationProps): StackCardInterpolatedStyle => { const translateX = Animated.multiply( progress.interpolate({ inputRange: [0, 1], diff --git a/src/libs/Navigation/AppNavigator/types.ts b/src/libs/Navigation/AppNavigator/types.ts new file mode 100644 index 000000000000..67286a6cbd85 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/types.ts @@ -0,0 +1,87 @@ +import {StackScreenProps, StackNavigationOptions, StackNavigationEventMap} from '@react-navigation/stack'; +import {DefaultNavigatorOptions, ParamListBase, StackNavigationState, DefaultRouterOptions, NavigatorScreenParams} from '@react-navigation/native'; +import {ValueOf} from 'type-fest'; + +import SCREENS from '../../../SCREENS'; +import NAVIGATORS from '../../../NAVIGATORS'; +import CONST from '../../../CONST'; + +type AccountValidationParams = { + /** AccountID associated with the validation link */ + accountID: string; + + /** Validation code associated with the validation link */ + validateCode: string; +}; + +type CentralPaneStackParamList = { + [SCREENS.REPORT]: { + /** If the admin room should be opened */ + openOnAdminRoom?: boolean; + + /** The ID of the report this screen should display */ + reportID: string; + }; +}; +type ReportScreenWrapperProps = StackScreenProps; + +type PublicScreensStackParamList = { + [SCREENS.HOME]: undefined; + [SCREENS.TRANSITION_BETWEEN_APPS]: { + /** Short-lived authToken to sign in a user */ + shortLivedAuthToken: string; + + /** Short-lived authToken to sign in as a user, if they are coming from the old mobile app */ + shortLivedToken: string; + + /** The email of the transitioning user */ + email: string; + }; + [SCREENS.VALIDATE_LOGIN]: AccountValidationParams; + [SCREENS.UNLINK_LOGIN]: AccountValidationParams; + [SCREENS.SIGN_IN_WITH_APPLE_DESKTOP]: undefined; + [SCREENS.SIGN_IN_WITH_GOOGLE_DESKTOP]: undefined; +}; + +type AuthScreensStackParamList = { + [SCREENS.HOME]: undefined; + [NAVIGATORS.CENTRAL_PANE_NAVIGATOR]: NavigatorScreenParams; + [SCREENS.VALIDATE_LOGIN]: AccountValidationParams; + [SCREENS.TRANSITION_BETWEEN_APPS]: undefined; + [SCREENS.CONCIERGE]: undefined; + [CONST.DEMO_PAGES.SAASTR]: {name: string}; + [CONST.DEMO_PAGES.SBE]: {name: string}; + [SCREENS.REPORT_ATTACHMENTS]: { + /** The report ID which the attachment is associated with */ + reportID: string; + + /** The uri encoded source of the attachment */ + source: string; + }; + [SCREENS.NOT_FOUND]: undefined; + [NAVIGATORS.RIGHT_MODAL_NAVIGATOR]: NavigatorScreenParams; + [SCREENS.DESKTOP_SIGN_IN_REDIRECT]: undefined; +}; + +// TODO: describe all of the nested navigators +type RightModalNavigatorStackParamList = Record, undefined>; + +type ResponsiveStackNavigatorConfig = { + isSmallScreenWidth: boolean; +}; +type ResponsiveStackNavigatorRouterOptions = DefaultRouterOptions & { + getIsSmallScreenWidth: () => boolean; +}; +type ResponsiveStackNavigatorProps = DefaultNavigatorOptions, StackNavigationOptions, StackNavigationEventMap> & + ResponsiveStackNavigatorConfig; + +export type { + CentralPaneStackParamList, + ReportScreenWrapperProps, + PublicScreensStackParamList, + RightModalNavigatorStackParamList, + ResponsiveStackNavigatorRouterOptions, + ResponsiveStackNavigatorProps, + ResponsiveStackNavigatorConfig, + AuthScreensStackParamList, +}; diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js index de6162685079..5cbd8e9b0af6 100644 --- a/src/libs/Navigation/Navigation.js +++ b/src/libs/Navigation/Navigation.js @@ -77,7 +77,7 @@ const getActiveRouteIndex = function (route, index) { /** * Main navigation method for redirecting to a route. * @param {String} route - * @param {String} type - Type of action to perform. Currently UP is supported. + * @param {String} [type] - Type of action to perform. Currently UP is supported. */ function navigate(route = ROUTES.HOME, type) { if (!canNavigate('navigate', {route})) { diff --git a/src/libs/compose.ts b/src/libs/compose.ts index dadc586d0f0d..043e1e9f1bd5 100644 --- a/src/libs/compose.ts +++ b/src/libs/compose.ts @@ -17,41 +17,40 @@ * hoc3(config3), * )(Component) */ + +type Func = (...a: T) => R; + export default function compose(): (a: R) => R; export default function compose(f: F): F; /* two functions */ -export default function compose(f1: (...args: A) => R1, f2: (a: R1) => R2): (...args: A) => R2; +export default function compose(f1: (args: A) => R1, f2: Func): Func; /* three functions */ -export default function compose(f1: (...args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3): (...args: A) => R3; +export default function compose(f1: (args: A) => R1, f2: (a: R1) => R2, f3: Func): Func; /* four functions */ -export default function compose(f1: (...args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3, f4: (a: R3) => R4): (...args: A) => R4; +export default function compose(f1: (args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3, f4: Func): Func; /* five functions */ -export default function compose( - f1: (...args: A) => R1, - f2: (a: R1) => R2, - f3: (a: R2) => R3, - f4: (a: R3) => R4, - f5: (a: R4) => R5, -): (...args: A) => R5; +export default function compose(f1: (args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3, f4: (a: R3) => R4, f5: Func): Func; /* six functions */ -export default function compose( - f1: (...args: A) => R1, +export default function compose( + f1: (args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3, f4: (a: R3) => R4, f5: (a: R4) => R5, - f6: (a: R5) => R6, -): (...args: A) => R6; + f6: Func, +): Func; /* rest */ export default function compose(f1: (a: unknown) => R, ...funcs: Function[]): (...args: unknown[]) => R; +export default function compose(...funcs: Function[]): (...args: unknown[]) => R; + export default function compose(...funcs: Function[]): Function { if (funcs.length === 0) { // infer the argument type so it is usable in inference down the line diff --git a/src/styles/cardStyles/types.ts b/src/styles/cardStyles/types.ts index e1598b7696ff..ce3e377bdc8f 100644 --- a/src/styles/cardStyles/types.ts +++ b/src/styles/cardStyles/types.ts @@ -1,6 +1,6 @@ import {CSSProperties} from 'react'; import {ViewStyle} from 'react-native'; -type GetCardStyles = (screenWidth: number) => Partial>; +type GetCardStyles = (screenWidth: number) => Partial>; export default GetCardStyles; diff --git a/src/styles/getModalStyles.ts b/src/styles/getModalStyles.ts index 32e6cf6f98e7..6af1354a4112 100644 --- a/src/styles/getModalStyles.ts +++ b/src/styles/getModalStyles.ts @@ -300,3 +300,4 @@ export default function getModalStyles( shouldAddTopSafeAreaPadding, }; } +export type {WindowDimensions}; diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index e2d4da88a0fb..5d22eaedd788 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -57,6 +57,9 @@ type Report = { /** The report type */ type?: string; + /** If the admin room should be opened */ + openOnAdminRoom?: boolean; + parentReportID?: string; parentReportActionID?: string; isOptimisticReport?: boolean; From fa528388f44aefd2a2fc59648b106274b2c928a3 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 10 Oct 2023 09:53:43 +0200 Subject: [PATCH 02/23] Fix ts error --- src/libs/NetworkConnection.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/NetworkConnection.ts b/src/libs/NetworkConnection.ts index 663a9c1b37d5..7c1bcaa0b339 100644 --- a/src/libs/NetworkConnection.ts +++ b/src/libs/NetworkConnection.ts @@ -13,7 +13,7 @@ let hasPendingNetworkCheck = false; // Holds all of the callbacks that need to be triggered when the network reconnects let callbackID = 0; -const reconnectionCallbacks: Record Promise> = {}; +const reconnectionCallbacks: Record void> = {}; /** * Loop over all reconnection callbacks and fire each one @@ -122,7 +122,7 @@ function listenForReconnect() { * Register callback to fire when we reconnect * @returns unsubscribe method */ -function onReconnect(callback: () => Promise): () => void { +function onReconnect(callback: () => void): () => void { const currentID = callbackID; callbackID++; reconnectionCallbacks[currentID] = callback; From 0a8b4ad6177ff5a2fe0f1b7cd16d176b35ec8fcf Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Thu, 12 Oct 2023 10:25:36 +0200 Subject: [PATCH 03/23] Minor code improvements --- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 12 +++++------- .../Navigation/AppNavigator/Navigators/Overlay.tsx | 2 +- src/libs/Navigation/AppNavigator/RHPScreenOptions.ts | 4 ++-- .../Navigation/AppNavigator/ReportScreenIDSetter.ts | 2 +- .../Navigation/AppNavigator/defaultScreenOptions.ts | 4 ++-- .../AppNavigator/getRootNavigatorScreenOptions.ts | 4 ++-- src/libs/Navigation/Navigation.js | 2 +- 7 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 5e8f471d4a79..c6269163a7f8 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -35,6 +35,7 @@ import DemoSetupPage from '../../../pages/DemoSetupPage'; import * as OnyxTypes from '../../../types/onyx'; import type {WindowDimensions} from '../../../styles/getModalStyles'; import type {AuthScreensStackParamList} from './types'; +import type {Timezone} from '../../../types/onyx/PersonalDetails'; type AuthScreensOnyxProps = { /** Session of currently logged in user */ @@ -52,11 +53,6 @@ type AuthScreensOnyxProps = { type AuthScreensProps = WindowDimensions & AuthScreensOnyxProps; -type Timezone = { - automatic?: boolean; - selected?: string; -}; - type UnsubscribeChatShortcut = () => void; type UnsubscribeSearchShortcut = () => void; @@ -76,7 +72,7 @@ Onyx.connect({ currentAccountID = val.accountID; if (Navigation.isActiveRoute(ROUTES.SIGN_IN_MODAL)) { // This means sign in in RHP was successful, so we can dismiss the modal and subscribe to user events - Navigation.dismissModal(undefined); + Navigation.dismissModal(); User.subscribeToUserEvents(); } }, @@ -94,7 +90,7 @@ Onyx.connect({ // If the current timezone is different than the user's timezone, and their timezone is set to automatic // then update their timezone. - if (timezone !== null && timezone.automatic && timezone.selected !== currentTimezone) { + if (timezone?.automatic && timezone?.selected !== currentTimezone) { timezone.selected = currentTimezone; PersonalDetails.updateAutomaticTimezone({ automatic: true, @@ -200,6 +196,7 @@ class AuthScreens extends React.Component { searchShortcutConfig.descriptionKey, [...searchShortcutConfig.modifiers], true, + // TODO: remove type assertion when KeyboardShortcut is migrated ) as UnsubscribeSearchShortcut; this.unsubscribeChatShortcut = KeyboardShortcut.subscribe( chatShortcutConfig.shortcutKey, @@ -214,6 +211,7 @@ class AuthScreens extends React.Component { chatShortcutConfig.descriptionKey, [...chatShortcutConfig.modifiers], true, + // TODO: remove type assertion when KeyboardShortcut is migrated ) as UnsubscribeChatShortcut; } diff --git a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx index 66888ac6201c..19b8a0b4453a 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx @@ -9,7 +9,7 @@ import useLocalize from '../../../../hooks/useLocalize'; import CONST from '../../../../CONST'; type OverlayProps = { - onPress: () => unknown; + onPress: () => void; }; function Overlay(props: OverlayProps) { diff --git a/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts b/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts index b21f29fc466e..ae2244cb510b 100644 --- a/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts +++ b/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts @@ -1,12 +1,12 @@ import {CardStyleInterpolators, StackNavigationOptions} from '@react-navigation/stack'; import styles from '../../../styles/styles'; -const RHPScreenOptions = { +const RHPScreenOptions: StackNavigationOptions = { headerShown: false, animationEnabled: true, gestureDirection: 'horizontal', cardStyle: styles.navigationScreenCardStyle, cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, -} as StackNavigationOptions; +}; export default RHPScreenOptions; diff --git a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts index de725a59f42c..2a5f7e3aac31 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts +++ b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts @@ -25,7 +25,7 @@ type ReportScreenIDSetterProps = ReportScreenIDSetterComponentProps & ReportScre * Get the most recently accessed report for the user */ const getLastAccessedReportID = ( - reports: OnyxCollection | Report[], + reports: OnyxCollection, ignoreDefaultRooms: boolean, policies: OnyxCollection, isFirstTimeNewExpensifyUser: OnyxEntry, diff --git a/src/libs/Navigation/AppNavigator/defaultScreenOptions.ts b/src/libs/Navigation/AppNavigator/defaultScreenOptions.ts index 745e66c52e94..65a6bd052742 100644 --- a/src/libs/Navigation/AppNavigator/defaultScreenOptions.ts +++ b/src/libs/Navigation/AppNavigator/defaultScreenOptions.ts @@ -1,12 +1,12 @@ import {StackNavigationOptions} from '@react-navigation/stack'; -const defaultScreenOptions = { +const defaultScreenOptions: StackNavigationOptions = { cardStyle: { overflow: 'visible', flex: 1, }, headerShown: false, animationTypeForReplace: 'push', -} as StackNavigationOptions; +}; export default defaultScreenOptions; diff --git a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts index 48dac2d13051..253006373a8e 100644 --- a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts +++ b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts @@ -5,13 +5,13 @@ import variables from '../../../styles/variables'; import getNavigationModalCardStyle from '../../../styles/getNavigationModalCardStyles'; import CONFIG from '../../../CONFIG'; -const commonScreenOptions = { +const commonScreenOptions: StackNavigationOptions = { headerShown: false, gestureDirection: 'horizontal', animationEnabled: true, cardOverlayEnabled: true, animationTypeForReplace: 'push', -} as StackNavigationOptions; +}; export default (isSmallScreenWidth: boolean) => ({ rightModalNavigator: { diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js index 09171503706c..f24270cfcd5c 100644 --- a/src/libs/Navigation/Navigation.js +++ b/src/libs/Navigation/Navigation.js @@ -159,7 +159,7 @@ function setParams(params, routeKey) { /** * Dismisses the last modal stack if there is any * - * @param {String | undefined} targetReportID - The reportID to navigate to after dismissing the modal + * @param {String | undefined} [targetReportID] - The reportID to navigate to after dismissing the modal */ function dismissModal(targetReportID) { if (!canNavigate('dismissModal')) { From ea9322136396092a53d6804858786c59924c40a3 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 13 Nov 2023 09:26:33 +0100 Subject: [PATCH 04/23] Resolve conflicts after merging main; partly fix TS issues --- src/ONYXKEYS.ts | 1 + src/SCREENS.ts | 19 +- .../Navigation/AppNavigator/AuthScreens.tsx | 106 ++++---- .../AppNavigator/ModalStackNavigators.js | 251 ------------------ .../AppNavigator/ModalStackNavigators.tsx | 55 ++-- ...igator.js => BaseCentralPaneNavigator.tsx} | 3 +- .../{index.native.js => index.native.tsx} | 0 .../{index.js => index.tsx} | 0 .../AppNavigator/Navigators/Overlay.tsx | 11 +- .../Navigators/RightModalNavigator.tsx | 9 +- .../Navigation/AppNavigator/PublicScreens.tsx | 2 +- .../AppNavigator/ReportScreenIDSetter.ts | 19 +- .../AppNavigator/ReportScreenWrapper.js | 45 ---- .../AppNavigator/ReportScreenWrapper.tsx | 13 +- .../CustomRouter.ts | 34 ++- .../createCustomStackNavigator/index.js | 91 ------- .../{index.native.js => index.native.tsx} | 40 +-- .../createCustomStackNavigator/index.tsx | 47 +++- src/libs/Navigation/AppNavigator/index.tsx | 4 +- src/libs/Navigation/AppNavigator/types.ts | 11 +- src/libs/actions/App.js | 2 +- .../getNavigationModalCardStyles/types.ts | 4 +- src/types/onyx/DemoInfo.ts | 7 + src/types/onyx/index.ts | 2 + 24 files changed, 219 insertions(+), 557 deletions(-) delete mode 100644 src/libs/Navigation/AppNavigator/ModalStackNavigators.js rename src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/{BaseCentralPaneNavigator.js => BaseCentralPaneNavigator.tsx} (88%) rename src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/{index.native.js => index.native.tsx} (100%) rename src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/{index.js => index.tsx} (100%) delete mode 100644 src/libs/Navigation/AppNavigator/ReportScreenWrapper.js delete mode 100644 src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js rename src/libs/Navigation/AppNavigator/createCustomStackNavigator/{index.native.js => index.native.tsx} (51%) create mode 100644 src/types/onyx/DemoInfo.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index a69bc985b550..8593b1b8cbaf 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -410,6 +410,7 @@ type OnyxValues = { [ONYXKEYS.MAPBOX_ACCESS_TOKEN]: OnyxTypes.MapboxAccessToken; [ONYXKEYS.ONYX_UPDATES_FROM_SERVER]: OnyxTypes.OnyxUpdatesFromServer; [ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT]: number; + [ONYXKEYS.DEMO_INFO]: OnyxTypes.DemoInfo; [ONYXKEYS.MAX_CANVAS_AREA]: number; [ONYXKEYS.MAX_CANVAS_HEIGHT]: number; [ONYXKEYS.MAX_CANVAS_WIDTH]: number; diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 6193020173b7..e3930aa81eda 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -40,6 +40,9 @@ export default { WALLET_TRANSFER_BALANCE: 'Settings_Wallet_Transfer_Balance', WALLET_CHOOSE_TRANSFER_ACCOUNT: 'Settings_Wallet_Choose_Transfer_Account', WALLET_ENABLE_PAYMENTS: 'Settings_Wallet_EnablePayments', + WALLET_CARD_ACTIVATE: 'Settings_Wallet_Card_Activate', + WALLET_REPORT_VIRTUAL_CARD_FRAUD: 'Settings_Wallet_ReportVirtualCardFraud', + WALLET_CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS: 'Settings_Wallet_Cards_Digital_Details_Update_Address', ADD_DEBIT_CARD: 'Settings_Add_Debit_Card', ADD_BANK_ACCOUNT: 'Settings_Add_Bank_Account', PREFERENCES_PRIORITY_MODE: 'Settings_Preferences_PriorityMode', @@ -47,6 +50,7 @@ export default { CLOSE: 'Settings_Close', STATUS_SET: 'Settings_Status_Set', TWO_FACTOR_AUTH: 'Settings_TwoFactorAuth', + REPORT_CARD_LOST_OR_DAMAGED: 'Settings_ReportCardLostOrDamaged', }, SAVE_THE_WORLD: { ROOT: 'SaveTheWorld_Root', @@ -73,6 +77,8 @@ export default { EDIT_REQUEST: 'EditRequest', SIGN_IN: 'SignIn', PRIVATE_NOTES: 'Private_Notes', + ROOM_MEMBERS: 'RoomMembers', + ROOM_INVITE: 'RoomInvite', }, SIGN_IN_WITH_APPLE_DESKTOP: 'AppleSignInDesktop', SIGN_IN_WITH_GOOGLE_DESKTOP: 'GoogleSignInDesktop', @@ -147,6 +153,7 @@ export default { MEMBERS: 'Workspace_Members', INVITE: 'Workspace_Invite', INVITE_MESSAGE: 'Workspace_Invite_Message', + CURRENCY: 'Workspace_Settings_Currency', }, EDIT_REQUEST: { @@ -163,17 +170,27 @@ export default { REIMBURSEMENT_ACCOUNT_ROOT: 'Reimbursement_Account_Root', WALLET_STATEMENT_ROOT: 'WalletStatement_Root', SIGN_IN_ROOT: 'SignIn_Root', - SPLIT_DETAILS_ROOT: 'SplitDetails_Root', + + SPLIT_DETAILS: { + ROOT: 'SplitDetails_Root', + EDIT_REQUEST: 'SplitDetails_Edit_Request', + EDIT_CURRENCY: 'SplitDetails_Edit_Currency', + }, + DETAILS_ROOT: 'Details_Root', PROFILE_ROOT: 'Profile_Root', REPORT_WELCOME_MESSAGE_ROOT: 'Report_WelcomeMessage_Root', REPORT_PARTICIPANTS_ROOT: 'ReportParticipants_Root', + ROOM_MEMBERS_ROOT: 'RoomMembers_Root', + ROOM_INVITE_ROOT: 'RoomInvite_Root', SEARCH_ROOT: 'Search_Root', NEW_CHAT_ROOT: 'NewChat_Root', FLAG_COMMENT_ROOT: 'FlagComment_Root', REIMBURSEMENT_ACCOUNT: 'ReimbursementAccount', GET_ASSISTANCE: 'GetAssistance', + KEYBOARD_SHORTCUTS: 'KeyboardShortcuts', + // Iframe screens from olddot HOME_OLDDOT: 'Home_OLDDOT', diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 33ddd77ed8c8..3017c2e8e884 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -1,9 +1,9 @@ import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; import React, {memo, useEffect, useRef} from 'react'; import {View} from 'react-native'; -import Onyx, {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import KeyCommand from 'react-native-key-command'; +import Onyx, {OnyxEntry, withOnyx} from 'react-native-onyx'; +import {ValueOf} from 'type-fest'; import useWindowDimensions from '@hooks/useWindowDimensions'; import KeyboardShortcut from '@libs/KeyboardShortcut'; import getCurrentUrl from '@libs/Navigation/currentUrl'; @@ -12,6 +12,7 @@ import NetworkConnection from '@libs/NetworkConnection'; import * as Pusher from '@libs/Pusher/pusher'; import PusherConnectionManager from '@libs/PusherConnectionManager'; import * as SessionUtils from '@libs/SessionUtils'; +import {AuthScreensStackParamList} from '@navigation/AppNavigator/types'; import DemoSetupPage from '@pages/DemoSetupPage'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import DesktopSignInRedirectPage from '@pages/signin/DesktopSignInRedirectPage'; @@ -30,27 +31,46 @@ import NAVIGATORS from '@src/NAVIGATORS'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; +import * as OnyxTypes from '@src/types/onyx'; +import type {Timezone} from '@src/types/onyx/PersonalDetails'; import createCustomStackNavigator from './createCustomStackNavigator'; import defaultScreenOptions from './defaultScreenOptions'; import getRootNavigatorScreenOptions from './getRootNavigatorScreenOptions'; import CentralPaneNavigator from './Navigators/CentralPaneNavigator'; import RightModalNavigator from './Navigators/RightModalNavigator'; -const loadReportAttachments = () => require('../../../pages/home/report/ReportAttachments').default; -const loadSidebarScreen = () => require('../../../pages/home/sidebar/SidebarScreen').default; -const loadValidateLoginPage = () => require('../../../pages/ValidateLoginPage').default; -const loadLogOutPreviousUserPage = () => require('../../../pages/LogOutPreviousUserPage').default; -const loadConciergePage = () => require('../../../pages/ConciergePage').default; +type AuthScreensProps = { + /** Session of currently logged in user */ + session: OnyxEntry; + + /** The report ID of the last opened public room as anonymous user */ + lastOpenedPublicRoomID: OnyxEntry; -let timezone; -let currentAccountID; -let isLoadingApp; + /** Opt-in experimental mode that prevents certain Onyx keys from persisting to disk */ + isUsingMemoryOnlyKeys: OnyxEntry; + + /** The last Onyx update ID was applied to the client */ + lastUpdateIDAppliedToClient: OnyxEntry; + + /** Information about any currently running demos */ + demoInfo: OnyxEntry; +}; + +const loadReportAttachments = () => require('../../../pages/home/report/ReportAttachments').default as React.ComponentType; +const loadSidebarScreen = () => require('../../../pages/home/sidebar/SidebarScreen').default as React.ComponentType; +const loadValidateLoginPage = () => require('../../../pages/ValidateLoginPage').default as React.ComponentType; +const loadLogOutPreviousUserPage = () => require('../../../pages/LogOutPreviousUserPage').default as React.ComponentType; +const loadConciergePage = () => require('../../../pages/ConciergePage').default as React.ComponentType; + +let timezone: Timezone | null; +let currentAccountID: number; +let isLoadingApp: boolean; Onyx.connect({ key: ONYXKEYS.SESSION, callback: (val) => { // When signed out, val hasn't accountID - if (!_.has(val, 'accountID')) { + if (!val?.accountID) { timezone = null; return; } @@ -71,12 +91,12 @@ Onyx.connect({ return; } - timezone = lodashGet(val, [currentAccountID, 'timezone'], {}); + timezone = val?.[currentAccountID]?.timezone ?? {}; const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone; // If the current timezone is different than the user's timezone, and their timezone is set to automatic // then update their timezone. - if (_.isObject(timezone) && timezone.automatic && timezone.selected !== currentTimezone) { + if (timezone?.automatic && timezone?.selected !== currentTimezone) { timezone.selected = currentTimezone; PersonalDetails.updateAutomaticTimezone({ automatic: true, @@ -89,11 +109,11 @@ Onyx.connect({ Onyx.connect({ key: ONYXKEYS.IS_LOADING_APP, callback: (val) => { - isLoadingApp = val; + isLoadingApp = !!val; }, }); -const RootStack = createCustomStackNavigator(); +const RootStack = createCustomStackNavigator(); // We want to delay the re-rendering for components(e.g. ReportActionCompose) // that depends on modal visibility until Modal is completely closed and its focused // When modal screen is focused, update modal visibility in Onyx @@ -108,40 +128,7 @@ const modalScreenListeners = { }, }; -const propTypes = { - /** Session of currently logged in user */ - session: PropTypes.shape({ - email: PropTypes.string.isRequired, - }), - - /** The report ID of the last opened public room as anonymous user */ - lastOpenedPublicRoomID: PropTypes.string, - - /** Opt-in experimental mode that prevents certain Onyx keys from persisting to disk */ - isUsingMemoryOnlyKeys: PropTypes.bool, - - /** The last Onyx update ID was applied to the client */ - lastUpdateIDAppliedToClient: PropTypes.number, - - /** Information about any currently running demos */ - demoInfo: PropTypes.shape({ - money2020: PropTypes.shape({ - isBeginningDemo: PropTypes.bool, - }), - }), -}; - -const defaultProps = { - isUsingMemoryOnlyKeys: false, - session: { - email: null, - }, - lastOpenedPublicRoomID: null, - lastUpdateIDAppliedToClient: null, - demoInfo: {}, -}; - -function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, session, lastOpenedPublicRoomID, demoInfo}) { +function AuthScreens({isUsingMemoryOnlyKeys = null, lastUpdateIDAppliedToClient = null, session = {email: undefined}, lastOpenedPublicRoomID = null, demoInfo = null}: AuthScreensProps) { const {isSmallScreenWidth} = useWindowDimensions(); const screenOptions = getRootNavigatorScreenOptions(isSmallScreenWidth); const isInitialRender = useRef(true); @@ -156,7 +143,7 @@ function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, sessio const searchShortcutConfig = CONST.KEYBOARD_SHORTCUTS.SEARCH; const chatShortcutConfig = CONST.KEYBOARD_SHORTCUTS.NEW_CHAT; const currentUrl = getCurrentUrl(); - const isLoggingInAsNewUser = SessionUtils.isLoggingInAsNewUser(currentUrl, session.email); + const isLoggingInAsNewUser = SessionUtils.isLoggingInAsNewUser(currentUrl, session?.email ?? ''); const shouldGetAllData = isUsingMemoryOnlyKeys || SessionUtils.didUserLogInDuringSession() || isLoggingInAsNewUser; // Sign out the current user if we're transitioning with a different user const isTransitioning = currentUrl.includes(ROUTES.TRANSITION_BETWEEN_APPS); @@ -193,6 +180,9 @@ function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, sessio App.reconnectApp(lastUpdateIDAppliedToClient); } + // TODO: remove when App is merged + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore App.setUpPoliciesAndNavigate(session); App.redirectThirdPartyDesktopSignIn(); @@ -221,7 +211,7 @@ function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, sessio }); }, shortcutsOverviewShortcutConfig.descriptionKey, - shortcutsOverviewShortcutConfig.modifiers, + shortcutsOverviewShortcutConfig.modifiers as unknown as string[], true, ); @@ -234,7 +224,7 @@ function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, sessio Modal.close(Session.checkIfActionIsAllowed(() => Navigation.navigate(ROUTES.SEARCH))); }, shortcutsOverviewShortcutConfig.descriptionKey, - shortcutsOverviewShortcutConfig.modifiers, + shortcutsOverviewShortcutConfig.modifiers as unknown as string[], true, ); @@ -244,7 +234,7 @@ function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, sessio Modal.close(Session.checkIfActionIsAllowed(() => Navigation.navigate(ROUTES.NEW))); }, chatShortcutConfig.descriptionKey, - chatShortcutConfig.modifiers, + chatShortcutConfig.modifiers as unknown as string[], true, ); @@ -263,12 +253,10 @@ function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, sessio true); -export default withOnyx({ +export default withOnyx({ session: { key: ONYXKEYS.SESSION, }, diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js deleted file mode 100644 index 2f0a75a02cc3..000000000000 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ /dev/null @@ -1,251 +0,0 @@ -import {CardStyleInterpolators, createStackNavigator} from '@react-navigation/stack'; -import React from 'react'; -import _ from 'underscore'; -import styles from '@styles/styles'; -import SCREENS from '@src/SCREENS'; - -const defaultSubRouteOptions = { - cardStyle: styles.navigationScreenCardStyle, - headerShown: false, - cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, -}; - -/** - * Create a modal stack navigator with an array of sub-screens. - * - * @param {Object} screens key/value pairs where the key is the name of the screen and the value is a functon that returns the lazy-loaded component - * @returns {Function} - */ -function createModalStackNavigator(screens) { - const ModalStackNavigator = createStackNavigator(); - - function ModalStack() { - return ( - - {_.map(screens, (getComponent, name) => ( - - ))} - - ); - } - - ModalStack.displayName = 'ModalStack'; - - return ModalStack; -} - -const MoneyRequestModalStackNavigator = createModalStackNavigator({ - Money_Request: () => require('../../../pages/iou/MoneyRequestSelectorPage').default, - Money_Request_Amount: () => require('../../../pages/iou/steps/NewRequestAmountPage').default, - Money_Request_Participants: () => require('../../../pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage').default, - Money_Request_Confirmation: () => require('../../../pages/iou/steps/MoneyRequestConfirmPage').default, - Money_Request_Currency: () => require('../../../pages/iou/IOUCurrencySelection').default, - Money_Request_Date: () => require('../../../pages/iou/MoneyRequestDatePage').default, - Money_Request_Description: () => require('../../../pages/iou/MoneyRequestDescriptionPage').default, - Money_Request_Category: () => require('../../../pages/iou/MoneyRequestCategoryPage').default, - Money_Request_Tag: () => require('../../../pages/iou/MoneyRequestTagPage').default, - Money_Request_Merchant: () => require('../../../pages/iou/MoneyRequestMerchantPage').default, - IOU_Send_Add_Bank_Account: () => require('../../../pages/AddPersonalBankAccountPage').default, - IOU_Send_Add_Debit_Card: () => require('../../../pages/settings/Wallet/AddDebitCardPage').default, - IOU_Send_Enable_Payments: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default, - Money_Request_Waypoint: () => require('../../../pages/iou/NewDistanceRequestWaypointEditorPage').default, - Money_Request_Edit_Waypoint: () => require('../../../pages/iou/MoneyRequestEditWaypointPage').default, - Money_Request_Distance: () => require('../../../pages/iou/NewDistanceRequestPage').default, - Money_Request_Receipt: () => require('../../../pages/EditRequestReceiptPage').default, -}); - -const SplitDetailsModalStackNavigator = createModalStackNavigator({ - SplitDetails_Root: () => require('../../../pages/iou/SplitBillDetailsPage').default, - SplitDetails_Edit_Request: () => require('../../../pages/EditSplitBillPage').default, - SplitDetails_Edit_Currency: () => require('../../../pages/iou/IOUCurrencySelection').default, -}); - -const DetailsModalStackNavigator = createModalStackNavigator({ - Details_Root: () => require('../../../pages/DetailsPage').default, -}); - -const ProfileModalStackNavigator = createModalStackNavigator({ - Profile_Root: () => require('../../../pages/ProfilePage').default, -}); - -const ReportDetailsModalStackNavigator = createModalStackNavigator({ - Report_Details_Root: () => require('../../../pages/ReportDetailsPage').default, - Report_Details_Share_Code: () => require('../../../pages/home/report/ReportDetailsShareCodePage').default, -}); - -const ReportSettingsModalStackNavigator = createModalStackNavigator({ - Report_Settings_Root: () => require('../../../pages/settings/Report/ReportSettingsPage').default, - Report_Settings_Room_Name: () => require('../../../pages/settings/Report/RoomNamePage').default, - Report_Settings_Notification_Preferences: () => require('../../../pages/settings/Report/NotificationPreferencePage').default, - Report_Settings_Write_Capability: () => require('../../../pages/settings/Report/WriteCapabilityPage').default, -}); - -const TaskModalStackNavigator = createModalStackNavigator({ - Task_Title: () => require('../../../pages/tasks/TaskTitlePage').default, - Task_Description: () => require('../../../pages/tasks/TaskDescriptionPage').default, - Task_Assignee: () => require('../../../pages/tasks/TaskAssigneeSelectorModal').default, -}); - -const ReportWelcomeMessageModalStackNavigator = createModalStackNavigator({ - Report_WelcomeMessage_Root: () => require('../../../pages/ReportWelcomeMessagePage').default, -}); - -const ReportParticipantsModalStackNavigator = createModalStackNavigator({ - ReportParticipants_Root: () => require('../../../pages/ReportParticipantsPage').default, -}); - -const RoomMembersModalStackNavigator = createModalStackNavigator({ - RoomMembers_Root: () => require('../../../pages/RoomMembersPage').default, -}); - -const RoomInviteModalStackNavigator = createModalStackNavigator({ - RoomInvite_Root: () => require('../../../pages/RoomInvitePage').default, -}); - -const SearchModalStackNavigator = createModalStackNavigator({ - Search_Root: () => require('../../../pages/SearchPage').default, -}); - -const NewChatModalStackNavigator = createModalStackNavigator({ - NewChat_Root: () => require('../../../pages/NewChatSelectorPage').default, -}); - -const NewTaskModalStackNavigator = createModalStackNavigator({ - NewTask_Root: () => require('../../../pages/tasks/NewTaskPage').default, - NewTask_TaskAssigneeSelector: () => require('../../../pages/tasks/TaskAssigneeSelectorModal').default, - NewTask_TaskShareDestinationSelector: () => require('../../../pages/tasks/TaskShareDestinationSelectorModal').default, - NewTask_Details: () => require('../../../pages/tasks/NewTaskDetailsPage').default, - NewTask_Title: () => require('../../../pages/tasks/NewTaskTitlePage').default, - NewTask_Description: () => require('../../../pages/tasks/NewTaskDescriptionPage').default, -}); - -const NewTeachersUniteNavigator = createModalStackNavigator({ - [SCREENS.SAVE_THE_WORLD.ROOT]: () => require('../../../pages/TeachersUnite/SaveTheWorldPage').default, - I_Know_A_Teacher: () => require('../../../pages/TeachersUnite/KnowATeacherPage').default, - Intro_School_Principal: () => require('../../../pages/TeachersUnite/ImTeacherPage').default, - I_Am_A_Teacher: () => require('../../../pages/TeachersUnite/ImTeacherPage').default, -}); - -const SettingsModalStackNavigator = createModalStackNavigator({ - [SCREENS.SETTINGS.ROOT]: () => require('../../../pages/settings/InitialSettingsPage').default, - Settings_Share_Code: () => require('../../../pages/ShareCodePage').default, - [SCREENS.SETTINGS.WORKSPACES]: () => require('../../../pages/workspace/WorkspacesListPage').default, - Settings_Profile: () => require('../../../pages/settings/Profile/ProfilePage').default, - Settings_Pronouns: () => require('../../../pages/settings/Profile/PronounsPage').default, - Settings_Display_Name: () => require('../../../pages/settings/Profile/DisplayNamePage').default, - Settings_Timezone: () => require('../../../pages/settings/Profile/TimezoneInitialPage').default, - Settings_Timezone_Select: () => require('../../../pages/settings/Profile/TimezoneSelectPage').default, - Settings_PersonalDetails_Initial: () => require('../../../pages/settings/Profile/PersonalDetails/PersonalDetailsInitialPage').default, - Settings_PersonalDetails_LegalName: () => require('../../../pages/settings/Profile/PersonalDetails/LegalNamePage').default, - Settings_PersonalDetails_DateOfBirth: () => require('../../../pages/settings/Profile/PersonalDetails/DateOfBirthPage').default, - Settings_PersonalDetails_Address: () => require('../../../pages/settings/Profile/PersonalDetails/AddressPage').default, - Settings_PersonalDetails_Address_Country: () => require('../../../pages/settings/Profile/PersonalDetails/CountrySelectionPage').default, - Settings_ContactMethods: () => require('../../../pages/settings/Profile/Contacts/ContactMethodsPage').default, - Settings_ContactMethodDetails: () => require('../../../pages/settings/Profile/Contacts/ContactMethodDetailsPage').default, - Settings_NewContactMethod: () => require('../../../pages/settings/Profile/Contacts/NewContactMethodPage').default, - [SCREENS.SETTINGS.PREFERENCES]: () => require('../../../pages/settings/Preferences/PreferencesPage').default, - Settings_Preferences_PriorityMode: () => require('../../../pages/settings/Preferences/PriorityModePage').default, - Settings_Preferences_Language: () => require('../../../pages/settings/Preferences/LanguagePage').default, - // Will be uncommented as part of https://github.com/Expensify/App/issues/21670 - // Settings_Preferences_Theme: () => require('../../../pages/settings/Preferences/ThemePage').default, - Settings_Close: () => require('../../../pages/settings/Security/CloseAccountPage').default, - [SCREENS.SETTINGS.SECURITY]: () => require('../../../pages/settings/Security/SecuritySettingsPage').default, - Settings_About: () => require('../../../pages/settings/AboutPage/AboutPage').default, - Settings_App_Download_Links: () => require('../../../pages/settings/AppDownloadLinks').default, - Settings_Lounge_Access: () => require('../../../pages/settings/Profile/LoungeAccessPage').default, - Settings_Wallet: () => require('../../../pages/settings/Wallet/WalletPage').default, - Settings_Wallet_Cards_Digital_Details_Update_Address: () => require('../../../pages/settings/Profile/PersonalDetails/AddressPage').default, - Settings_Wallet_DomainCards: () => require('../../../pages/settings/Wallet/ExpensifyCardPage').default, - Settings_Wallet_ReportVirtualCardFraud: () => require('../../../pages/settings/Wallet/ReportVirtualCardFraudPage').default, - Settings_Wallet_Card_Activate: () => require('../../../pages/settings/Wallet/ActivatePhysicalCardPage').default, - Settings_Wallet_Transfer_Balance: () => require('../../../pages/settings/Wallet/TransferBalancePage').default, - Settings_Wallet_Choose_Transfer_Account: () => require('../../../pages/settings/Wallet/ChooseTransferAccountPage').default, - Settings_Wallet_EnablePayments: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default, - Settings_Add_Debit_Card: () => require('../../../pages/settings/Wallet/AddDebitCardPage').default, - Settings_Add_Bank_Account: () => require('../../../pages/AddPersonalBankAccountPage').default, - [SCREENS.SETTINGS.STATUS]: () => require('../../../pages/settings/Profile/CustomStatus/StatusPage').default, - Settings_Status_Set: () => require('../../../pages/settings/Profile/CustomStatus/StatusSetPage').default, - Workspace_Initial: () => require('../../../pages/workspace/WorkspaceInitialPage').default, - Workspace_Settings: () => require('../../../pages/workspace/WorkspaceSettingsPage').default, - Workspace_Settings_Currency: () => require('../../../pages/workspace/WorkspaceSettingsCurrencyPage').default, - Workspace_Card: () => require('../../../pages/workspace/card/WorkspaceCardPage').default, - Workspace_Reimburse: () => require('../../../pages/workspace/reimburse/WorkspaceReimbursePage').default, - Workspace_RateAndUnit: () => require('../../../pages/workspace/reimburse/WorkspaceRateAndUnitPage').default, - Workspace_Bills: () => require('../../../pages/workspace/bills/WorkspaceBillsPage').default, - Workspace_Invoices: () => require('../../../pages/workspace/invoices/WorkspaceInvoicesPage').default, - Workspace_Travel: () => require('../../../pages/workspace/travel/WorkspaceTravelPage').default, - Workspace_Members: () => require('../../../pages/workspace/WorkspaceMembersPage').default, - Workspace_Invite: () => require('../../../pages/workspace/WorkspaceInvitePage').default, - Workspace_Invite_Message: () => require('../../../pages/workspace/WorkspaceInviteMessagePage').default, - ReimbursementAccount: () => require('../../../pages/ReimbursementAccount/ReimbursementAccountPage').default, - GetAssistance: () => require('../../../pages/GetAssistancePage').default, - Settings_TwoFactorAuth: () => require('../../../pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage').default, - Settings_ReportCardLostOrDamaged: () => require('../../../pages/settings/Wallet/ReportCardLostPage').default, - KeyboardShortcuts: () => require('../../../pages/KeyboardShortcutsPage').default, -}); - -const EnablePaymentsStackNavigator = createModalStackNavigator({ - EnablePayments_Root: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default, -}); - -const AddPersonalBankAccountModalStackNavigator = createModalStackNavigator({ - AddPersonalBankAccount_Root: () => require('../../../pages/AddPersonalBankAccountPage').default, -}); - -const ReimbursementAccountModalStackNavigator = createModalStackNavigator({ - ReimbursementAccount_Root: () => require('../../../pages/ReimbursementAccount/ReimbursementAccountPage').default, -}); - -const WalletStatementStackNavigator = createModalStackNavigator({ - WalletStatement_Root: () => require('../../../pages/wallet/WalletStatementPage').default, -}); - -const FlagCommentStackNavigator = createModalStackNavigator({ - FlagComment_Root: () => require('../../../pages/FlagCommentPage').default, -}); - -const EditRequestStackNavigator = createModalStackNavigator({ - EditRequest_Root: () => require('../../../pages/EditRequestPage').default, - EditRequest_Currency: () => require('../../../pages/iou/IOUCurrencySelection').default, -}); - -const PrivateNotesModalStackNavigator = createModalStackNavigator({ - PrivateNotes_View: () => require('../../../pages/PrivateNotes/PrivateNotesViewPage').default, - PrivateNotes_List: () => require('../../../pages/PrivateNotes/PrivateNotesListPage').default, - PrivateNotes_Edit: () => require('../../../pages/PrivateNotes/PrivateNotesEditPage').default, -}); - -const SignInModalStackNavigator = createModalStackNavigator({ - SignIn_Root: () => require('../../../pages/signin/SignInModal').default, -}); - -export { - MoneyRequestModalStackNavigator, - SplitDetailsModalStackNavigator, - DetailsModalStackNavigator, - ProfileModalStackNavigator, - ReportDetailsModalStackNavigator, - TaskModalStackNavigator, - ReportSettingsModalStackNavigator, - ReportWelcomeMessageModalStackNavigator, - ReportParticipantsModalStackNavigator, - SearchModalStackNavigator, - NewChatModalStackNavigator, - NewTaskModalStackNavigator, - SettingsModalStackNavigator, - EnablePaymentsStackNavigator, - AddPersonalBankAccountModalStackNavigator, - ReimbursementAccountModalStackNavigator, - WalletStatementStackNavigator, - FlagCommentStackNavigator, - EditRequestStackNavigator, - PrivateNotesModalStackNavigator, - NewTeachersUniteNavigator, - SignInModalStackNavigator, - RoomMembersModalStackNavigator, - RoomInviteModalStackNavigator, -}; diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index 9e8cf9680e73..15fd1dbf1516 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -1,7 +1,7 @@ +import {CardStyleInterpolators, createStackNavigator} from '@react-navigation/stack'; import React from 'react'; -import {createStackNavigator, CardStyleInterpolators} from '@react-navigation/stack'; -import styles from '../../../styles/styles'; -import SCREENS from '../../../SCREENS'; +import styles from '@styles/styles'; +import SCREENS from '@src/SCREENS'; const defaultSubRouteOptions = { cardStyle: styles.navigationScreenCardStyle, @@ -18,17 +18,24 @@ type Screens = Record React.ComponentType>; */ function createModalStackNavigator(screens: Screens): () => React.JSX.Element { const ModalStackNavigator = createStackNavigator(); - return () => ( - - {Object.keys(screens).map((name) => ( - - ))} - - ); + + function ModalStack() { + return ( + + {Object.keys(screens).map((name) => ( + + ))} + + ); + } + + ModalStack.displayName = 'ModalStack'; + + return ModalStack; } const MoneyRequestModalStackNavigator = createModalStackNavigator({ @@ -52,7 +59,9 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator({ }); const SplitDetailsModalStackNavigator = createModalStackNavigator({ - [SCREENS.SPLIT_DETAILS_ROOT]: () => require('../../../pages/iou/SplitBillDetailsPage').default as React.ComponentType, + [SCREENS.SPLIT_DETAILS.ROOT]: () => require('../../../pages/iou/SplitBillDetailsPage').default as React.ComponentType, + [SCREENS.SPLIT_DETAILS.EDIT_REQUEST]: () => require('../../../pages/EditSplitBillPage').default as React.ComponentType, + [SCREENS.SPLIT_DETAILS.EDIT_CURRENCY]: () => require('../../../pages/iou/IOUCurrencySelection').default as React.ComponentType, }); const DetailsModalStackNavigator = createModalStackNavigator({ @@ -89,6 +98,14 @@ const ReportParticipantsModalStackNavigator = createModalStackNavigator({ [SCREENS.REPORT_PARTICIPANTS_ROOT]: () => require('../../../pages/ReportParticipantsPage').default as React.ComponentType, }); +const RoomMembersModalStackNavigator = createModalStackNavigator({ + [SCREENS.ROOM_MEMBERS_ROOT]: () => require('../../../pages/RoomMembersPage').default as React.ComponentType, +}); + +const RoomInviteModalStackNavigator = createModalStackNavigator({ + [SCREENS.ROOM_INVITE_ROOT]: () => require('../../../pages/RoomInvitePage').default as React.ComponentType, +}); + const SearchModalStackNavigator = createModalStackNavigator({ [SCREENS.SEARCH_ROOT]: () => require('../../../pages/SearchPage').default as React.ComponentType, }); @@ -141,7 +158,10 @@ const SettingsModalStackNavigator = createModalStackNavigator({ [SCREENS.SETTINGS.APP_DOWNLOAD_LINKS]: () => require('../../../pages/settings/AppDownloadLinks').default as React.ComponentType, [SCREENS.SETTINGS.LOUNGE_ACCESS]: () => require('../../../pages/settings/Profile/LoungeAccessPage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET]: () => require('../../../pages/settings/Wallet/WalletPage').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS]: () => require('../../../pages/settings/Profile/PersonalDetails/AddressPage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET_DOMAIN_CARDS]: () => require('../../../pages/settings/Wallet/ExpensifyCardPage').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_REPORT_VIRTUAL_CARD_FRAUD]: () => require('../../../pages/settings/Wallet/ReportVirtualCardFraudPage').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_CARD_ACTIVATE]: () => require('../../../pages/settings/Wallet/ActivatePhysicalCardPage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET_TRANSFER_BALANCE]: () => require('../../../pages/settings/Wallet/TransferBalancePage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET_CHOOSE_TRANSFER_ACCOUNT]: () => require('../../../pages/settings/Wallet/ChooseTransferAccountPage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET_ENABLE_PAYMENTS]: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default as React.ComponentType, @@ -151,6 +171,7 @@ const SettingsModalStackNavigator = createModalStackNavigator({ [SCREENS.SETTINGS.STATUS_SET]: () => require('../../../pages/settings/Profile/CustomStatus/StatusSetPage').default as React.ComponentType, [SCREENS.WORKSPACE.INITIAL]: () => require('../../../pages/workspace/WorkspaceInitialPage').default as React.ComponentType, [SCREENS.WORKSPACE.SETTINGS]: () => require('../../../pages/workspace/WorkspaceSettingsPage').default as React.ComponentType, + [SCREENS.WORKSPACE.CURRENCY]: () => require('../../../pages/workspace/WorkspaceSettingsCurrencyPage').default as React.ComponentType, [SCREENS.WORKSPACE.CARD]: () => require('../../../pages/workspace/card/WorkspaceCardPage').default as React.ComponentType, [SCREENS.WORKSPACE.REIMBURSE]: () => require('../../../pages/workspace/reimburse/WorkspaceReimbursePage').default as React.ComponentType, [SCREENS.WORKSPACE.RATE_AND_UNIT]: () => require('../../../pages/workspace/reimburse/WorkspaceRateAndUnitPage').default as React.ComponentType, @@ -163,6 +184,8 @@ const SettingsModalStackNavigator = createModalStackNavigator({ [SCREENS.REIMBURSEMENT_ACCOUNT]: () => require('../../../pages/ReimbursementAccount/ReimbursementAccountPage').default as React.ComponentType, [SCREENS.GET_ASSISTANCE]: () => require('../../../pages/GetAssistancePage').default as React.ComponentType, [SCREENS.SETTINGS.TWO_FACTOR_AUTH]: () => require('../../../pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage').default as React.ComponentType, + [SCREENS.SETTINGS.REPORT_CARD_LOST_OR_DAMAGED]: () => require('../../../pages/settings/Wallet/ReportCardLostPage').default as React.ComponentType, + [SCREENS.KEYBOARD_SHORTCUTS]: () => require('../../../pages/KeyboardShortcutsPage').default as React.ComponentType, }); const EnablePaymentsStackNavigator = createModalStackNavigator({ @@ -223,4 +246,6 @@ export { PrivateNotesModalStackNavigator, NewTeachersUniteNavigator, SignInModalStackNavigator, + RoomMembersModalStackNavigator, + RoomInviteModalStackNavigator, }; diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.tsx similarity index 88% rename from src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.js rename to src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.tsx index a1646011e560..73785e643036 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/BaseCentralPaneNavigator.tsx @@ -1,11 +1,12 @@ import {createStackNavigator} from '@react-navigation/stack'; import React from 'react'; import ReportScreenWrapper from '@libs/Navigation/AppNavigator/ReportScreenWrapper'; +import type {CentralPaneStackParamList} from '@libs/Navigation/AppNavigator/types'; import getCurrentUrl from '@libs/Navigation/currentUrl'; import styles from '@styles/styles'; import SCREENS from '@src/SCREENS'; -const Stack = createStackNavigator(); +const Stack = createStackNavigator(); const url = getCurrentUrl(); const openOnAdminRoom = url ? new URL(url).searchParams.get('openOnAdminRoom') : undefined; diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.native.js b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.native.tsx similarity index 100% rename from src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.native.js rename to src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.native.tsx diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.js b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.tsx similarity index 100% rename from src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.js rename to src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator/index.tsx diff --git a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx index 266e86d210d7..e65c20ce8141 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx @@ -10,7 +10,7 @@ type OverlayProps = { onPress: () => void; }; -function Overlay(props: OverlayProps) { +function Overlay({onPress}: OverlayProps) { const {current} = useCardAnimation(); // TODO: remove type assertion when useLocalize is migrated const {translate} = useLocalize() as unknown as {translate: (phrase: string) => string}; @@ -23,19 +23,14 @@ function Overlay(props: OverlayProps) { we have 30px draggable ba at the top and the rest of the dimmed area is clickable. On other devices, everything behaves normally like one big pressable */} (); function RightModalNavigator(props: StackScreenProps) { - // TODO: remove type assertion when useWindowDimensions is migrated to TS - const {isSmallScreenWidth} = useWindowDimensions() as WindowDimensions; + const {isSmallScreenWidth} = useWindowDimensions(); return ( diff --git a/src/libs/Navigation/AppNavigator/PublicScreens.tsx b/src/libs/Navigation/AppNavigator/PublicScreens.tsx index 2a22d7d5dec5..d4e4726e7c42 100644 --- a/src/libs/Navigation/AppNavigator/PublicScreens.tsx +++ b/src/libs/Navigation/AppNavigator/PublicScreens.tsx @@ -47,7 +47,7 @@ function PublicScreens() { component={GoogleSignInDesktopPage} /> diff --git a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts index a67d8110040c..40bb2707ea01 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts +++ b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts @@ -3,11 +3,10 @@ import {OnyxCollection, OnyxEntry, withOnyx} from 'react-native-onyx'; import usePermissions from '@hooks/usePermissions'; import Navigation from '@libs/Navigation/Navigation'; import * as ReportUtils from '@libs/ReportUtils'; -import reportPropTypes from '@pages/reportPropTypes'; import * as App from '@userActions/App'; import ONYXKEYS from '@src/ONYXKEYS'; -import {Policy, Report} from '../../../types/onyx'; -import {ReportScreenWrapperProps} from './types'; +import type {Policy, Report} from '@src/types/onyx'; +import type {ReportScreenWrapperProps} from './types'; type ReportScreenIDSetterComponentProps = { /** Available reports that would be displayed in this navigator */ @@ -16,6 +15,7 @@ type ReportScreenIDSetterComponentProps = { /** The policies which the user has access to */ policies: OnyxCollection; + /** Whether user is a new user */ isFirstTimeNewExpensifyUser: OnyxEntry; }; @@ -33,7 +33,8 @@ const getLastAccessedReportID = ( ): number | string => { // If deeplink url contains reportID params, we should show the report that has this reportID. const currentRoute = Navigation.getActiveRoute(); - const {reportID} = ReportUtils.parseReportRouteParams(currentRoute); + // TODO: get rid of assertion when ReportUtils is migrated to TS + const {reportID} = ReportUtils.parseReportRouteParams(currentRoute) as {reportID: string}; if (reportID) { return reportID; } @@ -47,8 +48,7 @@ const getLastAccessedReportID = ( // This wrapper is reponsible for opening the last accessed report if there is no reportID specified in the route params function ReportScreenIDSetter({route, reports, policies, isFirstTimeNewExpensifyUser, navigation}: ReportScreenIDSetterProps): null { - // TODO: remove type assertion when usePermissions is migrated - const {canUseDefaultRooms} = usePermissions() as {canUseDefaultRooms: boolean}; + const {canUseDefaultRooms} = usePermissions(); useEffect(() => { // Don't update if there is a reportID in the params already @@ -79,21 +79,14 @@ ReportScreenIDSetter.displayName = 'ReportScreenIDSetter'; export default withOnyx({ reports: { key: ONYXKEYS.COLLECTION.REPORT, - // TODO: I think we need to update onyx mapping types to include allowStaleData/initialValue keys - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore allowStaleData: true, }, policies: { key: ONYXKEYS.COLLECTION.POLICY, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore allowStaleData: true, }, isFirstTimeNewExpensifyUser: { key: ONYXKEYS.NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore initialValue: false, }, })(ReportScreenIDSetter); diff --git a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.js b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.js deleted file mode 100644 index 87a8a4abc687..000000000000 --- a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.js +++ /dev/null @@ -1,45 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import ReportScreen from '@pages/home/ReportScreen'; -import ReportScreenIDSetter from './ReportScreenIDSetter'; - -const propTypes = { - /** Navigation route context info provided by react navigation */ - route: PropTypes.shape({ - /** Route specific parameters used on this screen */ - params: PropTypes.shape({ - /** If the admin room should be opened */ - openOnAdminRoom: PropTypes.bool, - - /** The ID of the report this screen should display */ - reportID: PropTypes.string, - }), - }).isRequired, - - /* Navigation functions provided by React Navigation */ - navigation: PropTypes.shape({ - setParams: PropTypes.func.isRequired, - }).isRequired, -}; - -const defaultProps = {}; - -function ReportScreenWrapper(props) { - // The ReportScreen without the reportID set will display a skeleton - // until the reportID is loaded and set in the route param - return ( - <> - - - - ); -} - -ReportScreenWrapper.propTypes = propTypes; -ReportScreenWrapper.defaultProps = defaultProps; -ReportScreenWrapper.displayName = 'ReportScreenWrapper'; - -export default ReportScreenWrapper; diff --git a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx index 2c17bf4b2ed0..fda939a0e15d 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx +++ b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx @@ -1,20 +1,17 @@ import React from 'react'; -import ReportScreen from '../../../pages/home/ReportScreen'; +import ReportScreen from '@pages/home/ReportScreen'; import ReportScreenIDSetter from './ReportScreenIDSetter'; import {ReportScreenWrapperProps} from './types'; -function ReportScreenWrapper(props: ReportScreenWrapperProps) { +function ReportScreenWrapper({route, navigation}: ReportScreenWrapperProps) { // The ReportScreen without the reportID set will display a skeleton // until the reportID is loaded and set in the route param return ( <> - {/* TODO: Remove when ReportScreen is migrated */} - {/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */} - {/* @ts-ignore */} - + ); diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts index dc80948a2dfa..ce120e0409e1 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts @@ -1,6 +1,7 @@ -import {StackRouter, RouterConfigOptions, ParamListBase, StackNavigationState, PartialState} from '@react-navigation/native'; -import NAVIGATORS from '../../../../NAVIGATORS'; -import {ResponsiveStackNavigatorRouterOptions} from '../types'; +import {ParamListBase, PartialState, RouterConfigOptions, StackNavigationState, StackRouter} from '@react-navigation/native'; +import {ResponsiveStackNavigatorRouterOptions} from '@libs/Navigation/AppNavigator/types'; +import NAVIGATORS from '@src/NAVIGATORS'; +import SCREENS from '@src/SCREENS'; type MutableState = { index: number; @@ -12,26 +13,39 @@ type State = Omit>, 'stale'> & const isAtLeastOneCentralPaneNavigatorInState = (state: State): boolean => !!state.routes.find((r) => r.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR); /** - * @param {Object} state - react-navigation state - * @returns {String} + * @param state - react-navigation state + * @returns */ -const getTopMostReportIDFromRHP = (state) => { +const getTopMostReportIDFromRHP = (state: State): string => { if (!state) { return ''; } - const topmostRightPane = lodashFindLast(state.routes, (route) => route.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR); + const topmostRightPane = [...state.routes].reverse().find((route) => route.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR); if (topmostRightPane) { + // TODO: fix TS issue + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore return getTopMostReportIDFromRHP(topmostRightPane.state); } - const topmostRoute = lodashFindLast(state.routes); + const topmostRoute = state.routes[state.routes.length - 1]; if (topmostRoute.state) { + // TODO: fix TS issue + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore return getTopMostReportIDFromRHP(topmostRoute.state); } - if (topmostRoute.params && topmostRoute.params.reportID) { + // TODO: fix TS issue + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + if (topmostRoute.params?.reportID) { + // TODO: fix TS issue + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-unsafe-return return topmostRoute.params.reportID; } @@ -41,7 +55,7 @@ const getTopMostReportIDFromRHP = (state) => { * Adds report route without any specific reportID to the state. * The report screen will self set proper reportID param based on the helper function findLastAccessedReport (look at ReportScreenWrapper for more info) */ -const addCentralPaneNavigatorRoute = (state) => { +const addCentralPaneNavigatorRoute = (state: State) => { const reportID = getTopMostReportIDFromRHP(state); const centralPaneNavigatorRoute = { name: NAVIGATORS.CENTRAL_PANE_NAVIGATOR, diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js deleted file mode 100644 index 8924b01e2acb..000000000000 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js +++ /dev/null @@ -1,91 +0,0 @@ -import {createNavigatorFactory, useNavigationBuilder} from '@react-navigation/native'; -import {StackView} from '@react-navigation/stack'; -import PropTypes from 'prop-types'; -import React, {useMemo, useRef} from 'react'; -import useWindowDimensions from '@hooks/useWindowDimensions'; -import NAVIGATORS from '@src/NAVIGATORS'; -import CustomRouter from './CustomRouter'; - -const propTypes = { - /* Determines if the navigator should render the StackView (narrow) or ThreePaneView (wide) */ - isSmallScreenWidth: PropTypes.bool.isRequired, - - /* Children for the useNavigationBuilder hook */ - children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired, - - /* initialRouteName for this navigator */ - initialRouteName: PropTypes.oneOf([PropTypes.string, PropTypes.undefined]), - - /* Screen options defined for this navigator */ - // eslint-disable-next-line react/forbid-prop-types - screenOptions: PropTypes.object, -}; - -const defaultProps = { - initialRouteName: undefined, - screenOptions: undefined, -}; - -function reduceReportRoutes(routes) { - const result = []; - let count = 0; - const reverseRoutes = [...routes].reverse(); - - reverseRoutes.forEach((route) => { - if (route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR) { - // Remove all report routes except the last 3. This will improve performance. - if (count < 3) { - result.push(route); - count++; - } - } else { - result.push(route); - } - }); - - return result.reverse(); -} - -function ResponsiveStackNavigator(props) { - const {isSmallScreenWidth} = useWindowDimensions(); - - const isSmallScreenWidthRef = useRef(isSmallScreenWidth); - - isSmallScreenWidthRef.current = isSmallScreenWidth; - - const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder(CustomRouter, { - children: props.children, - screenOptions: props.screenOptions, - initialRouteName: props.initialRouteName, - // Options for useNavigationBuilder won't update on prop change, so we need to pass a getter for the router to have the current state of isSmallScreenWidth. - getIsSmallScreenWidth: () => isSmallScreenWidthRef.current, - }); - - const stateToRender = useMemo(() => { - const result = reduceReportRoutes(state.routes); - - return { - ...state, - index: result.length - 1, - routes: [...result], - }; - }, [state]); - - return ( - - - - ); -} - -ResponsiveStackNavigator.defaultProps = defaultProps; -ResponsiveStackNavigator.propTypes = propTypes; -ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator'; - -export default createNavigatorFactory(ResponsiveStackNavigator); diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx similarity index 51% rename from src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.js rename to src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx index ae36f4aff9ad..25675effabca 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx @@ -1,38 +1,24 @@ -import {createNavigatorFactory, useNavigationBuilder} from '@react-navigation/native'; -import {StackView} from '@react-navigation/stack'; -import PropTypes from 'prop-types'; +import {createNavigatorFactory, ParamListBase, StackActionHelpers, StackNavigationState, useNavigationBuilder} from '@react-navigation/native'; +import {StackNavigationEventMap, StackNavigationOptions, StackView} from '@react-navigation/stack'; import React, {useRef} from 'react'; import useWindowDimensions from '@hooks/useWindowDimensions'; +import {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from '@navigation/AppNavigator/types'; import CustomRouter from './CustomRouter'; -const propTypes = { - /* Determines if the navigator should render the StackView (narrow) or ThreePaneView (wide) */ - isSmallScreenWidth: PropTypes.bool.isRequired, - - /* Children for the useNavigationBuilder hook */ - children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired, - - /* initialRouteName for this navigator */ - initialRouteName: PropTypes.oneOf([PropTypes.string, PropTypes.undefined]), - - /* Screen options defined for this navigator */ - // eslint-disable-next-line react/forbid-prop-types - screenOptions: PropTypes.object, -}; - -const defaultProps = { - initialRouteName: undefined, - screenOptions: undefined, -}; - -function ResponsiveStackNavigator(props) { +function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) { const {isSmallScreenWidth} = useWindowDimensions(); const isSmallScreenWidthRef = useRef(isSmallScreenWidth); isSmallScreenWidthRef.current = isSmallScreenWidth; - const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder(CustomRouter, { + const {navigation, state, descriptors, NavigationContent} = useNavigationBuilder< + StackNavigationState, + ResponsiveStackNavigatorRouterOptions, + StackActionHelpers, + StackNavigationOptions, + StackNavigationEventMap + >(CustomRouter, { children: props.children, screenOptions: props.screenOptions, initialRouteName: props.initialRouteName, @@ -53,8 +39,6 @@ function ResponsiveStackNavigator(props) { ); } -ResponsiveStackNavigator.defaultProps = defaultProps; -ResponsiveStackNavigator.propTypes = propTypes; ResponsiveStackNavigator.displayName = 'ResponsiveStackNavigator'; -export default createNavigatorFactory(ResponsiveStackNavigator); +export default createNavigatorFactory, StackNavigationOptions, StackNavigationEventMap, typeof ResponsiveStackNavigator>(ResponsiveStackNavigator); diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx index a97bb3de9611..3d3bd6d8d447 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx @@ -1,14 +1,35 @@ -import React, {useRef} from 'react'; -import {useNavigationBuilder, createNavigatorFactory, ParamListBase, StackActionHelpers, StackNavigationState} from '@react-navigation/native'; +import {createNavigatorFactory, ParamListBase, StackActionHelpers, StackNavigationState, useNavigationBuilder} from '@react-navigation/native'; import {StackNavigationEventMap, StackNavigationOptions, StackView} from '@react-navigation/stack'; +import React, {useMemo, useRef} from 'react'; +import useWindowDimensions from '@hooks/useWindowDimensions'; +import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from '@libs/Navigation/AppNavigator/types'; +import NAVIGATORS from '@src/NAVIGATORS'; import CustomRouter from './CustomRouter'; -import useWindowDimensions from '../../../../hooks/useWindowDimensions'; -import {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from '../types'; -import type {WindowDimensions} from '../../../../styles/getModalStyles'; + +type Routes = StackNavigationState['routes']; + +function reduceReportRoutes(routes: Routes): Routes { + const result: Routes = []; + let count = 0; + const reverseRoutes = [...routes].reverse(); + + reverseRoutes.forEach((route) => { + if (route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR) { + // Remove all report routes except the last 3. This will improve performance. + if (count < 3) { + result.push(route); + count++; + } + } else { + result.push(route); + } + }); + + return result.reverse(); +} function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) { - // TODO: remove type assertion when useWindowDimensions is migrated to TS - const {isSmallScreenWidth} = useWindowDimensions() as WindowDimensions; + const {isSmallScreenWidth} = useWindowDimensions(); const isSmallScreenWidthRef = useRef(isSmallScreenWidth); @@ -28,12 +49,22 @@ function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) { getIsSmallScreenWidth: () => isSmallScreenWidthRef.current, }); + const stateToRender = useMemo(() => { + const result = reduceReportRoutes(state.routes); + + return { + ...state, + index: result.length - 1, + routes: [...result], + }; + }, [state]); + return ( diff --git a/src/libs/Navigation/AppNavigator/index.tsx b/src/libs/Navigation/AppNavigator/index.tsx index d2cf587b8fa8..8d65f5166060 100644 --- a/src/libs/Navigation/AppNavigator/index.tsx +++ b/src/libs/Navigation/AppNavigator/index.tsx @@ -5,8 +5,8 @@ type AppNavigatorProps = { authenticated: boolean; }; -function AppNavigator(props: AppNavigatorProps) { - if (props.authenticated) { +function AppNavigator({authenticated}: AppNavigatorProps) { + if (authenticated) { const AuthScreens = require('./AuthScreens').default; // These are the protected screens and only accessible when an authToken is present diff --git a/src/libs/Navigation/AppNavigator/types.ts b/src/libs/Navigation/AppNavigator/types.ts index 67286a6cbd85..fa5ac3702597 100644 --- a/src/libs/Navigation/AppNavigator/types.ts +++ b/src/libs/Navigation/AppNavigator/types.ts @@ -1,10 +1,9 @@ -import {StackScreenProps, StackNavigationOptions, StackNavigationEventMap} from '@react-navigation/stack'; -import {DefaultNavigatorOptions, ParamListBase, StackNavigationState, DefaultRouterOptions, NavigatorScreenParams} from '@react-navigation/native'; +import {DefaultNavigatorOptions, DefaultRouterOptions, NavigatorScreenParams, ParamListBase, StackNavigationState} from '@react-navigation/native'; +import {StackNavigationEventMap, StackNavigationOptions, StackScreenProps} from '@react-navigation/stack'; import {ValueOf} from 'type-fest'; - -import SCREENS from '../../../SCREENS'; -import NAVIGATORS from '../../../NAVIGATORS'; import CONST from '../../../CONST'; +import NAVIGATORS from '../../../NAVIGATORS'; +import SCREENS from '../../../SCREENS'; type AccountValidationParams = { /** AccountID associated with the validation link */ @@ -41,6 +40,7 @@ type PublicScreensStackParamList = { [SCREENS.UNLINK_LOGIN]: AccountValidationParams; [SCREENS.SIGN_IN_WITH_APPLE_DESKTOP]: undefined; [SCREENS.SIGN_IN_WITH_GOOGLE_DESKTOP]: undefined; + [SCREENS.SAML_SIGN_IN]: undefined; }; type AuthScreensStackParamList = { @@ -59,6 +59,7 @@ type AuthScreensStackParamList = { source: string; }; [SCREENS.NOT_FOUND]: undefined; + [CONST.DEMO_PAGES.MONEY2020]: undefined; [NAVIGATORS.RIGHT_MODAL_NAVIGATOR]: NavigatorScreenParams; [SCREENS.DESKTOP_SIGN_IN_REDIRECT]: undefined; }; diff --git a/src/libs/actions/App.js b/src/libs/actions/App.js index 884dddf0eb0a..92913b290aa6 100644 --- a/src/libs/actions/App.js +++ b/src/libs/actions/App.js @@ -227,7 +227,7 @@ function openApp() { /** * Fetches data when the app reconnects to the network - * @param {Number} [updateIDFrom] the ID of the Onyx update that we want to start fetching from + * @param {Number | null} [updateIDFrom] the ID of the Onyx update that we want to start fetching from */ function reconnectApp(updateIDFrom = 0) { console.debug(`[OnyxUpdates] App reconnecting with updateIDFrom: ${updateIDFrom}`); diff --git a/src/styles/getNavigationModalCardStyles/types.ts b/src/styles/getNavigationModalCardStyles/types.ts index 877981dd4dd2..e0dba07dc908 100644 --- a/src/styles/getNavigationModalCardStyles/types.ts +++ b/src/styles/getNavigationModalCardStyles/types.ts @@ -1,7 +1,5 @@ import {ViewStyle} from 'react-native'; -type GetNavigationModalCardStylesParams = {isSmallScreenWidth: number}; - -type GetNavigationModalCardStyles = (params: GetNavigationModalCardStylesParams) => ViewStyle; +type GetNavigationModalCardStyles = () => ViewStyle; export default GetNavigationModalCardStyles; diff --git a/src/types/onyx/DemoInfo.ts b/src/types/onyx/DemoInfo.ts new file mode 100644 index 000000000000..0e7a09f93983 --- /dev/null +++ b/src/types/onyx/DemoInfo.ts @@ -0,0 +1,7 @@ +type DemoInfo = { + money2020: { + isBeginningDemo?: boolean; + }; +}; + +export default DemoInfo; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index f02d3d2f548f..9486e4e9624c 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -7,6 +7,7 @@ import Card from './Card'; import Credentials from './Credentials'; import Currency from './Currency'; import CustomStatusDraft from './CustomStatusDraft'; +import DemoInfo from './DemoInfo'; import Download from './Download'; import Form, {AddDebitCardForm, DateOfBirthForm} from './Form'; import FrequentlyUsedEmoji from './FrequentlyUsedEmoji'; @@ -61,6 +62,7 @@ export type { Currency, CustomStatusDraft, DateOfBirthForm, + DemoInfo, Download, Form, FrequentlyUsedEmoji, From 22e369f69823c38d02a7bfcd2d428d110b0bfcdb Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 13 Nov 2023 12:37:30 +0100 Subject: [PATCH 05/23] TS fixes after merging main --- .../Navigation/AppNavigator/AuthScreens.tsx | 22 +++++++------------ src/libs/actions/App.ts | 4 ++-- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 3017c2e8e884..533fc68e57d4 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -1,9 +1,6 @@ -import lodashGet from 'lodash/get'; import React, {memo, useEffect, useRef} from 'react'; import {View} from 'react-native'; -import KeyCommand from 'react-native-key-command'; import Onyx, {OnyxEntry, withOnyx} from 'react-native-onyx'; -import {ValueOf} from 'type-fest'; import useWindowDimensions from '@hooks/useWindowDimensions'; import KeyboardShortcut from '@libs/KeyboardShortcut'; import getCurrentUrl from '@libs/Navigation/currentUrl'; @@ -12,7 +9,6 @@ import NetworkConnection from '@libs/NetworkConnection'; import * as Pusher from '@libs/Pusher/pusher'; import PusherConnectionManager from '@libs/PusherConnectionManager'; import * as SessionUtils from '@libs/SessionUtils'; -import {AuthScreensStackParamList} from '@navigation/AppNavigator/types'; import DemoSetupPage from '@pages/DemoSetupPage'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import DesktopSignInRedirectPage from '@pages/signin/DesktopSignInRedirectPage'; @@ -38,6 +34,7 @@ import defaultScreenOptions from './defaultScreenOptions'; import getRootNavigatorScreenOptions from './getRootNavigatorScreenOptions'; import CentralPaneNavigator from './Navigators/CentralPaneNavigator'; import RightModalNavigator from './Navigators/RightModalNavigator'; +import {AuthScreensStackParamList} from './types'; type AuthScreensProps = { /** Session of currently logged in user */ @@ -144,7 +141,7 @@ function AuthScreens({isUsingMemoryOnlyKeys = null, lastUpdateIDAppliedToClient const chatShortcutConfig = CONST.KEYBOARD_SHORTCUTS.NEW_CHAT; const currentUrl = getCurrentUrl(); const isLoggingInAsNewUser = SessionUtils.isLoggingInAsNewUser(currentUrl, session?.email ?? ''); - const shouldGetAllData = isUsingMemoryOnlyKeys || SessionUtils.didUserLogInDuringSession() || isLoggingInAsNewUser; + const shouldGetAllData = isUsingMemoryOnlyKeys ?? SessionUtils.didUserLogInDuringSession() ?? isLoggingInAsNewUser; // Sign out the current user if we're transitioning with a different user const isTransitioning = currentUrl.includes(ROUTES.TRANSITION_BETWEEN_APPS); if (isLoggingInAsNewUser && isTransitioning) { @@ -157,7 +154,7 @@ function AuthScreens({isUsingMemoryOnlyKeys = null, lastUpdateIDAppliedToClient if (isLoadingApp) { App.openApp(); } else { - App.reconnectApp(lastUpdateIDAppliedToClient); + App.reconnectApp(lastUpdateIDAppliedToClient ?? 0); } }); PusherConnectionManager.init(); @@ -177,18 +174,15 @@ function AuthScreens({isUsingMemoryOnlyKeys = null, lastUpdateIDAppliedToClient if (shouldGetAllData) { App.openApp(); } else { - App.reconnectApp(lastUpdateIDAppliedToClient); + App.reconnectApp(lastUpdateIDAppliedToClient ?? 0); } - // TODO: remove when App is merged - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore App.setUpPoliciesAndNavigate(session); App.redirectThirdPartyDesktopSignIn(); // Check if we should be running any demos immediately after signing in. - if (lodashGet(demoInfo, 'money2020.isBeginningDemo', false)) { + if (demoInfo?.money2020?.isBeginningDemo) { Navigation.navigate(ROUTES.MONEY2020, CONST.NAVIGATION.TYPE.FORCED_UP); } if (lastOpenedPublicRoomID) { @@ -211,7 +205,7 @@ function AuthScreens({isUsingMemoryOnlyKeys = null, lastUpdateIDAppliedToClient }); }, shortcutsOverviewShortcutConfig.descriptionKey, - shortcutsOverviewShortcutConfig.modifiers as unknown as string[], + shortcutsOverviewShortcutConfig.modifiers, true, ); @@ -224,7 +218,7 @@ function AuthScreens({isUsingMemoryOnlyKeys = null, lastUpdateIDAppliedToClient Modal.close(Session.checkIfActionIsAllowed(() => Navigation.navigate(ROUTES.SEARCH))); }, shortcutsOverviewShortcutConfig.descriptionKey, - shortcutsOverviewShortcutConfig.modifiers as unknown as string[], + shortcutsOverviewShortcutConfig.modifiers, true, ); @@ -234,7 +228,7 @@ function AuthScreens({isUsingMemoryOnlyKeys = null, lastUpdateIDAppliedToClient Modal.close(Session.checkIfActionIsAllowed(() => Navigation.navigate(ROUTES.NEW))); }, chatShortcutConfig.descriptionKey, - chatShortcutConfig.modifiers as unknown as string[], + chatShortcutConfig.modifiers, true, ); diff --git a/src/libs/actions/App.ts b/src/libs/actions/App.ts index ff673d173613..956c10521363 100644 --- a/src/libs/actions/App.ts +++ b/src/libs/actions/App.ts @@ -3,7 +3,7 @@ import Str from 'expensify-common/lib/str'; import 'moment/locale/es'; import {AppState, AppStateStatus} from 'react-native'; -import Onyx, {OnyxCollection, OnyxUpdate} from 'react-native-onyx'; +import Onyx, {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import {ValueOf} from 'type-fest'; import * as API from '@libs/API'; import * as Browser from '@libs/Browser'; @@ -385,7 +385,7 @@ function savePolicyDraftByNewWorkspace(policyID?: string, policyName?: string, p * pass it in as a parameter. withOnyx guarantees that the value has been read * from Onyx because it will not render the AuthScreens until that point. */ -function setUpPoliciesAndNavigate(session: OnyxTypes.Session) { +function setUpPoliciesAndNavigate(session: OnyxEntry) { const currentUrl = getCurrentUrl(); if (!session || !currentUrl || !currentUrl.includes('exitTo')) { return; From 70bf7426d0c3820e19012e6eb8d2cc86c8daa0c4 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 29 Nov 2023 17:55:36 +0100 Subject: [PATCH 06/23] Fix TS issues after merging main --- src/SCREENS.ts | 2 ++ .../Navigation/AppNavigator/AuthScreens.tsx | 6 ++++- .../AppNavigator/ModalStackNavigators.tsx | 11 +++++++- .../AppNavigator/Navigators/Overlay.tsx | 3 +-- .../AppNavigator/ReportScreenIDSetter.ts | 10 +++---- .../AppNavigator/ReportScreenWrapper.tsx | 1 + src/libs/compose.ts | 27 ++++++++++--------- 7 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 99c0ea877911..6638a207852d 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -89,6 +89,7 @@ const SCREENS = { PRIVATE_NOTES: 'Private_Notes', ROOM_MEMBERS: 'RoomMembers', ROOM_INVITE: 'RoomInvite', + REFERRAL: 'Referral', }, SIGN_IN_WITH_APPLE_DESKTOP: 'AppleSignInDesktop', SIGN_IN_WITH_GOOGLE_DESKTOP: 'GoogleSignInDesktop', @@ -180,6 +181,7 @@ const SCREENS = { REIMBURSEMENT_ACCOUNT_ROOT: 'Reimbursement_Account_Root', WALLET_STATEMENT_ROOT: 'WalletStatement_Root', SIGN_IN_ROOT: 'SignIn_Root', + REFERRAL_DETAILS: 'Referral_Details', SPLIT_DETAILS: { ROOT: 'SplitDetails_Root', diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index c3f2da38cf85..d93cfcc63967 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -29,6 +29,7 @@ import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import * as OnyxTypes from '@src/types/onyx'; import type {Timezone} from '@src/types/onyx/PersonalDetails'; +import {SelectedTimezone} from '@src/types/onyx/PersonalDetails'; import createCustomStackNavigator from './createCustomStackNavigator'; import defaultScreenOptions from './defaultScreenOptions'; import getRootNavigatorScreenOptions from './getRootNavigatorScreenOptions'; @@ -89,7 +90,7 @@ Onyx.connect({ } timezone = val?.[currentAccountID]?.timezone ?? {}; - const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone; + const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone as SelectedTimezone; // If the current timezone is different than the user's timezone, and their timezone is set to automatic // then update their timezone. @@ -309,6 +310,9 @@ function AuthScreens({isUsingMemoryOnlyKeys = null, lastUpdateIDAppliedToClient require('../../../pages/settings/Profile/LoungeAccessPage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET]: () => require('../../../pages/settings/Wallet/WalletPage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET_CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS]: () => require('../../../pages/settings/Profile/PersonalDetails/AddressPage').default as React.ComponentType, - [SCREENS.SETTINGS.WALLET_DOMAIN_CARDS]: () => require('../../../pages/settings/Wallet/ExpensifyCardPage').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_DOMAIN_CARD]: () => require('../../../pages/settings/Wallet/ExpensifyCardPage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET_REPORT_VIRTUAL_CARD_FRAUD]: () => require('../../../pages/settings/Wallet/ReportVirtualCardFraudPage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET_CARD_ACTIVATE]: () => require('../../../pages/settings/Wallet/ActivatePhysicalCardPage').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_CARD_GET_PHYSICAL.NAME]: () => require('../../../pages/settings/Wallet/Card/GetPhysicalCardName').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_CARD_GET_PHYSICAL.PHONE]: () => require('../../../pages/settings/Wallet/Card/GetPhysicalCardPhone').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_CARD_GET_PHYSICAL.ADDRESS]: () => require('../../../pages/settings/Wallet/Card/GetPhysicalCardAddress').default as React.ComponentType, + [SCREENS.SETTINGS.WALLET_CARD_GET_PHYSICAL.CONFIRM]: () => require('../../../pages/settings/Wallet/Card/GetPhysicalCardConfirm').default as React.ComponentType, [SCREENS.SETTINGS.WALLET_TRANSFER_BALANCE]: () => require('../../../pages/settings/Wallet/TransferBalancePage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET_CHOOSE_TRANSFER_ACCOUNT]: () => require('../../../pages/settings/Wallet/ChooseTransferAccountPage').default as React.ComponentType, [SCREENS.SETTINGS.WALLET_ENABLE_PAYMENTS]: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default as React.ComponentType, @@ -223,6 +227,10 @@ const SignInModalStackNavigator = createModalStackNavigator({ [SCREENS.SIGN_IN_ROOT]: () => require('../../../pages/signin/SignInModal').default as React.ComponentType, }); +const ReferralModalStackNavigator = createModalStackNavigator({ + [SCREENS.REFERRAL_DETAILS]: () => require('../../../pages/ReferralDetailsPage').default as React.ComponentType, +}); + export { MoneyRequestModalStackNavigator, SplitDetailsModalStackNavigator, @@ -248,4 +256,5 @@ export { SignInModalStackNavigator, RoomMembersModalStackNavigator, RoomInviteModalStackNavigator, + ReferralModalStackNavigator, }; diff --git a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx index 96478df1e489..098e9a3dccf5 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx @@ -13,8 +13,7 @@ type OverlayProps = { function Overlay({onPress}: OverlayProps) { const styles = useThemeStyles(); const {current} = useCardAnimation(); - // TODO: remove type assertion when useLocalize is migrated - const {translate} = useLocalize() as unknown as {translate: (phrase: string) => string}; + const {translate} = useLocalize(); return ( diff --git a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts index 40bb2707ea01..5484aca5acdf 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts +++ b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts @@ -30,19 +30,15 @@ const getLastAccessedReportID = ( policies: OnyxCollection, isFirstTimeNewExpensifyUser: OnyxEntry, openOnAdminRoom: boolean, -): number | string => { +): string | undefined => { // If deeplink url contains reportID params, we should show the report that has this reportID. const currentRoute = Navigation.getActiveRoute(); - // TODO: get rid of assertion when ReportUtils is migrated to TS - const {reportID} = ReportUtils.parseReportRouteParams(currentRoute) as {reportID: string}; + const {reportID} = ReportUtils.parseReportRouteParams(currentRoute); if (reportID) { return reportID; } - // TODO: get rid of ignore when ReportUtils is migrated to TS - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore till ReportUtils file is migrated - const lastReport = ReportUtils.findLastAccessedReport(reports, ignoreDefaultRooms, policies, isFirstTimeNewExpensifyUser, openOnAdminRoom) as Report; + const lastReport = ReportUtils.findLastAccessedReport(reports, ignoreDefaultRooms, policies, !!isFirstTimeNewExpensifyUser, openOnAdminRoom); return lastReport?.reportID; }; diff --git a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx index fda939a0e15d..a155cb6f3085 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx +++ b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx @@ -8,6 +8,7 @@ function ReportScreenWrapper({route, navigation}: ReportScreenWrapperProps) { // until the reportID is loaded and set in the route param return ( <> + {/* @ts-expect-error Error will be resolved after ReportScreen migration */} = (...a: T) => R; - export default function compose(): (a: R) => R; export default function compose(f: F): F; /* two functions */ -export default function compose(f1: (args: A) => R1, f2: Func): Func; +export default function compose(f1: (...args: A) => R1, f2: (a: R1) => R2): (...args: A) => R2; /* three functions */ -export default function compose(f1: (args: A) => R1, f2: (a: R1) => R2, f3: Func): Func; +export default function compose(f1: (...args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3): (...args: A) => R3; /* four functions */ -export default function compose(f1: (args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3, f4: Func): Func; +export default function compose(f1: (...args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3, f4: (a: R3) => R4): (...args: A) => R4; /* five functions */ -export default function compose(f1: (args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3, f4: (a: R3) => R4, f5: Func): Func; +export default function compose( + f1: (...args: A) => R1, + f2: (a: R1) => R2, + f3: (a: R2) => R3, + f4: (a: R3) => R4, + f5: (a: R4) => R5, +): (...args: A) => R5; /* six functions */ -export default function compose( - f1: (args: A) => R1, +export default function compose( + f1: (...args: A) => R1, f2: (a: R1) => R2, f3: (a: R2) => R3, f4: (a: R3) => R4, f5: (a: R4) => R5, - f6: Func, -): Func; + f6: (a: R5) => R6, +): (...args: A) => R6; /* rest */ export default function compose(f1: (a: unknown) => R, ...funcs: Function[]): (...args: unknown[]) => R; -export default function compose(...funcs: Function[]): (...args: unknown[]) => R; - export default function compose(...funcs: Function[]): Function { if (funcs.length === 0) { // infer the argument type so it is usable in inference down the line From 6799a1d4fe8539ff799520412554a61f6af50406 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 29 Nov 2023 18:06:37 +0100 Subject: [PATCH 07/23] Fix TS issues after merging main --- .../AppNavigator/ModalStackNavigators.tsx | 21 ++++++++++++------- .../AppNavigator/RHPScreenOptions.ts | 10 ++++----- .../getRootNavigatorScreenOptions.ts | 5 +++-- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index f7bf35c1d876..f0289b2927bf 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -1,14 +1,8 @@ import {CardStyleInterpolators, createStackNavigator} from '@react-navigation/stack'; -import React from 'react'; -import styles from '@styles/styles'; +import React, {useMemo} from 'react'; +import useThemeStyles from '@styles/useThemeStyles'; import SCREENS from '@src/SCREENS'; -const defaultSubRouteOptions = { - cardStyle: styles.navigationScreenCardStyle, - headerShown: false, - cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, -}; - type Screens = Record React.ComponentType>; /** @@ -20,6 +14,17 @@ function createModalStackNavigator(screens: Screens): () => React.JSX.Element { const ModalStackNavigator = createStackNavigator(); function ModalStack() { + const styles = useThemeStyles(); + + const defaultSubRouteOptions = useMemo( + () => ({ + cardStyle: styles.navigationScreenCardStyle, + headerShown: false, + cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, + }), + [styles], + ); + return ( {Object.keys(screens).map((name) => ( diff --git a/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts b/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts index 5e04bf4d0905..6b56bb00cf56 100644 --- a/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts +++ b/src/libs/Navigation/AppNavigator/RHPScreenOptions.ts @@ -1,16 +1,16 @@ import {CardStyleInterpolators, StackNavigationOptions} from '@react-navigation/stack'; +import styles from '@styles/styles'; /** * RHP stack navigator screen options generator function - * @function - * @param {Object} styles - The styles object - * @returns {Object} - The screen options object + * @param themeStyles - The styles object + * @returns The screen options object */ -const RHPScreenOptions = (styles): StackNavigationOptions => ({ +const RHPScreenOptions = (themeStyles: typeof styles): StackNavigationOptions => ({ headerShown: false, animationEnabled: true, gestureDirection: 'horizontal', - cardStyle: styles.navigationScreenCardStyle, + cardStyle: themeStyles.navigationScreenCardStyle, cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, }); diff --git a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts index a04260fc4b59..7f7dfdda7adc 100644 --- a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts +++ b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.ts @@ -1,5 +1,6 @@ import {StackCardInterpolationProps, StackNavigationOptions} from '@react-navigation/stack'; import getNavigationModalCardStyle from '@styles/getNavigationModalCardStyles'; +import styles from '@styles/styles'; import variables from '@styles/variables'; import CONFIG from '@src/CONFIG'; import modalCardStyleInterpolator from './modalCardStyleInterpolator'; @@ -12,7 +13,7 @@ const commonScreenOptions: StackNavigationOptions = { animationTypeForReplace: 'push', }; -export default (isSmallScreenWidth: boolean, styles) => ({ +export default (isSmallScreenWidth: boolean, themeStyles: typeof styles) => ({ rightModalNavigator: { ...commonScreenOptions, cardStyleInterpolator: (props: StackCardInterpolationProps) => modalCardStyleInterpolator(isSmallScreenWidth, false, props), @@ -41,7 +42,7 @@ export default (isSmallScreenWidth: boolean, styles) => ({ // We need to translate the sidebar to not be covered by the StackNavigator so it can be clickable. transform: [{translateX: isSmallScreenWidth ? 0 : -variables.sideBarWidth}], - ...(isSmallScreenWidth ? {} : styles.borderRight), + ...(isSmallScreenWidth ? {} : themeStyles.borderRight), }, } as StackNavigationOptions, fullScreen: { From 7580e3ad45fc7e74ac16a886c1519b3b56e7093f Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 29 Nov 2023 18:10:23 +0100 Subject: [PATCH 08/23] Fix lint issue --- src/libs/Navigation/AppNavigator/types.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/types.ts b/src/libs/Navigation/AppNavigator/types.ts index fa5ac3702597..8b8423e9bada 100644 --- a/src/libs/Navigation/AppNavigator/types.ts +++ b/src/libs/Navigation/AppNavigator/types.ts @@ -1,9 +1,9 @@ import {DefaultNavigatorOptions, DefaultRouterOptions, NavigatorScreenParams, ParamListBase, StackNavigationState} from '@react-navigation/native'; import {StackNavigationEventMap, StackNavigationOptions, StackScreenProps} from '@react-navigation/stack'; import {ValueOf} from 'type-fest'; -import CONST from '../../../CONST'; -import NAVIGATORS from '../../../NAVIGATORS'; -import SCREENS from '../../../SCREENS'; +import CONST from '@src/CONST'; +import NAVIGATORS from '@src/NAVIGATORS'; +import SCREENS from '@src/SCREENS'; type AccountValidationParams = { /** AccountID associated with the validation link */ From 8cb67ac73a3c7e537a09f0c83dd18bfd0bdd4dfb Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 29 Nov 2023 18:15:48 +0100 Subject: [PATCH 09/23] Run prettier --- src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts b/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts index 711905104acf..f7e772148e79 100644 --- a/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts +++ b/src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.ts @@ -1,5 +1,5 @@ -import {Animated} from 'react-native'; import type {StackCardInterpolatedStyle, StackCardInterpolationProps} from '@react-navigation/stack'; +import {Animated} from 'react-native'; import getCardStyles from '@styles/cardStyles'; import variables from '@styles/variables'; From 16b732f571ce2c9ce2a2ea45a03bfd40d1f1b005 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Fri, 1 Dec 2023 10:31:23 +0100 Subject: [PATCH 10/23] Update CustomRouter typing --- .../CustomRouter.ts | 56 ++++++++----------- .../createCustomStackNavigator/index.tsx | 1 - src/libs/Navigation/AppNavigator/types.ts | 4 +- 3 files changed, 25 insertions(+), 36 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts index ce120e0409e1..020abbf3fd04 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts @@ -1,51 +1,36 @@ -import {ParamListBase, PartialState, RouterConfigOptions, StackNavigationState, StackRouter} from '@react-navigation/native'; -import {ResponsiveStackNavigatorRouterOptions} from '@libs/Navigation/AppNavigator/types'; +import {NavigationState, PartialState, RouterConfigOptions, StackNavigationState, StackRouter} from '@react-navigation/native'; +import {ParamListBase} from '@react-navigation/routers'; +import {ResponsiveStackNavigatorRouterOptions} from '@navigation/AppNavigator/types'; import NAVIGATORS from '@src/NAVIGATORS'; import SCREENS from '@src/SCREENS'; -type MutableState = { - index: number; - stale: true; -}; - -type State = Omit>, 'stale'> & MutableState; +type State = NavigationState | PartialState; -const isAtLeastOneCentralPaneNavigatorInState = (state: State): boolean => !!state.routes.find((r) => r.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR); +/** + * @param state - react-navigation state + */ +const isAtLeastOneCentralPaneNavigatorInState = (state: State): boolean => !!state.routes.find((route) => route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR); /** * @param state - react-navigation state - * @returns */ const getTopMostReportIDFromRHP = (state: State): string => { if (!state) { return ''; } - const topmostRightPane = [...state.routes].reverse().find((route) => route.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR); + const topmostRightPane = state.routes.filter((route) => route.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR).at(-1); - if (topmostRightPane) { - // TODO: fix TS issue - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore + if (topmostRightPane?.state) { return getTopMostReportIDFromRHP(topmostRightPane.state); } - const topmostRoute = state.routes[state.routes.length - 1]; + const topmostRoute = state.routes.at(-1); - if (topmostRoute.state) { - // TODO: fix TS issue - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore + if (topmostRoute?.state) { return getTopMostReportIDFromRHP(topmostRoute.state); } - // TODO: fix TS issue - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - if (topmostRoute.params?.reportID) { - // TODO: fix TS issue - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unsafe-return + if (topmostRoute?.params && 'reportID' in topmostRoute.params && typeof topmostRoute.params.reportID === 'string' && topmostRoute.params.reportID) { return topmostRoute.params.reportID; } @@ -54,6 +39,8 @@ const getTopMostReportIDFromRHP = (state: State): string => { /** * Adds report route without any specific reportID to the state. * The report screen will self set proper reportID param based on the helper function findLastAccessedReport (look at ReportScreenWrapper for more info) + * + * @param state - react-navigation state */ const addCentralPaneNavigatorRoute = (state: State) => { const reportID = getTopMostReportIDFromRHP(state); @@ -71,8 +58,9 @@ const addCentralPaneNavigatorRoute = (state: State) => { }, }; state.routes.splice(1, 0, centralPaneNavigatorRoute); - // eslint-disable-next-line no-param-reassign - state.index = state.routes.length - 1; + // @ts-expect-error Updating read only property + // noinspection JSConstantReassignment + state.index = state.routes.length - 1; // eslint-disable-line }; function CustomRouter(options: ResponsiveStackNavigatorRouterOptions) { @@ -80,12 +68,14 @@ function CustomRouter(options: ResponsiveStackNavigatorRouterOptions) { return { ...stackRouter, - getRehydratedState(partialState: State, {routeNames, routeParamList, routeGetIdList}: RouterConfigOptions) { + getRehydratedState(partialState: StackNavigationState, {routeNames, routeParamList, routeGetIdList}: RouterConfigOptions): StackNavigationState { // Make sure that there is at least one CentralPaneNavigator (ReportScreen by default) in the state if this is a wide layout if (!isAtLeastOneCentralPaneNavigatorInState(partialState) && !options.getIsSmallScreenWidth()) { // If we added a route we need to make sure that the state.stale is true to generate new key for this route - // eslint-disable-next-line no-param-reassign - partialState.stale = true; + + // @ts-expect-error Updating read only property + // noinspection JSConstantReassignment + partialState.stale = true; // eslint-disable-line addCentralPaneNavigatorRoute(partialState); } const state = stackRouter.getRehydratedState(partialState, {routeNames, routeParamList, routeGetIdList}); diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx index 3d3bd6d8d447..f60d96782538 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx @@ -7,7 +7,6 @@ import NAVIGATORS from '@src/NAVIGATORS'; import CustomRouter from './CustomRouter'; type Routes = StackNavigationState['routes']; - function reduceReportRoutes(routes: Routes): Routes { const result: Routes = []; let count = 0; diff --git a/src/libs/Navigation/AppNavigator/types.ts b/src/libs/Navigation/AppNavigator/types.ts index 8b8423e9bada..3cce416fcfd8 100644 --- a/src/libs/Navigation/AppNavigator/types.ts +++ b/src/libs/Navigation/AppNavigator/types.ts @@ -1,4 +1,4 @@ -import {DefaultNavigatorOptions, DefaultRouterOptions, NavigatorScreenParams, ParamListBase, StackNavigationState} from '@react-navigation/native'; +import {DefaultNavigatorOptions, NavigatorScreenParams, ParamListBase, StackNavigationState, StackRouterOptions} from '@react-navigation/native'; import {StackNavigationEventMap, StackNavigationOptions, StackScreenProps} from '@react-navigation/stack'; import {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; @@ -70,7 +70,7 @@ type RightModalNavigatorStackParamList = Record boolean; }; type ResponsiveStackNavigatorProps = DefaultNavigatorOptions, StackNavigationOptions, StackNavigationEventMap> & From 603bab0b5a4250be1ce4bb7b951443589fa017ee Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Fri, 1 Dec 2023 11:14:31 +0100 Subject: [PATCH 11/23] Use types from Navigation types file --- .../Navigation/AppNavigator/AuthScreens.tsx | 7 +- .../BaseCentralPaneNavigator.tsx | 4 +- .../Navigators/RightModalNavigator.tsx | 6 +- .../Navigation/AppNavigator/PublicScreens.tsx | 4 +- .../AppNavigator/ReportScreenIDSetter.ts | 2 +- .../AppNavigator/ReportScreenWrapper.tsx | 7 +- .../CustomRouter.ts | 2 +- .../index.native.tsx | 2 +- .../createCustomStackNavigator/index.tsx | 2 +- .../createCustomStackNavigator/types.ts | 15 ++++ src/libs/Navigation/AppNavigator/types.ts | 88 ------------------- src/libs/Navigation/types.ts | 20 ++++- src/pages/ErrorPage/NotFoundPage.js | 4 +- 13 files changed, 55 insertions(+), 108 deletions(-) create mode 100644 src/libs/Navigation/AppNavigator/createCustomStackNavigator/types.ts delete mode 100644 src/libs/Navigation/AppNavigator/types.ts diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 1dfb8512ad10..a50bae34f064 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -9,6 +9,7 @@ import NetworkConnection from '@libs/NetworkConnection'; import * as Pusher from '@libs/Pusher/pusher'; import PusherConnectionManager from '@libs/PusherConnectionManager'; import * as SessionUtils from '@libs/SessionUtils'; +import type {AuthScreensParamList} from '@navigation/types'; import DemoSetupPage from '@pages/DemoSetupPage'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import DesktopSignInRedirectPage from '@pages/signin/DesktopSignInRedirectPage'; @@ -35,7 +36,6 @@ import defaultScreenOptions from './defaultScreenOptions'; import getRootNavigatorScreenOptions from './getRootNavigatorScreenOptions'; import CentralPaneNavigator from './Navigators/CentralPaneNavigator'; import RightModalNavigator from './Navigators/RightModalNavigator'; -import {AuthScreensStackParamList} from './types'; type AuthScreensProps = { /** Session of currently logged in user */ @@ -111,7 +111,7 @@ Onyx.connect({ }, }); -const RootStack = createCustomStackNavigator(); +const RootStack = createCustomStackNavigator(); // We want to delay the re-rendering for components(e.g. ReportActionCompose) // that depends on modal visibility until Modal is completely closed and its focused // When modal screen is focused, update modal visibility in Onyx @@ -310,9 +310,6 @@ function AuthScreens({isUsingMemoryOnlyKeys = null, lastUpdateIDAppliedToClient (); +const Stack = createStackNavigator(); const url = getCurrentUrl(); const openOnAdminRoom = url ? new URL(url).searchParams.get('openOnAdminRoom') : undefined; diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx index cf3aea683fd8..104fbc29b12b 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx @@ -5,14 +5,14 @@ import NoDropZone from '@components/DragAndDrop/NoDropZone'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as ModalStackNavigators from '@libs/Navigation/AppNavigator/ModalStackNavigators'; import RHPScreenOptions from '@libs/Navigation/AppNavigator/RHPScreenOptions'; -import {AuthScreensStackParamList, RightModalNavigatorStackParamList} from '@libs/Navigation/AppNavigator/types'; +import type {AuthScreensParamList, RightModalNavigatorParamList} from '@navigation/types'; import useThemeStyles from '@styles/useThemeStyles'; import NAVIGATORS from '@src/NAVIGATORS'; import Overlay from './Overlay'; -const Stack = createStackNavigator(); +const Stack = createStackNavigator(); -function RightModalNavigator(props: StackScreenProps) { +function RightModalNavigator(props: StackScreenProps) { const styles = useThemeStyles(); const {isSmallScreenWidth} = useWindowDimensions(); const screenOptions = useMemo(() => RHPScreenOptions(styles), [styles]); diff --git a/src/libs/Navigation/AppNavigator/PublicScreens.tsx b/src/libs/Navigation/AppNavigator/PublicScreens.tsx index d4e4726e7c42..84bcf39e7121 100644 --- a/src/libs/Navigation/AppNavigator/PublicScreens.tsx +++ b/src/libs/Navigation/AppNavigator/PublicScreens.tsx @@ -1,5 +1,6 @@ import {createStackNavigator} from '@react-navigation/stack'; import React from 'react'; +import type {PublicScreensParamList} from '@navigation/types'; import LogInWithShortLivedAuthTokenPage from '@pages/LogInWithShortLivedAuthTokenPage'; import AppleSignInDesktopPage from '@pages/signin/AppleSignInDesktopPage'; import GoogleSignInDesktopPage from '@pages/signin/GoogleSignInDesktopPage'; @@ -9,9 +10,8 @@ import UnlinkLoginPage from '@pages/UnlinkLoginPage'; import ValidateLoginPage from '@pages/ValidateLoginPage'; import SCREENS from '@src/SCREENS'; import defaultScreenOptions from './defaultScreenOptions'; -import type {PublicScreensStackParamList} from './types'; -const RootStack = createStackNavigator(); +const RootStack = createStackNavigator(); function PublicScreens() { return ( diff --git a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts index 33baa939ae62..d59c1731a6fa 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts +++ b/src/libs/Navigation/AppNavigator/ReportScreenIDSetter.ts @@ -5,7 +5,7 @@ import * as ReportUtils from '@libs/ReportUtils'; import * as App from '@userActions/App'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, Report} from '@src/types/onyx'; -import type {ReportScreenWrapperProps} from './types'; +import type {ReportScreenWrapperProps} from './ReportScreenWrapper'; type ReportScreenIDSetterComponentProps = { /** Available reports that would be displayed in this navigator */ diff --git a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx index a155cb6f3085..b0be8eae82ce 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx +++ b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx @@ -1,7 +1,11 @@ +import {StackScreenProps} from '@react-navigation/stack'; import React from 'react'; +import type {CentralPaneNavigatorParamList} from '@navigation/types'; import ReportScreen from '@pages/home/ReportScreen'; +import SCREENS from '@src/SCREENS'; import ReportScreenIDSetter from './ReportScreenIDSetter'; -import {ReportScreenWrapperProps} from './types'; + +type ReportScreenWrapperProps = StackScreenProps; function ReportScreenWrapper({route, navigation}: ReportScreenWrapperProps) { // The ReportScreen without the reportID set will display a skeleton @@ -21,3 +25,4 @@ function ReportScreenWrapper({route, navigation}: ReportScreenWrapperProps) { ReportScreenWrapper.displayName = 'ReportScreenWrapper'; export default ReportScreenWrapper; +export type {ReportScreenWrapperProps}; diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts index 020abbf3fd04..c7fdd59329d0 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts @@ -1,8 +1,8 @@ import {NavigationState, PartialState, RouterConfigOptions, StackNavigationState, StackRouter} from '@react-navigation/native'; import {ParamListBase} from '@react-navigation/routers'; -import {ResponsiveStackNavigatorRouterOptions} from '@navigation/AppNavigator/types'; import NAVIGATORS from '@src/NAVIGATORS'; import SCREENS from '@src/SCREENS'; +import type {ResponsiveStackNavigatorRouterOptions} from './types'; type State = NavigationState | PartialState; diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx index 25675effabca..05bff008bb14 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.native.tsx @@ -2,8 +2,8 @@ import {createNavigatorFactory, ParamListBase, StackActionHelpers, StackNavigati import {StackNavigationEventMap, StackNavigationOptions, StackView} from '@react-navigation/stack'; import React, {useRef} from 'react'; import useWindowDimensions from '@hooks/useWindowDimensions'; -import {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from '@navigation/AppNavigator/types'; import CustomRouter from './CustomRouter'; +import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from './types'; function ResponsiveStackNavigator(props: ResponsiveStackNavigatorProps) { const {isSmallScreenWidth} = useWindowDimensions(); diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx index f60d96782538..daf03a66b4a0 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.tsx @@ -2,9 +2,9 @@ import {createNavigatorFactory, ParamListBase, StackActionHelpers, StackNavigati import {StackNavigationEventMap, StackNavigationOptions, StackView} from '@react-navigation/stack'; import React, {useMemo, useRef} from 'react'; import useWindowDimensions from '@hooks/useWindowDimensions'; -import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from '@libs/Navigation/AppNavigator/types'; import NAVIGATORS from '@src/NAVIGATORS'; import CustomRouter from './CustomRouter'; +import type {ResponsiveStackNavigatorProps, ResponsiveStackNavigatorRouterOptions} from './types'; type Routes = StackNavigationState['routes']; function reduceReportRoutes(routes: Routes): Routes { diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/types.ts b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/types.ts new file mode 100644 index 000000000000..a6135e8365ad --- /dev/null +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/types.ts @@ -0,0 +1,15 @@ +import {DefaultNavigatorOptions, ParamListBase, StackNavigationState, StackRouterOptions} from '@react-navigation/native'; +import {StackNavigationEventMap, StackNavigationOptions} from '@react-navigation/stack'; + +type ResponsiveStackNavigatorConfig = { + isSmallScreenWidth: boolean; +}; + +type ResponsiveStackNavigatorRouterOptions = StackRouterOptions & { + getIsSmallScreenWidth: () => boolean; +}; + +type ResponsiveStackNavigatorProps = DefaultNavigatorOptions, StackNavigationOptions, StackNavigationEventMap> & + ResponsiveStackNavigatorConfig; + +export type {ResponsiveStackNavigatorRouterOptions, ResponsiveStackNavigatorProps, ResponsiveStackNavigatorConfig}; diff --git a/src/libs/Navigation/AppNavigator/types.ts b/src/libs/Navigation/AppNavigator/types.ts deleted file mode 100644 index 3cce416fcfd8..000000000000 --- a/src/libs/Navigation/AppNavigator/types.ts +++ /dev/null @@ -1,88 +0,0 @@ -import {DefaultNavigatorOptions, NavigatorScreenParams, ParamListBase, StackNavigationState, StackRouterOptions} from '@react-navigation/native'; -import {StackNavigationEventMap, StackNavigationOptions, StackScreenProps} from '@react-navigation/stack'; -import {ValueOf} from 'type-fest'; -import CONST from '@src/CONST'; -import NAVIGATORS from '@src/NAVIGATORS'; -import SCREENS from '@src/SCREENS'; - -type AccountValidationParams = { - /** AccountID associated with the validation link */ - accountID: string; - - /** Validation code associated with the validation link */ - validateCode: string; -}; - -type CentralPaneStackParamList = { - [SCREENS.REPORT]: { - /** If the admin room should be opened */ - openOnAdminRoom?: boolean; - - /** The ID of the report this screen should display */ - reportID: string; - }; -}; -type ReportScreenWrapperProps = StackScreenProps; - -type PublicScreensStackParamList = { - [SCREENS.HOME]: undefined; - [SCREENS.TRANSITION_BETWEEN_APPS]: { - /** Short-lived authToken to sign in a user */ - shortLivedAuthToken: string; - - /** Short-lived authToken to sign in as a user, if they are coming from the old mobile app */ - shortLivedToken: string; - - /** The email of the transitioning user */ - email: string; - }; - [SCREENS.VALIDATE_LOGIN]: AccountValidationParams; - [SCREENS.UNLINK_LOGIN]: AccountValidationParams; - [SCREENS.SIGN_IN_WITH_APPLE_DESKTOP]: undefined; - [SCREENS.SIGN_IN_WITH_GOOGLE_DESKTOP]: undefined; - [SCREENS.SAML_SIGN_IN]: undefined; -}; - -type AuthScreensStackParamList = { - [SCREENS.HOME]: undefined; - [NAVIGATORS.CENTRAL_PANE_NAVIGATOR]: NavigatorScreenParams; - [SCREENS.VALIDATE_LOGIN]: AccountValidationParams; - [SCREENS.TRANSITION_BETWEEN_APPS]: undefined; - [SCREENS.CONCIERGE]: undefined; - [CONST.DEMO_PAGES.SAASTR]: {name: string}; - [CONST.DEMO_PAGES.SBE]: {name: string}; - [SCREENS.REPORT_ATTACHMENTS]: { - /** The report ID which the attachment is associated with */ - reportID: string; - - /** The uri encoded source of the attachment */ - source: string; - }; - [SCREENS.NOT_FOUND]: undefined; - [CONST.DEMO_PAGES.MONEY2020]: undefined; - [NAVIGATORS.RIGHT_MODAL_NAVIGATOR]: NavigatorScreenParams; - [SCREENS.DESKTOP_SIGN_IN_REDIRECT]: undefined; -}; - -// TODO: describe all of the nested navigators -type RightModalNavigatorStackParamList = Record, undefined>; - -type ResponsiveStackNavigatorConfig = { - isSmallScreenWidth: boolean; -}; -type ResponsiveStackNavigatorRouterOptions = StackRouterOptions & { - getIsSmallScreenWidth: () => boolean; -}; -type ResponsiveStackNavigatorProps = DefaultNavigatorOptions, StackNavigationOptions, StackNavigationEventMap> & - ResponsiveStackNavigatorConfig; - -export type { - CentralPaneStackParamList, - ReportScreenWrapperProps, - PublicScreensStackParamList, - RightModalNavigatorStackParamList, - ResponsiveStackNavigatorRouterOptions, - ResponsiveStackNavigatorProps, - ResponsiveStackNavigatorConfig, - AuthScreensStackParamList, -}; diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 41df21d8e237..1668ecc9cf50 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -37,6 +37,7 @@ type CentralPaneNavigatorParamList = { [SCREENS.REPORT]: { reportActionID: string; reportID: string; + openOnAdminRoom?: boolean; }; }; @@ -390,6 +391,12 @@ type AuthScreensParamList = { reportID: string; source: string; }; + [CONST.DEMO_PAGES.SAASTR]: { + name: string; + }; + [CONST.DEMO_PAGES.SBE]: { + name: string; + }; [SCREENS.NOT_FOUND]: undefined; [NAVIGATORS.RIGHT_MODAL_NAVIGATOR]: NavigatorScreenParams; [SCREENS.DESKTOP_SIGN_IN_REDIRECT]: undefined; @@ -398,4 +405,15 @@ type AuthScreensParamList = { type RootStackParamList = PublicScreensParamList & AuthScreensParamList; -export type {NavigationRef, StackNavigationAction, CentralPaneNavigatorParamList, RootStackParamList, StateOrRoute, NavigationStateRoute, NavigationRoot}; +export type { + NavigationRef, + StackNavigationAction, + CentralPaneNavigatorParamList, + RootStackParamList, + StateOrRoute, + NavigationStateRoute, + NavigationRoot, + AuthScreensParamList, + RightModalNavigatorParamList, + PublicScreensParamList, +}; diff --git a/src/pages/ErrorPage/NotFoundPage.js b/src/pages/ErrorPage/NotFoundPage.js index aac2e6d613f9..e10ec32732ea 100644 --- a/src/pages/ErrorPage/NotFoundPage.js +++ b/src/pages/ErrorPage/NotFoundPage.js @@ -13,12 +13,12 @@ const defaultProps = { }; // eslint-disable-next-line rulesdir/no-negated-variables -function NotFoundPage({onBackButtonPress}) { +function NotFoundPage(props) { return ( ); From 38d5c731b1c1c5fff64d9e53bb1d4a695ee98f11 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Fri, 1 Dec 2023 14:42:55 +0100 Subject: [PATCH 12/23] Update types file to use screen constants --- src/SCREENS.ts | 1 + src/libs/Navigation/types.ts | 260 +++++++++++++++++------------------ 2 files changed, 131 insertions(+), 130 deletions(-) diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 6638a207852d..3072b534f744 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -57,6 +57,7 @@ const SCREENS = { ADD_BANK_ACCOUNT: 'Settings_Add_Bank_Account', PREFERENCES_PRIORITY_MODE: 'Settings_Preferences_PriorityMode', PREFERENCES_LANGUAGE: 'Settings_Preferences_Language', + PREFERENCES_THEME: 'Settings_Preferences_Theme', CLOSE: 'Settings_Close', STATUS_SET: 'Settings_Status_Set', TWO_FACTOR_AUTH: 'Settings_TwoFactorAuth', diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 1668ecc9cf50..c5eac46f8ffa 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -43,313 +43,313 @@ type CentralPaneNavigatorParamList = { type SettingsNavigatorParamList = { [SCREENS.SETTINGS.ROOT]: undefined; - Settings_Share_Code: undefined; + [SCREENS.SETTINGS.SHARE_CODE]: undefined; [SCREENS.SETTINGS.WORKSPACES]: undefined; - Settings_Profile: undefined; - Settings_Pronouns: undefined; - Settings_Display_Name: undefined; - Settings_Timezone: undefined; - Settings_Timezone_Select: undefined; - Settings_PersonalDetails_Initial: undefined; - Settings_PersonalDetails_LegalName: undefined; - Settings_PersonalDetails_DateOfBirth: undefined; - Settings_PersonalDetails_Address: undefined; - Settings_PersonalDetails_Address_Country: undefined; - Settings_ContactMethods: undefined; - Settings_ContactMethodDetails: undefined; - Settings_NewContactMethod: undefined; + [SCREENS.SETTINGS.PROFILE]: undefined; + [SCREENS.SETTINGS.PRONOUNS]: undefined; + [SCREENS.SETTINGS.DISPLAY_NAME]: undefined; + [SCREENS.SETTINGS.TIMEZONE]: undefined; + [SCREENS.SETTINGS.TIMEZONE_SELECT]: undefined; + [SCREENS.SETTINGS.PERSONAL_DETAILS_INITIAL]: undefined; + [SCREENS.SETTINGS.PERSONAL_DETAILS_LEGAL_NAME]: undefined; + [SCREENS.SETTINGS.PERSONAL_DETAILS_DATE_OF_BIRTH]: undefined; + [SCREENS.SETTINGS.PERSONAL_DETAILS_ADDRESS]: undefined; + [SCREENS.SETTINGS.PERSONAL_DETAILS_ADDRESS_COUNTRY]: undefined; + [SCREENS.SETTINGS.CONTACT_METHODS]: undefined; + [SCREENS.SETTINGS.CONTACT_METHOD_DETAILS]: undefined; + [SCREENS.SETTINGS.NEW_CONTACT_METHOD]: undefined; [SCREENS.SETTINGS.PREFERENCES]: undefined; - Settings_Preferences_PriorityMode: undefined; - Settings_Preferences_Language: undefined; - Settings_Preferences_Theme: undefined; - Settings_Close: undefined; + [SCREENS.SETTINGS.PREFERENCES_PRIORITY_MODE]: undefined; + [SCREENS.SETTINGS.PREFERENCES_LANGUAGE]: undefined; + [SCREENS.SETTINGS.PREFERENCES_THEME]: undefined; + [SCREENS.SETTINGS.CLOSE]: undefined; [SCREENS.SETTINGS.SECURITY]: undefined; - Settings_About: undefined; - Settings_App_Download_Links: undefined; - Settings_Lounge_Access: undefined; - Settings_Wallet: undefined; - Settings_Wallet_Cards_Digital_Details_Update_Address: undefined; - Settings_Wallet_DomainCard: undefined; - Settings_Wallet_ReportVirtualCardFraud: undefined; - Settings_Wallet_Card_Activate: undefined; + [SCREENS.SETTINGS.ABOUT]: undefined; + [SCREENS.SETTINGS.APP_DOWNLOAD_LINKS]: undefined; + [SCREENS.SETTINGS.LOUNGE_ACCESS]: undefined; + [SCREENS.SETTINGS.WALLET]: undefined; + [SCREENS.SETTINGS.WALLET_CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS]: undefined; + [SCREENS.SETTINGS.WALLET_DOMAIN_CARD]: undefined; + [SCREENS.SETTINGS.WALLET_REPORT_VIRTUAL_CARD_FRAUD]: undefined; + [SCREENS.SETTINGS.WALLET_CARD_ACTIVATE]: undefined; [SCREENS.SETTINGS.WALLET_CARD_GET_PHYSICAL.NAME]: undefined; [SCREENS.SETTINGS.WALLET_CARD_GET_PHYSICAL.PHONE]: undefined; [SCREENS.SETTINGS.WALLET_CARD_GET_PHYSICAL.ADDRESS]: undefined; [SCREENS.SETTINGS.WALLET_CARD_GET_PHYSICAL.CONFIRM]: undefined; - Settings_Wallet_Transfer_Balance: undefined; - Settings_Wallet_Choose_Transfer_Account: undefined; - Settings_Wallet_EnablePayments: undefined; - Settings_Add_Debit_Card: undefined; - Settings_Add_Bank_Account: undefined; + [SCREENS.SETTINGS.WALLET_TRANSFER_BALANCE]: undefined; + [SCREENS.SETTINGS.WALLET_CHOOSE_TRANSFER_ACCOUNT]: undefined; + [SCREENS.SETTINGS.WALLET_ENABLE_PAYMENTS]: undefined; + [SCREENS.SETTINGS.ADD_DEBIT_CARD]: undefined; + [SCREENS.SETTINGS.ADD_BANK_ACCOUNT]: undefined; [SCREENS.SETTINGS.STATUS]: undefined; - Settings_Status_Set: undefined; - Workspace_Initial: undefined; - Workspace_Settings: undefined; - Workspace_Settings_Currency: undefined; - Workspace_Card: { + [SCREENS.SETTINGS.STATUS_SET]: undefined; + [SCREENS.WORKSPACE.INITIAL]: undefined; + [SCREENS.WORKSPACE.SETTINGS]: undefined; + [SCREENS.WORKSPACE.CURRENCY]: undefined; + [SCREENS.WORKSPACE.CARD]: { policyID: string; }; - Workspace_Reimburse: { + [SCREENS.WORKSPACE.REIMBURSE]: { policyID: string; }; - Workspace_RateAndUnit: undefined; - Workspace_Bills: { + [SCREENS.WORKSPACE.RATE_AND_UNIT]: undefined; + [SCREENS.WORKSPACE.BILLS]: { policyID: string; }; - Workspace_Invoices: { + [SCREENS.WORKSPACE.INVOICES]: { policyID: string; }; - Workspace_Travel: { + [SCREENS.WORKSPACE.TRAVEL]: { policyID: string; }; - Workspace_Members: { + [SCREENS.WORKSPACE.MEMBERS]: { policyID: string; }; - Workspace_Invite: { + [SCREENS.WORKSPACE.INVITE]: { policyID: string; }; - Workspace_Invite_Message: { + [SCREENS.WORKSPACE.INVITE_MESSAGE]: { policyID: string; }; - ReimbursementAccount: { + [SCREENS.REIMBURSEMENT_ACCOUNT]: { stepToOpen: string; policyID: string; }; - GetAssistance: { + [SCREENS.GET_ASSISTANCE]: { taskID: string; }; - Settings_TwoFactorAuth: undefined; - Settings_ReportCardLostOrDamaged: undefined; - KeyboardShortcuts: undefined; + [SCREENS.SETTINGS.TWO_FACTOR_AUTH]: undefined; + [SCREENS.SETTINGS.REPORT_CARD_LOST_OR_DAMAGED]: undefined; + [SCREENS.KEYBOARD_SHORTCUTS]: undefined; }; type NewChatNavigatorParamList = { - NewChat_Root: undefined; + [SCREENS.NEW_CHAT_ROOT]: undefined; }; type SearchNavigatorParamList = { - Search_Root: undefined; + [SCREENS.SEARCH_ROOT]: undefined; }; type DetailsNavigatorParamList = { - Details_Root: { + [SCREENS.DETAILS_ROOT]: { login: string; reportID: string; }; }; type ProfileNavigatorParamList = { - Profile_Root: { + [SCREENS.PROFILE_ROOT]: { accountID: string; reportID: string; }; }; type ReportDetailsNavigatorParamList = { - Report_Details_Root: undefined; - Report_Details_Share_Code: { + [SCREENS.REPORT_DETAILS.ROOT]: undefined; + [SCREENS.REPORT_DETAILS.SHARE_CODE]: { reportID: string; }; }; type ReportSettingsNavigatorParamList = { - Report_Settings_Root: undefined; - Report_Settings_Room_Name: undefined; - Report_Settings_Notification_Preferences: undefined; - Report_Settings_Write_Capability: undefined; + [SCREENS.REPORT_SETTINGS.ROOT]: undefined; + [SCREENS.REPORT_SETTINGS.ROOM_NAME]: undefined; + [SCREENS.REPORT_SETTINGS.NOTIFICATION_PREFERENCES]: undefined; + [SCREENS.REPORT_SETTINGS.WRITE_CAPABILITY]: undefined; }; type ReportWelcomeMessageNavigatorParamList = { - Report_WelcomeMessage_Root: {reportID: string}; + [SCREENS.REPORT_WELCOME_MESSAGE_ROOT]: {reportID: string}; }; type ParticipantsNavigatorParamList = { - ReportParticipants_Root: {reportID: string}; + [SCREENS.REPORT_PARTICIPANTS_ROOT]: {reportID: string}; }; type RoomMembersNavigatorParamList = { - RoomMembers_Root: undefined; + [SCREENS.ROOM_MEMBERS_ROOT]: undefined; }; type RoomInviteNavigatorParamList = { - RoomInvite_Root: undefined; + [SCREENS.ROOM_INVITE_ROOT]: undefined; }; type MoneyRequestNavigatorParamList = { - Money_Request: undefined; - Money_Request_Amount: undefined; - Money_Request_Participants: { + [SCREENS.MONEY_REQUEST.ROOT]: undefined; + [SCREENS.MONEY_REQUEST.AMOUNT]: undefined; + [SCREENS.MONEY_REQUEST.PARTICIPANTS]: { iouType: string; reportID: string; }; - Money_Request_Confirmation: { + [SCREENS.MONEY_REQUEST.CONFIRMATION]: { iouType: string; reportID: string; }; - Money_Request_Currency: { + [SCREENS.MONEY_REQUEST.CURRENCY]: { iouType: string; reportID: string; currency: string; backTo: string; }; - Money_Request_Date: { + [SCREENS.MONEY_REQUEST.DATE]: { iouType: string; reportID: string; field: string; threadReportID: string; }; - Money_Request_Description: { + [SCREENS.MONEY_REQUEST.DESCRIPTION]: { iouType: string; reportID: string; field: string; threadReportID: string; }; - Money_Request_Category: { + [SCREENS.MONEY_REQUEST.CATEGORY]: { iouType: string; reportID: string; }; - Money_Request_Tag: { + [SCREENS.MONEY_REQUEST.TAG]: { iouType: string; reportID: string; }; - Money_Request_Merchant: { + [SCREENS.MONEY_REQUEST.MERCHANT]: { iouType: string; reportID: string; field: string; threadReportID: string; }; - IOU_Send_Enable_Payments: undefined; - IOU_Send_Add_Bank_Account: undefined; - IOU_Send_Add_Debit_Card: undefined; - Money_Request_Waypoint: { + [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: undefined; + [SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: undefined; + [SCREENS.IOU_SEND.ADD_DEBIT_CARD]: undefined; + [SCREENS.MONEY_REQUEST.WAYPOINT]: { iouType: string; transactionID: string; waypointIndex: string; threadReportID: number; }; - Money_Request_Edit_Waypoint: { + [SCREENS.MONEY_REQUEST.EDIT_WAYPOINT]: { iouType: string; transactionID: string; waypointIndex: string; threadReportID: number; }; - Money_Request_Distance: { + [SCREENS.MONEY_REQUEST.DISTANCE]: { iouType: ValueOf; reportID: string; }; - Money_Request_Receipt: { + [SCREENS.MONEY_REQUEST.RECEIPT]: { iouType: string; reportID: string; }; }; type NewTaskNavigatorParamList = { - NewTask_Root: undefined; - NewTask_TaskAssigneeSelector: undefined; - NewTask_TaskShareDestinationSelector: undefined; - NewTask_Details: undefined; - NewTask_Title: undefined; - NewTask_Description: undefined; + [SCREENS.NEW_TASK.ROOT]: undefined; + [SCREENS.NEW_TASK.TASK_ASSIGNEE_SELECTOR]: undefined; + [SCREENS.NEW_TASK.TASK_SHARE_DESTINATION_SELECTOR]: undefined; + [SCREENS.NEW_TASK.DETAILS]: undefined; + [SCREENS.NEW_TASK.TITLE]: undefined; + [SCREENS.NEW_TASK.DESCRIPTION]: undefined; }; type TeachersUniteNavigatorParamList = { [SCREENS.SAVE_THE_WORLD.ROOT]: undefined; - I_Know_A_Teacher: undefined; - Intro_School_Principal: undefined; - I_Am_A_Teacher: undefined; + [SCREENS.I_KNOW_A_TEACHER]: undefined; + [SCREENS.INTRO_SCHOOL_PRINCIPAL]: undefined; + [SCREENS.I_AM_A_TEACHER]: undefined; }; type TaskDetailsNavigatorParamList = { - Task_Title: undefined; - Task_Description: undefined; - Task_Assignee: { + [SCREENS.TASK.TITLE]: undefined; + [SCREENS.TASK.DESCRIPTION]: undefined; + [SCREENS.TASK.ASSIGNEE]: { reportID: string; }; }; type EnablePaymentsNavigatorParamList = { - EnablePayments_Root: undefined; + [SCREENS.ENABLE_PAYMENTS_ROOT]: undefined; }; type SplitDetailsNavigatorParamList = { - SplitDetails_Root: { + [SCREENS.SPLIT_DETAILS.ROOT]: { reportActionID: string; }; - SplitDetails_Edit_Request: undefined; - SplitDetails_Edit_Currency: undefined; + [SCREENS.SPLIT_DETAILS.EDIT_REQUEST]: undefined; + [SCREENS.SPLIT_DETAILS.EDIT_CURRENCY]: undefined; }; type AddPersonalBankAccountNavigatorParamList = { - AddPersonalBankAccount_Root: undefined; + [SCREENS.ADD_PERSONAL_BANK_ACCOUNT_ROOT]: undefined; }; type WalletStatementNavigatorParamList = { - WalletStatement_Root: undefined; + [SCREENS.WALLET_STATEMENT_ROOT]: undefined; }; type FlagCommentNavigatorParamList = { - FlagComment_Root: { + [SCREENS.FLAG_COMMENT_ROOT]: { reportID: string; reportActionID: string; }; }; type EditRequestNavigatorParamList = { - EditRequest_Root: { + [SCREENS.EDIT_REQUEST.ROOT]: { field: string; threadReportID: string; }; - EditRequest_Currency: undefined; + [SCREENS.EDIT_REQUEST.CURRENCY]: undefined; }; type SignInNavigatorParamList = { - SignIn_Root: undefined; + [SCREENS.SIGN_IN_ROOT]: undefined; }; type ReferralDetailsNavigatorParamList = { - Referral_Details: undefined; + [SCREENS.REFERRAL_DETAILS]: undefined; }; type PrivateNotesNavigatorParamList = { - PrivateNotes_View: { + [SCREENS.PRIVATE_NOTES.VIEW]: { reportID: string; accountID: string; }; - PrivateNotes_List: { + [SCREENS.PRIVATE_NOTES.LIST]: { reportID: string; accountID: string; }; - PrivateNotes_Edit: { + [SCREENS.PRIVATE_NOTES.EDIT]: { reportID: string; accountID: string; }; }; type RightModalNavigatorParamList = { - Settings: NavigatorScreenParams; - NewChat: NavigatorScreenParams; - Search: NavigatorScreenParams; - Details: NavigatorScreenParams; - Profile: NavigatorScreenParams; - Report_Details: NavigatorScreenParams; - Report_Settings: NavigatorScreenParams; - Report_WelcomeMessage: NavigatorScreenParams; - Participants: NavigatorScreenParams; - RoomMembers: NavigatorScreenParams; - RoomInvite: NavigatorScreenParams; - MoneyRequest: NavigatorScreenParams; - NewTask: NavigatorScreenParams; - TeachersUnite: NavigatorScreenParams; - Task_Details: NavigatorScreenParams; - EnablePayments: NavigatorScreenParams; - SplitDetails: NavigatorScreenParams; - AddPersonalBankAccount: NavigatorScreenParams; - Wallet_Statement: NavigatorScreenParams; - Flag_Comment: NavigatorScreenParams; - EditRequest: NavigatorScreenParams; - SignIn: NavigatorScreenParams; - Referral: NavigatorScreenParams; - Private_Notes: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.SETTINGS]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.NEW_CHAT]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.SEARCH]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.DETAILS]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.PROFILE]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.REPORT_DETAILS]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.REPORT_SETTINGS]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.REPORT_WELCOME_MESSAGE]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.PARTICIPANTS]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.ROOM_MEMBERS]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.ROOM_INVITE]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.MONEY_REQUEST]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.NEW_TASK]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.TEACHERS_UNITE]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.TASK_DETAILS]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.ENABLE_PAYMENTS]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.SPLIT_DETAILS]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.ADD_PERSONAL_BANK_ACCOUNT]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.WALLET_STATEMENT]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.FLAG_COMMENT]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.EDIT_REQUEST]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.SIGN_IN]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.REFERRAL]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.PRIVATE_NOTES]: NavigatorScreenParams; }; type PublicScreensParamList = { From bff05982129d30a55190c2f19a38807823e28443 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 4 Dec 2023 12:29:44 +0100 Subject: [PATCH 13/23] AuthScreens improvements --- .../Navigation/AppNavigator/AuthScreens.tsx | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index a50bae34f064..55f2ae258f5c 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -29,8 +29,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import * as OnyxTypes from '@src/types/onyx'; -import type {Timezone} from '@src/types/onyx/PersonalDetails'; -import {SelectedTimezone} from '@src/types/onyx/PersonalDetails'; +import type {SelectedTimezone, Timezone} from '@src/types/onyx/PersonalDetails'; import createCustomStackNavigator from './createCustomStackNavigator'; import defaultScreenOptions from './defaultScreenOptions'; import getRootNavigatorScreenOptions from './getRootNavigatorScreenOptions'; @@ -60,20 +59,20 @@ const loadValidateLoginPage = () => require('../../../pages/ValidateLoginPage'). const loadLogOutPreviousUserPage = () => require('../../../pages/LogOutPreviousUserPage').default as React.ComponentType; const loadConciergePage = () => require('../../../pages/ConciergePage').default as React.ComponentType; -let timezone: Timezone | null; -let currentAccountID: number; -let isLoadingApp: boolean; +let timezone: Timezone | null | undefined; +let currentAccountID: number | undefined; +let isLoadingApp: boolean | undefined; Onyx.connect({ key: ONYXKEYS.SESSION, - callback: (val) => { + callback: (value) => { // When signed out, val hasn't accountID - if (!val?.accountID) { + if (!(value && 'accountID' in value)) { timezone = null; return; } - currentAccountID = val.accountID; + currentAccountID = value.accountID; if (Navigation.isActiveRoute(ROUTES.SIGN_IN_MODAL)) { // This means sign in in RHP was successful, so we can dismiss the modal and subscribe to user events Navigation.dismissModal(); @@ -84,12 +83,12 @@ Onyx.connect({ Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, - callback: (val) => { - if (!val || timezone) { + callback: (value) => { + if (!value || timezone) { return; } - timezone = val?.[currentAccountID]?.timezone ?? {}; + timezone = value?.[currentAccountID ?? -1]?.timezone ?? {}; const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone as SelectedTimezone; // If the current timezone is different than the user's timezone, and their timezone is set to automatic @@ -106,8 +105,8 @@ Onyx.connect({ Onyx.connect({ key: ONYXKEYS.IS_LOADING_APP, - callback: (val) => { - isLoadingApp = !!val; + callback: (value) => { + isLoadingApp = !!value; }, }); @@ -126,7 +125,7 @@ const modalScreenListeners = { }, }; -function AuthScreens({isUsingMemoryOnlyKeys = null, lastUpdateIDAppliedToClient = null, session = {email: undefined}, lastOpenedPublicRoomID = null, demoInfo = null}: AuthScreensProps) { +function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, session, lastOpenedPublicRoomID, demoInfo}: AuthScreensProps) { const styles = useThemeStyles(); const {isSmallScreenWidth} = useWindowDimensions(); const screenOptions = getRootNavigatorScreenOptions(isSmallScreenWidth, styles); @@ -142,8 +141,8 @@ function AuthScreens({isUsingMemoryOnlyKeys = null, lastUpdateIDAppliedToClient const searchShortcutConfig = CONST.KEYBOARD_SHORTCUTS.SEARCH; const chatShortcutConfig = CONST.KEYBOARD_SHORTCUTS.NEW_CHAT; const currentUrl = getCurrentUrl(); - const isLoggingInAsNewUser = SessionUtils.isLoggingInAsNewUser(currentUrl, session?.email ?? ''); - const shouldGetAllData = isUsingMemoryOnlyKeys ?? SessionUtils.didUserLogInDuringSession() ?? isLoggingInAsNewUser; + const isLoggingInAsNewUser = !!session?.email && SessionUtils.isLoggingInAsNewUser(currentUrl, session.email); + const shouldGetAllData = !!isUsingMemoryOnlyKeys || SessionUtils.didUserLogInDuringSession() || isLoggingInAsNewUser; // Sign out the current user if we're transitioning with a different user const isTransitioning = currentUrl.includes(ROUTES.TRANSITION_BETWEEN_APPS); if (isLoggingInAsNewUser && isTransitioning) { From a22d4f7647f580106187564c70e294fdd00e02b6 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 4 Dec 2023 13:30:45 +0100 Subject: [PATCH 14/23] Code improvements --- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 2 +- .../AppNavigator/ModalStackNavigators.tsx | 6 +++--- .../Navigation/AppNavigator/Navigators/Overlay.tsx | 1 + .../AppNavigator/Navigators/RightModalNavigator.tsx | 6 ++++-- src/libs/Navigation/AppNavigator/PublicScreens.tsx | 1 + .../Navigation/AppNavigator/ReportScreenIDSetter.ts | 6 +++--- .../Navigation/AppNavigator/ReportScreenWrapper.tsx | 2 +- .../AppNavigator/getRootNavigatorScreenOptions.ts | 13 ++++++++----- src/styles/getModalStyles.ts | 1 - src/types/onyx/DemoInfo.ts | 1 + 10 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 55f2ae258f5c..4fbc0078689a 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -125,7 +125,7 @@ const modalScreenListeners = { }, }; -function AuthScreens({isUsingMemoryOnlyKeys, lastUpdateIDAppliedToClient, session, lastOpenedPublicRoomID, demoInfo}: AuthScreensProps) { +function AuthScreens({lastUpdateIDAppliedToClient, session, lastOpenedPublicRoomID, demoInfo, isUsingMemoryOnlyKeys = false}: AuthScreensProps) { const styles = useThemeStyles(); const {isSmallScreenWidth} = useWindowDimensions(); const screenOptions = getRootNavigatorScreenOptions(isSmallScreenWidth, styles); diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index f0289b2927bf..db587f62f493 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -1,4 +1,4 @@ -import {CardStyleInterpolators, createStackNavigator} from '@react-navigation/stack'; +import {CardStyleInterpolators, createStackNavigator, StackNavigationOptions} from '@react-navigation/stack'; import React, {useMemo} from 'react'; import useThemeStyles from '@styles/useThemeStyles'; import SCREENS from '@src/SCREENS'; @@ -10,14 +10,14 @@ type Screens = Record React.ComponentType>; * * @param screens key/value pairs where the key is the name of the screen and the value is a functon that returns the lazy-loaded component */ -function createModalStackNavigator(screens: Screens): () => React.JSX.Element { +function createModalStackNavigator(screens: Screens): React.ComponentType { const ModalStackNavigator = createStackNavigator(); function ModalStack() { const styles = useThemeStyles(); const defaultSubRouteOptions = useMemo( - () => ({ + (): StackNavigationOptions => ({ cardStyle: styles.navigationScreenCardStyle, headerShown: false, cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, diff --git a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx index 098e9a3dccf5..31eb818b60dc 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/Overlay.tsx @@ -7,6 +7,7 @@ import useThemeStyles from '@styles/useThemeStyles'; import CONST from '@src/CONST'; type OverlayProps = { + /* Callback to close the modal */ onPress: () => void; }; diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx index 104fbc29b12b..75358648be59 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx @@ -10,16 +10,18 @@ import useThemeStyles from '@styles/useThemeStyles'; import NAVIGATORS from '@src/NAVIGATORS'; import Overlay from './Overlay'; +type RightModalNavigatorProps = StackScreenProps; + const Stack = createStackNavigator(); -function RightModalNavigator(props: StackScreenProps) { +function RightModalNavigator({navigation}: RightModalNavigatorProps) { const styles = useThemeStyles(); const {isSmallScreenWidth} = useWindowDimensions(); const screenOptions = useMemo(() => RHPScreenOptions(styles), [styles]); return ( - {!isSmallScreenWidth && } + {!isSmallScreenWidth && } { // Don't update if there is a reportID in the params already - if (route?.params?.reportID ?? null) { + if (route?.params?.reportID) { App.confirmReadyToOpenApp(); return; } // If there is no reportID in route, try to find last accessed and use it for setParams - const reportID = getLastAccessedReportID(reports, !canUseDefaultRooms, policies, isFirstTimeNewExpensifyUser, reports?.params?.openOnAdminRoom ?? false); + const reportID = getLastAccessedReportID(reports, !canUseDefaultRooms, policies, isFirstTimeNewExpensifyUser, !!reports?.params?.openOnAdminRoom); // It's possible that reports aren't fully loaded yet // in that case the reportID is undefined diff --git a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx index b0be8eae82ce..20922fd785ce 100644 --- a/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx +++ b/src/libs/Navigation/AppNavigator/ReportScreenWrapper.tsx @@ -12,7 +12,7 @@ function ReportScreenWrapper({route, navigation}: ReportScreenWrapperProps) { // until the reportID is loaded and set in the route param return ( <> - {/* @ts-expect-error Error will be resolved after ReportScreen migration */} + {/* @ts-expect-error Error will be resolved after ReportScreen migration to TypeScript */} ; + const commonScreenOptions: StackNavigationOptions = { headerShown: false, gestureDirection: 'horizontal', @@ -13,7 +15,7 @@ const commonScreenOptions: StackNavigationOptions = { animationTypeForReplace: 'push', }; -export default (isSmallScreenWidth: boolean, themeStyles: typeof styles) => ({ +export default (isSmallScreenWidth: boolean, themeStyles: typeof styles): ScreenOptions => ({ rightModalNavigator: { ...commonScreenOptions, cardStyleInterpolator: (props: StackCardInterpolationProps) => modalCardStyleInterpolator(isSmallScreenWidth, false, props), @@ -29,7 +31,7 @@ export default (isSmallScreenWidth: boolean, themeStyles: typeof styles) => ({ // Excess space should be on the left so we need to position from right. right: 0, }, - } as StackNavigationOptions, + }, homeScreen: { title: CONFIG.SITE_TITLE, @@ -44,7 +46,8 @@ export default (isSmallScreenWidth: boolean, themeStyles: typeof styles) => ({ transform: [{translateX: isSmallScreenWidth ? 0 : -variables.sideBarWidth}], ...(isSmallScreenWidth ? {} : themeStyles.borderRight), }, - } as StackNavigationOptions, + }, + fullScreen: { ...commonScreenOptions, cardStyleInterpolator: (props: StackCardInterpolationProps) => modalCardStyleInterpolator(isSmallScreenWidth, true, props), @@ -54,7 +57,7 @@ export default (isSmallScreenWidth: boolean, themeStyles: typeof styles) => ({ // This is necessary to cover whole screen. Including translated sidebar. marginLeft: isSmallScreenWidth ? 0 : -variables.sideBarWidth, }, - } as StackNavigationOptions, + }, centralPaneNavigator: { title: CONFIG.SITE_TITLE, @@ -66,5 +69,5 @@ export default (isSmallScreenWidth: boolean, themeStyles: typeof styles) => ({ ...getNavigationModalCardStyle(), paddingRight: isSmallScreenWidth ? 0 : variables.sideBarWidth, }, - } as StackNavigationOptions, + }, }); diff --git a/src/styles/getModalStyles.ts b/src/styles/getModalStyles.ts index 0bb0cdc6452a..1c28de3bb5e2 100644 --- a/src/styles/getModalStyles.ts +++ b/src/styles/getModalStyles.ts @@ -269,4 +269,3 @@ export default function getModalStyles( shouldAddTopSafeAreaPadding, }; } -export type {WindowDimensions}; diff --git a/src/types/onyx/DemoInfo.ts b/src/types/onyx/DemoInfo.ts index 0e7a09f93983..dcd7efc44d8d 100644 --- a/src/types/onyx/DemoInfo.ts +++ b/src/types/onyx/DemoInfo.ts @@ -1,5 +1,6 @@ type DemoInfo = { money2020: { + /** If the beginning demo should be shown */ isBeginningDemo?: boolean; }; }; From a44f5cd3207f678d6e5c705039f391f2230c767d Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 4 Dec 2023 14:12:55 +0100 Subject: [PATCH 15/23] Add empty lines to improve code readability --- src/SCREENS.ts | 30 ++++++++++--------- .../CustomRouter.ts | 1 + 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 3072b534f744..91ebc6f030ea 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -27,11 +27,6 @@ const SCREENS = { DISPLAY_NAME: 'Settings_Display_Name', TIMEZONE: 'Settings_Timezone', TIMEZONE_SELECT: 'Settings_Timezone_Select', - PERSONAL_DETAILS_INITIAL: 'Settings_PersonalDetails_Initial', - PERSONAL_DETAILS_LEGAL_NAME: 'Settings_PersonalDetails_LegalName', - PERSONAL_DETAILS_DATE_OF_BIRTH: 'Settings_PersonalDetails_DateOfBirth', - PERSONAL_DETAILS_ADDRESS: 'Settings_PersonalDetails_Address', - PERSONAL_DETAILS_ADDRESS_COUNTRY: 'Settings_PersonalDetails_Address_Country', CONTACT_METHODS: 'Settings_ContactMethods', CONTACT_METHOD_DETAILS: 'Settings_ContactMethodDetails', NEW_CONTACT_METHOD: 'Settings_NewContactMethod', @@ -39,6 +34,13 @@ const SCREENS = { ABOUT: 'Settings_About', APP_DOWNLOAD_LINKS: 'Settings_App_Download_Links', LOUNGE_ACCESS: 'Settings_Lounge_Access', + + PERSONAL_DETAILS_INITIAL: 'Settings_PersonalDetails_Initial', + PERSONAL_DETAILS_LEGAL_NAME: 'Settings_PersonalDetails_LegalName', + PERSONAL_DETAILS_DATE_OF_BIRTH: 'Settings_PersonalDetails_DateOfBirth', + PERSONAL_DETAILS_ADDRESS: 'Settings_PersonalDetails_Address', + PERSONAL_DETAILS_ADDRESS_COUNTRY: 'Settings_PersonalDetails_Address_Country', + WALLET: 'Settings_Wallet', WALLET_DOMAIN_CARD: 'Settings_Wallet_DomainCard', WALLET_CARD_GET_PHYSICAL: { @@ -53,6 +55,7 @@ const SCREENS = { WALLET_CARD_ACTIVATE: 'Settings_Wallet_Card_Activate', WALLET_REPORT_VIRTUAL_CARD_FRAUD: 'Settings_Wallet_ReportVirtualCardFraud', WALLET_CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS: 'Settings_Wallet_Cards_Digital_Details_Update_Address', + ADD_DEBIT_CARD: 'Settings_Add_Debit_Card', ADD_BANK_ACCOUNT: 'Settings_Add_Bank_Account', PREFERENCES_PRIORITY_MODE: 'Settings_Preferences_PriorityMode', @@ -182,14 +185,6 @@ const SCREENS = { REIMBURSEMENT_ACCOUNT_ROOT: 'Reimbursement_Account_Root', WALLET_STATEMENT_ROOT: 'WalletStatement_Root', SIGN_IN_ROOT: 'SignIn_Root', - REFERRAL_DETAILS: 'Referral_Details', - - SPLIT_DETAILS: { - ROOT: 'SplitDetails_Root', - EDIT_REQUEST: 'SplitDetails_Edit_Request', - EDIT_CURRENCY: 'SplitDetails_Edit_Currency', - }, - DETAILS_ROOT: 'Details_Root', PROFILE_ROOT: 'Profile_Root', REPORT_WELCOME_MESSAGE_ROOT: 'Report_WelcomeMessage_Root', @@ -199,9 +194,16 @@ const SCREENS = { SEARCH_ROOT: 'Search_Root', NEW_CHAT_ROOT: 'NewChat_Root', FLAG_COMMENT_ROOT: 'FlagComment_Root', + + SPLIT_DETAILS: { + ROOT: 'SplitDetails_Root', + EDIT_REQUEST: 'SplitDetails_Edit_Request', + EDIT_CURRENCY: 'SplitDetails_Edit_Currency', + }, + REIMBURSEMENT_ACCOUNT: 'ReimbursementAccount', GET_ASSISTANCE: 'GetAssistance', - + REFERRAL_DETAILS: 'Referral_Details', KEYBOARD_SHORTCUTS: 'KeyboardShortcuts', } as const; diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts index c7fdd59329d0..3690182108d3 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts @@ -18,6 +18,7 @@ const getTopMostReportIDFromRHP = (state: State): string => { if (!state) { return ''; } + const topmostRightPane = state.routes.filter((route) => route.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR).at(-1); if (topmostRightPane?.state) { From 274073d76e5782bcf49ce4b17cc892697e051faf Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 4 Dec 2023 14:49:33 +0100 Subject: [PATCH 16/23] Update createModalStackNavigator typing --- .../AppNavigator/ModalStackNavigators.tsx | 82 +++++++++++++------ src/libs/Navigation/types.ts | 32 ++++++++ 2 files changed, 87 insertions(+), 27 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index db587f62f493..a12f6405da45 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -1,5 +1,33 @@ +import {ParamListBase} from '@react-navigation/routers'; import {CardStyleInterpolators, createStackNavigator, StackNavigationOptions} from '@react-navigation/stack'; import React, {useMemo} from 'react'; +import type { + AddPersonalBankAccountNavigatorParamList, + DetailsNavigatorParamList, + EditRequestNavigatorParamList, + EnablePaymentsNavigatorParamList, + FlagCommentNavigatorParamList, + MoneyRequestNavigatorParamList, + NewChatNavigatorParamList, + NewTaskNavigatorParamList, + ParticipantsNavigatorParamList, + PrivateNotesNavigatorParamList, + ProfileNavigatorParamList, + ReferralDetailsNavigatorParamList, + ReimbursementAccountNavigatorParamList, + ReportDetailsNavigatorParamList, + ReportSettingsNavigatorParamList, + ReportWelcomeMessageNavigatorParamList, + RoomInviteNavigatorParamList, + RoomMembersNavigatorParamList, + SearchNavigatorParamList, + SettingsNavigatorParamList, + SignInNavigatorParamList, + SplitDetailsNavigatorParamList, + TaskDetailsNavigatorParamList, + TeachersUniteNavigatorParamList, + WalletStatementNavigatorParamList, +} from '@navigation/types'; import useThemeStyles from '@styles/useThemeStyles'; import SCREENS from '@src/SCREENS'; @@ -10,8 +38,8 @@ type Screens = Record React.ComponentType>; * * @param screens key/value pairs where the key is the name of the screen and the value is a functon that returns the lazy-loaded component */ -function createModalStackNavigator(screens: Screens): React.ComponentType { - const ModalStackNavigator = createStackNavigator(); +function createModalStackNavigator(screens: Screens): React.ComponentType { + const ModalStackNavigator = createStackNavigator(); function ModalStack() { const styles = useThemeStyles(); @@ -43,7 +71,7 @@ function createModalStackNavigator(screens: Screens): React.ComponentType { return ModalStack; } -const MoneyRequestModalStackNavigator = createModalStackNavigator({ +const MoneyRequestModalStackNavigator = createModalStackNavigator({ [SCREENS.MONEY_REQUEST.ROOT]: () => require('../../../pages/iou/MoneyRequestSelectorPage').default as React.ComponentType, [SCREENS.MONEY_REQUEST.AMOUNT]: () => require('../../../pages/iou/steps/NewRequestAmountPage').default as React.ComponentType, [SCREENS.MONEY_REQUEST.PARTICIPANTS]: () => require('../../../pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage').default as React.ComponentType, @@ -63,63 +91,63 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator({ [SCREENS.MONEY_REQUEST.RECEIPT]: () => require('../../../pages/EditRequestReceiptPage').default as React.ComponentType, }); -const SplitDetailsModalStackNavigator = createModalStackNavigator({ +const SplitDetailsModalStackNavigator = createModalStackNavigator({ [SCREENS.SPLIT_DETAILS.ROOT]: () => require('../../../pages/iou/SplitBillDetailsPage').default as React.ComponentType, [SCREENS.SPLIT_DETAILS.EDIT_REQUEST]: () => require('../../../pages/EditSplitBillPage').default as React.ComponentType, [SCREENS.SPLIT_DETAILS.EDIT_CURRENCY]: () => require('../../../pages/iou/IOUCurrencySelection').default as React.ComponentType, }); -const DetailsModalStackNavigator = createModalStackNavigator({ +const DetailsModalStackNavigator = createModalStackNavigator({ [SCREENS.DETAILS_ROOT]: () => require('../../../pages/DetailsPage').default as React.ComponentType, }); -const ProfileModalStackNavigator = createModalStackNavigator({ +const ProfileModalStackNavigator = createModalStackNavigator({ [SCREENS.PROFILE_ROOT]: () => require('../../../pages/ProfilePage').default as React.ComponentType, }); -const ReportDetailsModalStackNavigator = createModalStackNavigator({ +const ReportDetailsModalStackNavigator = createModalStackNavigator({ [SCREENS.REPORT_DETAILS.ROOT]: () => require('../../../pages/ReportDetailsPage').default as React.ComponentType, [SCREENS.REPORT_DETAILS.SHARE_CODE]: () => require('../../../pages/home/report/ReportDetailsShareCodePage').default as React.ComponentType, }); -const ReportSettingsModalStackNavigator = createModalStackNavigator({ +const ReportSettingsModalStackNavigator = createModalStackNavigator({ [SCREENS.REPORT_SETTINGS.ROOT]: () => require('../../../pages/settings/Report/ReportSettingsPage').default as React.ComponentType, [SCREENS.REPORT_SETTINGS.ROOM_NAME]: () => require('../../../pages/settings/Report/RoomNamePage').default as React.ComponentType, [SCREENS.REPORT_SETTINGS.NOTIFICATION_PREFERENCES]: () => require('../../../pages/settings/Report/NotificationPreferencePage').default as React.ComponentType, [SCREENS.REPORT_SETTINGS.WRITE_CAPABILITY]: () => require('../../../pages/settings/Report/WriteCapabilityPage').default as React.ComponentType, }); -const TaskModalStackNavigator = createModalStackNavigator({ +const TaskModalStackNavigator = createModalStackNavigator({ [SCREENS.TASK.TITLE]: () => require('../../../pages/tasks/TaskTitlePage').default as React.ComponentType, [SCREENS.TASK.DESCRIPTION]: () => require('../../../pages/tasks/TaskDescriptionPage').default as React.ComponentType, [SCREENS.TASK.ASSIGNEE]: () => require('../../../pages/tasks/TaskAssigneeSelectorModal').default as React.ComponentType, }); -const ReportWelcomeMessageModalStackNavigator = createModalStackNavigator({ +const ReportWelcomeMessageModalStackNavigator = createModalStackNavigator({ [SCREENS.REPORT_WELCOME_MESSAGE_ROOT]: () => require('../../../pages/ReportWelcomeMessagePage').default as React.ComponentType, }); -const ReportParticipantsModalStackNavigator = createModalStackNavigator({ +const ReportParticipantsModalStackNavigator = createModalStackNavigator({ [SCREENS.REPORT_PARTICIPANTS_ROOT]: () => require('../../../pages/ReportParticipantsPage').default as React.ComponentType, }); -const RoomMembersModalStackNavigator = createModalStackNavigator({ +const RoomMembersModalStackNavigator = createModalStackNavigator({ [SCREENS.ROOM_MEMBERS_ROOT]: () => require('../../../pages/RoomMembersPage').default as React.ComponentType, }); -const RoomInviteModalStackNavigator = createModalStackNavigator({ +const RoomInviteModalStackNavigator = createModalStackNavigator({ [SCREENS.ROOM_INVITE_ROOT]: () => require('../../../pages/RoomInvitePage').default as React.ComponentType, }); -const SearchModalStackNavigator = createModalStackNavigator({ +const SearchModalStackNavigator = createModalStackNavigator({ [SCREENS.SEARCH_ROOT]: () => require('../../../pages/SearchPage').default as React.ComponentType, }); -const NewChatModalStackNavigator = createModalStackNavigator({ +const NewChatModalStackNavigator = createModalStackNavigator({ [SCREENS.NEW_CHAT_ROOT]: () => require('../../../pages/NewChatSelectorPage').default as React.ComponentType, }); -const NewTaskModalStackNavigator = createModalStackNavigator({ +const NewTaskModalStackNavigator = createModalStackNavigator({ [SCREENS.NEW_TASK.ROOT]: () => require('../../../pages/tasks/NewTaskPage').default as React.ComponentType, [SCREENS.NEW_TASK.TASK_ASSIGNEE_SELECTOR]: () => require('../../../pages/tasks/TaskAssigneeSelectorModal').default as React.ComponentType, [SCREENS.NEW_TASK.TASK_SHARE_DESTINATION_SELECTOR]: () => require('../../../pages/tasks/TaskShareDestinationSelectorModal').default as React.ComponentType, @@ -128,14 +156,14 @@ const NewTaskModalStackNavigator = createModalStackNavigator({ [SCREENS.NEW_TASK.DESCRIPTION]: () => require('../../../pages/tasks/NewTaskDescriptionPage').default as React.ComponentType, }); -const NewTeachersUniteNavigator = createModalStackNavigator({ +const NewTeachersUniteNavigator = createModalStackNavigator({ [SCREENS.SAVE_THE_WORLD.ROOT]: () => require('../../../pages/TeachersUnite/SaveTheWorldPage').default as React.ComponentType, [SCREENS.I_KNOW_A_TEACHER]: () => require('../../../pages/TeachersUnite/KnowATeacherPage').default as React.ComponentType, [SCREENS.INTRO_SCHOOL_PRINCIPAL]: () => require('../../../pages/TeachersUnite/ImTeacherPage').default as React.ComponentType, [SCREENS.I_AM_A_TEACHER]: () => require('../../../pages/TeachersUnite/ImTeacherPage').default as React.ComponentType, }); -const SettingsModalStackNavigator = createModalStackNavigator({ +const SettingsModalStackNavigator = createModalStackNavigator({ [SCREENS.SETTINGS.ROOT]: () => require('../../../pages/settings/InitialSettingsPage').default as React.ComponentType, [SCREENS.SETTINGS.SHARE_CODE]: () => require('../../../pages/ShareCodePage').default as React.ComponentType, [SCREENS.SETTINGS.WORKSPACES]: () => require('../../../pages/workspace/WorkspacesListPage').default as React.ComponentType, @@ -197,42 +225,42 @@ const SettingsModalStackNavigator = createModalStackNavigator({ [SCREENS.KEYBOARD_SHORTCUTS]: () => require('../../../pages/KeyboardShortcutsPage').default as React.ComponentType, }); -const EnablePaymentsStackNavigator = createModalStackNavigator({ +const EnablePaymentsStackNavigator = createModalStackNavigator({ [SCREENS.ENABLE_PAYMENTS_ROOT]: () => require('../../../pages/EnablePayments/EnablePaymentsPage').default as React.ComponentType, }); -const AddPersonalBankAccountModalStackNavigator = createModalStackNavigator({ +const AddPersonalBankAccountModalStackNavigator = createModalStackNavigator({ [SCREENS.ADD_PERSONAL_BANK_ACCOUNT_ROOT]: () => require('../../../pages/AddPersonalBankAccountPage').default as React.ComponentType, }); -const ReimbursementAccountModalStackNavigator = createModalStackNavigator({ +const ReimbursementAccountModalStackNavigator = createModalStackNavigator({ [SCREENS.REIMBURSEMENT_ACCOUNT_ROOT]: () => require('../../../pages/ReimbursementAccount/ReimbursementAccountPage').default as React.ComponentType, }); -const WalletStatementStackNavigator = createModalStackNavigator({ +const WalletStatementStackNavigator = createModalStackNavigator({ [SCREENS.WALLET_STATEMENT_ROOT]: () => require('../../../pages/wallet/WalletStatementPage').default as React.ComponentType, }); -const FlagCommentStackNavigator = createModalStackNavigator({ +const FlagCommentStackNavigator = createModalStackNavigator({ [SCREENS.FLAG_COMMENT_ROOT]: () => require('../../../pages/FlagCommentPage').default as React.ComponentType, }); -const EditRequestStackNavigator = createModalStackNavigator({ +const EditRequestStackNavigator = createModalStackNavigator({ [SCREENS.EDIT_REQUEST.ROOT]: () => require('../../../pages/EditRequestPage').default as React.ComponentType, [SCREENS.EDIT_REQUEST.CURRENCY]: () => require('../../../pages/iou/IOUCurrencySelection').default as React.ComponentType, }); -const PrivateNotesModalStackNavigator = createModalStackNavigator({ +const PrivateNotesModalStackNavigator = createModalStackNavigator({ [SCREENS.PRIVATE_NOTES.VIEW]: () => require('../../../pages/PrivateNotes/PrivateNotesViewPage').default as React.ComponentType, [SCREENS.PRIVATE_NOTES.LIST]: () => require('../../../pages/PrivateNotes/PrivateNotesListPage').default as React.ComponentType, [SCREENS.PRIVATE_NOTES.EDIT]: () => require('../../../pages/PrivateNotes/PrivateNotesEditPage').default as React.ComponentType, }); -const SignInModalStackNavigator = createModalStackNavigator({ +const SignInModalStackNavigator = createModalStackNavigator({ [SCREENS.SIGN_IN_ROOT]: () => require('../../../pages/signin/SignInModal').default as React.ComponentType, }); -const ReferralModalStackNavigator = createModalStackNavigator({ +const ReferralModalStackNavigator = createModalStackNavigator({ [SCREENS.REFERRAL_DETAILS]: () => require('../../../pages/ReferralDetailsPage').default as React.ComponentType, }); diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index c5eac46f8ffa..7aa5bb32a4e4 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -283,6 +283,13 @@ type AddPersonalBankAccountNavigatorParamList = { [SCREENS.ADD_PERSONAL_BANK_ACCOUNT_ROOT]: undefined; }; +type ReimbursementAccountNavigatorParamList = { + [SCREENS.REIMBURSEMENT_ACCOUNT_ROOT]: { + stepToOpen: string; + policyID: string; + }; +}; + type WalletStatementNavigatorParamList = { [SCREENS.WALLET_STATEMENT_ROOT]: undefined; }; @@ -416,4 +423,29 @@ export type { AuthScreensParamList, RightModalNavigatorParamList, PublicScreensParamList, + MoneyRequestNavigatorParamList, + SplitDetailsNavigatorParamList, + DetailsNavigatorParamList, + ProfileNavigatorParamList, + ReportDetailsNavigatorParamList, + ReportSettingsNavigatorParamList, + TaskDetailsNavigatorParamList, + ReportWelcomeMessageNavigatorParamList, + ParticipantsNavigatorParamList, + RoomMembersNavigatorParamList, + RoomInviteNavigatorParamList, + SearchNavigatorParamList, + NewChatNavigatorParamList, + NewTaskNavigatorParamList, + TeachersUniteNavigatorParamList, + SettingsNavigatorParamList, + EnablePaymentsNavigatorParamList, + AddPersonalBankAccountNavigatorParamList, + WalletStatementNavigatorParamList, + FlagCommentNavigatorParamList, + EditRequestNavigatorParamList, + PrivateNotesNavigatorParamList, + SignInNavigatorParamList, + ReferralDetailsNavigatorParamList, + ReimbursementAccountNavigatorParamList, }; From 18e25a51a1907f1e34c3667e4cea635714c7c2a7 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 4 Dec 2023 16:31:17 +0100 Subject: [PATCH 17/23] Remove extra comments, get rid of ts-expect-error --- .../createCustomStackNavigator/CustomRouter.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts index 3690182108d3..550f980c4fa3 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts @@ -6,14 +6,8 @@ import type {ResponsiveStackNavigatorRouterOptions} from './types'; type State = NavigationState | PartialState; -/** - * @param state - react-navigation state - */ const isAtLeastOneCentralPaneNavigatorInState = (state: State): boolean => !!state.routes.find((route) => route.name === NAVIGATORS.CENTRAL_PANE_NAVIGATOR); -/** - * @param state - react-navigation state - */ const getTopMostReportIDFromRHP = (state: State): string => { if (!state) { return ''; @@ -59,9 +53,8 @@ const addCentralPaneNavigatorRoute = (state: State) => { }, }; state.routes.splice(1, 0, centralPaneNavigatorRoute); - // @ts-expect-error Updating read only property - // noinspection JSConstantReassignment - state.index = state.routes.length - 1; // eslint-disable-line + // eslint-disable-next-line no-param-reassign, @typescript-eslint/non-nullable-type-assertion-style + (state.index as number) = state.routes.length - 1; }; function CustomRouter(options: ResponsiveStackNavigatorRouterOptions) { @@ -74,9 +67,8 @@ function CustomRouter(options: ResponsiveStackNavigatorRouterOptions) { if (!isAtLeastOneCentralPaneNavigatorInState(partialState) && !options.getIsSmallScreenWidth()) { // If we added a route we need to make sure that the state.stale is true to generate new key for this route - // @ts-expect-error Updating read only property - // noinspection JSConstantReassignment - partialState.stale = true; // eslint-disable-line + // eslint-disable-next-line no-param-reassign + (partialState.stale as boolean) = true; addCentralPaneNavigatorRoute(partialState); } const state = stackRouter.getRehydratedState(partialState, {routeNames, routeParamList, routeGetIdList}); From 371860f83a4fb0a3b86032c9ecbd2b822830d815 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 4 Dec 2023 17:50:50 +0100 Subject: [PATCH 18/23] Update NAVIGATION.md file and commented code --- contributingGuides/NAVIGATION.md | 10 +++++----- .../Navigation/AppNavigator/ModalStackNavigators.tsx | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contributingGuides/NAVIGATION.md b/contributingGuides/NAVIGATION.md index 32d3919efbe4..8467b97c29fb 100644 --- a/contributingGuides/NAVIGATION.md +++ b/contributingGuides/NAVIGATION.md @@ -1,6 +1,6 @@ # Overview -The navigation in the App consists of a top-level Stack Navigator (called `RootStack`) with each of its `Screen` components handling different high-level flow. All those flows can be seen in `AuthScreens.js` file. +The navigation in the App consists of a top-level Stack Navigator (called `RootStack`) with each of its `Screen` components handling different high-level flow. All those flows can be seen in `AuthScreens.tsx` file. ## Terminology @@ -20,11 +20,11 @@ Navigation Actions - User actions correspond to resulting navigation actions tha ## Adding RHP flows -Most of the time, if you want to add some of the flows concerning one of your reports, e.g. `Money Request` from a user, you will most probably use `RightModalNavigator.js` and `ModalStackNavigators.js` file: +Most of the time, if you want to add some of the flows concerning one of your reports, e.g. `Money Request` from a user, you will most probably use `RightModalNavigator.tsx` and `ModalStackNavigators.tsx` file: -- Since each of those flows is kind of a modal stack, if you want to add a page to the existing flow, you should just add a page to the correct stack in `ModalStackNavigators.js`. +- Since each of those flows is kind of a modal stack, if you want to add a page to the existing flow, you should just add a page to the correct stack in `ModalStackNavigators.tsx`. -- If you want to create new flow, add a `Screen` in `RightModalNavigator.js` and make new modal in `ModalStackNavigators.js` with chosen pages. +- If you want to create new flow, add a `Screen` in `RightModalNavigator.tsx` and make new modal in `ModalStackNavigators.tsx` with chosen pages. When creating RHP flows, you have to remember a couple things: @@ -196,4 +196,4 @@ The action for the first step created with `getMinimalAction` looks like this: ``` ### Deeplinking -There is no minimal action for deeplinking directly to the `Profile` screen. But because the `Settings_root` is not on the stack, pressing UP will reset the params for navigators to the correct ones. \ No newline at end of file +There is no minimal action for deeplinking directly to the `Profile` screen. But because the `Settings_root` is not on the stack, pressing UP will reset the params for navigators to the correct ones. diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index a12f6405da45..a440b5d211ea 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -184,7 +184,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../pages/settings/Preferences/PriorityModePage').default as React.ComponentType, [SCREENS.SETTINGS.PREFERENCES_LANGUAGE]: () => require('../../../pages/settings/Preferences/LanguagePage').default as React.ComponentType, // Will be uncommented as part of https://github.com/Expensify/App/issues/21670 - // Settings_Preferences_Theme: () => require('../../../pages/settings/Preferences/ThemePage').default as React.ComponentType, + // [SCREENS.SETTINGS.PREFERENCES_THEME]: () => require('../../../pages/settings/Preferences/ThemePage').default as React.ComponentType, [SCREENS.SETTINGS.CLOSE]: () => require('../../../pages/settings/Security/CloseAccountPage').default as React.ComponentType, [SCREENS.SETTINGS.SECURITY]: () => require('../../../pages/settings/Security/SecuritySettingsPage').default as React.ComponentType, [SCREENS.SETTINGS.ABOUT]: () => require('../../../pages/settings/AboutPage/AboutPage').default as React.ComponentType, From 5fbf995f67400bf6da217af1ec1e533fd1ac706c Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 5 Dec 2023 12:52:10 +0100 Subject: [PATCH 19/23] Remove old screen options; add default values to params --- .../Navigation/AppNavigator/AuthScreens.tsx | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 4fbc0078689a..96a9a5a81a4a 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -59,9 +59,9 @@ const loadValidateLoginPage = () => require('../../../pages/ValidateLoginPage'). const loadLogOutPreviousUserPage = () => require('../../../pages/LogOutPreviousUserPage').default as React.ComponentType; const loadConciergePage = () => require('../../../pages/ConciergePage').default as React.ComponentType; -let timezone: Timezone | null | undefined; -let currentAccountID: number | undefined; -let isLoadingApp: boolean | undefined; +let timezone: Timezone | null; +let currentAccountID = -1; +let isLoadingApp = false; Onyx.connect({ key: ONYXKEYS.SESSION, @@ -72,7 +72,10 @@ Onyx.connect({ return; } - currentAccountID = value.accountID; + if (value.accountID) { + currentAccountID = value.accountID; + } + if (Navigation.isActiveRoute(ROUTES.SIGN_IN_MODAL)) { // This means sign in in RHP was successful, so we can dismiss the modal and subscribe to user events Navigation.dismissModal(); @@ -88,7 +91,7 @@ Onyx.connect({ return; } - timezone = value?.[currentAccountID ?? -1]?.timezone ?? {}; + timezone = value?.[currentAccountID]?.timezone ?? {}; const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone as SelectedTimezone; // If the current timezone is different than the user's timezone, and their timezone is set to automatic @@ -246,13 +249,7 @@ function AuthScreens({lastUpdateIDAppliedToClient, session, lastOpenedPublicRoom return ( - + Date: Tue, 5 Dec 2023 13:15:55 +0100 Subject: [PATCH 20/23] Update ModalStackNavigator typing --- src/SCREENS.ts | 4 ++++ src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 91ebc6f030ea..c0d3df82e228 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -2,6 +2,7 @@ * This is a file containing constants for all of the screen names. In most cases, we should use the routes for * navigation. But there are situations where we may need to access screen names directly. */ +import DeepValueOf from './types/utils/DeepValueOf'; const PROTECTED_SCREENS = { HOME: 'Home', @@ -207,5 +208,8 @@ const SCREENS = { KEYBOARD_SHORTCUTS: 'KeyboardShortcuts', } as const; +type Screen = DeepValueOf; + export default SCREENS; export {PROTECTED_SCREENS}; +export type {Screen}; diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index a440b5d211ea..163423036362 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -30,8 +30,9 @@ import type { } from '@navigation/types'; import useThemeStyles from '@styles/useThemeStyles'; import SCREENS from '@src/SCREENS'; +import type {Screen} from '@src/SCREENS'; -type Screens = Record React.ComponentType>; +type Screens = Partial React.ComponentType>>; /** * Create a modal stack navigator with an array of sub-screens. @@ -55,11 +56,11 @@ function createModalStackNavigator(screens: return ( - {Object.keys(screens).map((name) => ( + {Object.keys(screens as Required).map((name) => ( )[name as Screen]} /> ))} From 0fc1b1e739d1f2f83583625f74a2770f22579864 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 5 Dec 2023 13:18:29 +0100 Subject: [PATCH 21/23] Update reconnectApp function typing --- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 4 ++-- src/libs/actions/App.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 96a9a5a81a4a..b9d01d8cefac 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -158,7 +158,7 @@ function AuthScreens({lastUpdateIDAppliedToClient, session, lastOpenedPublicRoom if (isLoadingApp) { App.openApp(); } else { - App.reconnectApp(lastUpdateIDAppliedToClient ?? 0); + App.reconnectApp(lastUpdateIDAppliedToClient); } }); PusherConnectionManager.init(); @@ -178,7 +178,7 @@ function AuthScreens({lastUpdateIDAppliedToClient, session, lastOpenedPublicRoom if (shouldGetAllData) { App.openApp(); } else { - App.reconnectApp(lastUpdateIDAppliedToClient ?? 0); + App.reconnectApp(lastUpdateIDAppliedToClient); } App.setUpPoliciesAndNavigate(session); diff --git a/src/libs/actions/App.ts b/src/libs/actions/App.ts index 16b6d474b54d..ec43d4358134 100644 --- a/src/libs/actions/App.ts +++ b/src/libs/actions/App.ts @@ -228,7 +228,7 @@ function openApp() { * Fetches data when the app reconnects to the network * @param [updateIDFrom] the ID of the Onyx update that we want to start fetching from */ -function reconnectApp(updateIDFrom = 0) { +function reconnectApp(updateIDFrom: OnyxEntry = 0) { console.debug(`[OnyxUpdates] App reconnecting with updateIDFrom: ${updateIDFrom}`); getPolicyParamsForOpenOrReconnect().then((policyParams) => { type ReconnectParams = { From d666c0d4573f4ce0f5eae39d28eed312a11181d9 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 5 Dec 2023 14:03:12 +0100 Subject: [PATCH 22/23] Minor code improvement --- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index b9d01d8cefac..71b9998fc813 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -72,9 +72,7 @@ Onyx.connect({ return; } - if (value.accountID) { - currentAccountID = value.accountID; - } + currentAccountID = value.accountID ?? -1; if (Navigation.isActiveRoute(ROUTES.SIGN_IN_MODAL)) { // This means sign in in RHP was successful, so we can dismiss the modal and subscribe to user events From 1d6a804e384b23da2683eb42f52b87d2406fc5c0 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 6 Dec 2023 11:25:19 +0100 Subject: [PATCH 23/23] Fix TS issue --- .../AppNavigator/createCustomStackNavigator/types.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/types.ts b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/types.ts index a6135e8365ad..707a0ff4498d 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/types.ts +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/types.ts @@ -5,9 +5,7 @@ type ResponsiveStackNavigatorConfig = { isSmallScreenWidth: boolean; }; -type ResponsiveStackNavigatorRouterOptions = StackRouterOptions & { - getIsSmallScreenWidth: () => boolean; -}; +type ResponsiveStackNavigatorRouterOptions = StackRouterOptions; type ResponsiveStackNavigatorProps = DefaultNavigatorOptions, StackNavigationOptions, StackNavigationEventMap> & ResponsiveStackNavigatorConfig;