diff --git a/src/components/CurrencySelectionList/index.tsx b/src/components/CurrencySelectionList/index.tsx index 361d8214032..02ed11afa7d 100644 --- a/src/components/CurrencySelectionList/index.tsx +++ b/src/components/CurrencySelectionList/index.tsx @@ -48,6 +48,7 @@ function CurrencySelectionList({searchInputLabel, initiallySelectedCurrencyCode, textInputValue={searchValue} onChangeText={setSearchValue} onSelectRow={onSelect} + shouldDebounceRowSelect headerMessage={headerMessage} initiallyFocusedOptionKey={initiallySelectedCurrencyCode} showScrollIndicator diff --git a/src/components/MenuItemGroup.tsx b/src/components/MenuItemGroup.tsx index 8dc8586028d..ed34778dd94 100644 --- a/src/components/MenuItemGroup.tsx +++ b/src/components/MenuItemGroup.tsx @@ -5,7 +5,7 @@ import useWaitForNavigation from '@hooks/useWaitForNavigation'; type MenuItemGroupContextProps = { isExecuting: boolean; - singleExecution: (action?: Action | undefined) => (...params: T) => void; + singleExecution: (action: Action) => (...params: T) => void; waitForNavigate: ReturnType; }; diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 65a83090a05..76418a8675a 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -1237,6 +1237,7 @@ function MoneyRequestConfirmationList({ sections={sections} ListItem={UserListItem} onSelectRow={navigateToReportOrUserDetail} + shouldDebounceRowSelect canSelectMultiple={false} shouldPreventDefaultFocusOnSelectRow footerContent={footerContent} diff --git a/src/components/Search.tsx b/src/components/Search.tsx index 27e87017bfe..6f3bcacf102 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -86,6 +86,7 @@ function Search({query, policyIDs}: SearchProps) { onSelectRow={(item) => { openReport(item.transactionThreadReportID); }} + shouldDebounceRowSelect shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]} containerStyle={[styles.pv0]} diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 5453590b933..c142aae9675 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -1,4 +1,5 @@ import {useFocusEffect, useIsFocused} from '@react-navigation/native'; +import lodashDebounce from 'lodash/debounce'; import isEmpty from 'lodash/isEmpty'; import type {ForwardedRef} from 'react'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; @@ -35,6 +36,7 @@ function BaseSelectionList( ListItem, canSelectMultiple = false, onSelectRow, + shouldDebounceRowSelect = false, onCheckboxPress, onSelectAll, onDismissError, @@ -252,6 +254,9 @@ function BaseSelectionList( isFocused, }); + // eslint-disable-next-line react-hooks/exhaustive-deps + const debouncedOnSelectRow = useCallback(lodashDebounce(onSelectRow, 1000, {leading: true}), [onSelectRow]); + /** * Logic to run when a row is selected, either with click/press or keyboard hotkeys. * @@ -273,7 +278,11 @@ function BaseSelectionList( } } - onSelectRow(item); + if (shouldDebounceRowSelect) { + debouncedOnSelectRow(item); + } else { + onSelectRow(item); + } if (shouldShowTextInput && shouldPreventDefaultFocusOnSelectRow && innerTextInputRef.current) { innerTextInputRef.current.focus(); @@ -298,6 +307,11 @@ function BaseSelectionList( selectRow(focusedOption); }; + // This debounce happens on the trailing edge because on repeated enter presses, rapid component state update cancels the existing debounce and the redundant + // enter presses runs the debounced function again. + // eslint-disable-next-line react-hooks/exhaustive-deps + const debouncedSelectFocusedOption = useCallback(lodashDebounce(selectFocusedOption, 100), [selectFocusedOption]); + /** * This function is used to compute the layout of any given item in our list. * We need to implement it so that we can programmatically scroll to items outside the virtual render window of the SectionList. @@ -450,6 +464,26 @@ function BaseSelectionList( [scrollToIndex, setFocusedIndex], ); + useEffect(() => { + if (!(shouldDebounceRowSelect && debouncedOnSelectRow.cancel)) { + return; + } + + return () => { + debouncedOnSelectRow.cancel(); + }; + }, [debouncedOnSelectRow, shouldDebounceRowSelect]); + + useEffect(() => { + if (!(shouldDebounceRowSelect && debouncedSelectFocusedOption.cancel)) { + return; + } + + return () => { + debouncedSelectFocusedOption.cancel(); + }; + }, [debouncedSelectFocusedOption, shouldDebounceRowSelect]); + /** Focuses the text input when the component comes into focus and after any navigation animations finish. */ useFocusEffect( useCallback(() => { @@ -539,7 +573,7 @@ function BaseSelectionList( useImperativeHandle(ref, () => ({scrollAndHighlightItem}), [scrollAndHighlightItem]); /** Selects row when pressing Enter */ - useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ENTER, selectFocusedOption, { + useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ENTER, shouldDebounceRowSelect ? debouncedSelectFocusedOption : selectFocusedOption, { captureOnInputs: true, shouldBubble: !flattenedSections.allOptions[focusedIndex], shouldStopPropagation, @@ -599,7 +633,7 @@ function BaseSelectionList( selectTextOnFocus spellCheck={false} iconLeft={textInputIconLeft} - onSubmitEditing={selectFocusedOption} + onSubmitEditing={shouldDebounceRowSelect ? debouncedSelectFocusedOption : selectFocusedOption} blurOnSubmit={!!flattenedSections.allOptions.length} isLoading={isLoadingNewOptions} testID="selection-list-text-input" diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 4c9b72634c4..ab24f0bc7a2 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -240,6 +240,9 @@ type BaseSelectionListProps = Partial & { /** Callback to fire when a row is pressed */ onSelectRow: (item: TItem) => void; + /** Whether to debounce `onRowSelect` */ + shouldDebounceRowSelect?: boolean; + /** Optional callback function triggered upon pressing a checkbox. If undefined and the list displays checkboxes, checkbox interactions are managed by onSelectRow, allowing for pressing anywhere on the list. */ onCheckboxPress?: (item: TItem) => void; diff --git a/src/pages/ChatFinderPage/index.tsx b/src/pages/ChatFinderPage/index.tsx index d4b856e6955..b45adcb7e8e 100644 --- a/src/pages/ChatFinderPage/index.tsx +++ b/src/pages/ChatFinderPage/index.tsx @@ -179,6 +179,7 @@ function ChatFinderPage({betas, isSearchingForReports, navigation}: ChatFinderPa headerMessage={headerMessage} onLayout={setPerformanceTimersEnd} onSelectRow={selectReport} + shouldDebounceRowSelect showLoadingPlaceholder={!areOptionsInitialized || !isScreenTransitionEnd} footerContent={!isDismissed && ChatFinderPageFooterInstance} isLoadingNewOptions={!!isSearchingForReports} diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index a70320444dc..d62333be488 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -311,6 +311,7 @@ function NewChatPage({isGroupChat}: NewChatPageProps) { textInputLabel={translate('selectionList.nameEmailOrPhoneNumber')} headerMessage={headerMessage} onSelectRow={createChat} + shouldDebounceRowSelect onConfirm={(e, option) => (selectedOptions.length > 0 ? createGroup() : createChat(option))} rightHandSideComponent={itemRightSideComponent} footerContent={footerContent} diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx index 0f85b58bf10..a3fc3737dbf 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx @@ -65,6 +65,7 @@ function BusinessTypeSelectorModal({isVisible, currentBusinessType, onBusinessTy sections={[{data: incorporationTypes}]} initiallyFocusedOptionKey={currentBusinessType} onSelectRow={onBusinessTypeSelected} + shouldDebounceRowSelect shouldStopPropagation shouldUseDynamicMaxToRenderPerBatch ListItem={RadioListItem} diff --git a/src/pages/ReportParticipantRoleSelectionPage.tsx b/src/pages/ReportParticipantRoleSelectionPage.tsx index 6d8c5d95106..e6a42188e54 100644 --- a/src/pages/ReportParticipantRoleSelectionPage.tsx +++ b/src/pages/ReportParticipantRoleSelectionPage.tsx @@ -68,6 +68,7 @@ function ReportParticipantRoleSelectionPage({report, route}: ReportParticipantRo sections={[{data: items}]} ListItem={RadioListItem} onSelectRow={changeRole} + shouldDebounceRowSelect initiallyFocusedOptionKey={items.find((item) => item.isSelected)?.keyForList} /> diff --git a/src/pages/ReportParticipantsPage.tsx b/src/pages/ReportParticipantsPage.tsx index a3670d722b3..121c80738b4 100755 --- a/src/pages/ReportParticipantsPage.tsx +++ b/src/pages/ReportParticipantsPage.tsx @@ -351,6 +351,7 @@ function ReportParticipantsPage({report, personalDetails, session}: ReportPartic ListItem={TableListItem} headerContent={headerContent} onSelectRow={openMemberDetails} + shouldDebounceRowSelect={!(isGroupChat && isCurrentUserAdmin)} onCheckboxPress={(item) => toggleUser(item.accountID)} onSelectAll={() => toggleAllUsers(participants)} showScrollIndicator diff --git a/src/pages/WorkspaceSwitcherPage/index.tsx b/src/pages/WorkspaceSwitcherPage/index.tsx index d9b9d62bb53..c8c830e530f 100644 --- a/src/pages/WorkspaceSwitcherPage/index.tsx +++ b/src/pages/WorkspaceSwitcherPage/index.tsx @@ -178,6 +178,7 @@ function WorkspaceSwitcherPage() { ListItem={UserListItem} sections={sections} onSelectRow={selectPolicy} + shouldDebounceRowSelect textInputLabel={usersWorkspaces.length >= CONST.WORKSPACE_SWITCHER.MINIMUM_WORKSPACES_TO_SHOW_SEARCH ? translate('common.search') : undefined} textInputValue={searchTerm} onChangeText={setSearchTerm} diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index b525a2c1e3d..278f408ccc1 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -358,6 +358,7 @@ function MoneyRequestParticipantsSelector({participants = [], onFinish, onPartic onChangeText={setSearchTerm} shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} onSelectRow={(item) => (isIOUSplit ? addParticipantToSelection(item) : addSingleParticipant(item))} + shouldDebounceRowSelect footerContent={footerContent} headerMessage={headerMessage} showLoadingPlaceholder={!areOptionsInitialized || !didScreenTransitionEnd} diff --git a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 1b9ccf1876c..a7ebe843e8a 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx @@ -86,6 +86,7 @@ function IOURequestStepDistanceRate({ sections={[{data: sections}]} ListItem={RadioListItem} onSelectRow={({value}) => selectDistanceRate(value ?? '')} + shouldDebounceRowSelect initiallyFocusedOptionKey={initiallyFocusedOption} /> diff --git a/src/pages/iou/request/step/IOURequestStepSendFrom.tsx b/src/pages/iou/request/step/IOURequestStepSendFrom.tsx index 46d8a1ce36a..3bbff502d91 100644 --- a/src/pages/iou/request/step/IOURequestStepSendFrom.tsx +++ b/src/pages/iou/request/step/IOURequestStepSendFrom.tsx @@ -86,6 +86,7 @@ function IOURequestStepSendFrom({route, transaction, allPolicies}: IOURequestSte diff --git a/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx index c2ee404b120..48aa4789d6b 100644 --- a/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx +++ b/src/pages/iou/request/step/IOURequestStepSplitPayer.tsx @@ -87,6 +87,7 @@ function IOURequestStepSplitPayer({ sections={sections} ListItem={UserListItem} onSelectRow={setSplitPayer} + shouldDebounceRowSelect showLoadingPlaceholder={!didScreenTransitionEnd} /> diff --git a/src/pages/settings/AboutPage/ShareLogList/BaseShareLogList.tsx b/src/pages/settings/AboutPage/ShareLogList/BaseShareLogList.tsx index 05ec664fb4c..7c874e4efd2 100644 --- a/src/pages/settings/AboutPage/ShareLogList/BaseShareLogList.tsx +++ b/src/pages/settings/AboutPage/ShareLogList/BaseShareLogList.tsx @@ -105,6 +105,7 @@ function BaseShareLogList({onAttachLogToReport}: BaseShareLogListProps) { ListItem={UserListItem} sections={didScreenTransitionEnd ? sections : CONST.EMPTY_ARRAY} onSelectRow={attachLogToReport} + shouldDebounceRowSelect onChangeText={setSearchValue} textInputValue={searchValue} headerMessage={searchOptions.headerMessage} diff --git a/src/pages/settings/Preferences/LanguagePage.tsx b/src/pages/settings/Preferences/LanguagePage.tsx index b577e006acf..f5c2cb4097a 100644 --- a/src/pages/settings/Preferences/LanguagePage.tsx +++ b/src/pages/settings/Preferences/LanguagePage.tsx @@ -31,6 +31,7 @@ function LanguagePage() { sections={[{data: localesToLanguages}]} ListItem={RadioListItem} onSelectRow={(language) => App.setLocaleAndNavigate(language.value)} + shouldDebounceRowSelect initiallyFocusedOptionKey={localesToLanguages.find((locale) => locale.isSelected)?.keyForList} /> diff --git a/src/pages/settings/Preferences/PriorityModePage.tsx b/src/pages/settings/Preferences/PriorityModePage.tsx index 2a4cd196f17..aef727e448f 100644 --- a/src/pages/settings/Preferences/PriorityModePage.tsx +++ b/src/pages/settings/Preferences/PriorityModePage.tsx @@ -58,6 +58,7 @@ function PriorityModePage() { sections={[{data: priorityModes}]} ListItem={RadioListItem} onSelectRow={updateMode} + shouldDebounceRowSelect initiallyFocusedOptionKey={priorityModes.find((mode) => mode.isSelected)?.keyForList} /> diff --git a/src/pages/settings/Preferences/ThemePage.tsx b/src/pages/settings/Preferences/ThemePage.tsx index f879a7a259e..c46e0f2abaa 100644 --- a/src/pages/settings/Preferences/ThemePage.tsx +++ b/src/pages/settings/Preferences/ThemePage.tsx @@ -49,6 +49,7 @@ function ThemePage({preferredTheme}: ThemePageProps) { sections={[{data: localesToThemes}]} ListItem={RadioListItem} onSelectRow={(theme) => User.updateTheme(theme.value)} + shouldDebounceRowSelect initiallyFocusedOptionKey={localesToThemes.find((theme) => theme.isSelected)?.keyForList} /> diff --git a/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.tsx index c0d980083dd..249698e1916 100644 --- a/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.tsx @@ -80,6 +80,7 @@ function CountrySelectionPage({route, navigation}: CountrySelectionPageProps) { sections={[{data: searchResults}]} ListItem={RadioListItem} onSelectRow={selectCountry} + shouldDebounceRowSelect onChangeText={setSearchValue} initiallyFocusedOptionKey={currentCountry} shouldUseDynamicMaxToRenderPerBatch diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index bf1bb8ad197..8003c2ce767 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -105,6 +105,7 @@ function StateSelectionPage() { diff --git a/src/pages/settings/Profile/TimezoneSelectPage.tsx b/src/pages/settings/Profile/TimezoneSelectPage.tsx index 97cec508f86..fdc10b72ad4 100644 --- a/src/pages/settings/Profile/TimezoneSelectPage.tsx +++ b/src/pages/settings/Profile/TimezoneSelectPage.tsx @@ -72,6 +72,7 @@ function TimezoneSelectPage({currentUserPersonalDetails}: TimezoneSelectPageProp textInputValue={timezoneInputText} onChangeText={filterShownTimezones} onSelectRow={saveSelectedTimezone} + shouldDebounceRowSelect sections={[{data: timezoneOptions, isDisabled: timezone.automatic}]} initiallyFocusedOptionKey={timezoneOptions.find((tz) => tz.text === timezone.selected)?.keyForList} showScrollIndicator diff --git a/src/pages/settings/Report/NotificationPreferencePage.tsx b/src/pages/settings/Report/NotificationPreferencePage.tsx index af55ff994fc..39e008c2bee 100644 --- a/src/pages/settings/Report/NotificationPreferencePage.tsx +++ b/src/pages/settings/Report/NotificationPreferencePage.tsx @@ -44,6 +44,7 @@ function NotificationPreferencePage({report}: NotificationPreferencePageProps) { onSelectRow={(option) => report && ReportActions.updateNotificationPreference(report.reportID, report.notificationPreference, option.value, true, undefined, undefined, report) } + shouldDebounceRowSelect initiallyFocusedOptionKey={notificationPreferenceOptions.find((locale) => locale.isSelected)?.keyForList} /> diff --git a/src/pages/settings/Report/VisibilityPage.tsx b/src/pages/settings/Report/VisibilityPage.tsx index d3b8b2656d5..9bcf3b05e83 100644 --- a/src/pages/settings/Report/VisibilityPage.tsx +++ b/src/pages/settings/Report/VisibilityPage.tsx @@ -72,6 +72,7 @@ function VisibilityPage({report}: VisibilityProps) { } changeVisibility(option.value); }} + shouldDebounceRowSelect initiallyFocusedOptionKey={visibilityOptions.find((visibility) => visibility.isSelected)?.keyForList} ListItem={RadioListItem} /> diff --git a/src/pages/settings/Report/WriteCapabilityPage.tsx b/src/pages/settings/Report/WriteCapabilityPage.tsx index 1f991ef87c9..9de1c6d3779 100644 --- a/src/pages/settings/Report/WriteCapabilityPage.tsx +++ b/src/pages/settings/Report/WriteCapabilityPage.tsx @@ -55,6 +55,7 @@ function WriteCapabilityPage({report, policy}: WriteCapabilityPageProps) { sections={[{data: writeCapabilityOptions}]} ListItem={RadioListItem} onSelectRow={(option) => report && ReportActions.updateWriteCapabilityAndNavigate(report, option.value)} + shouldDebounceRowSelect initiallyFocusedOptionKey={writeCapabilityOptions.find((locale) => locale.isSelected)?.keyForList} /> diff --git a/src/pages/tasks/TaskAssigneeSelectorModal.tsx b/src/pages/tasks/TaskAssigneeSelectorModal.tsx index 3116b8a8415..9cff3694fc5 100644 --- a/src/pages/tasks/TaskAssigneeSelectorModal.tsx +++ b/src/pages/tasks/TaskAssigneeSelectorModal.tsx @@ -217,6 +217,7 @@ function TaskAssigneeSelectorModal({reports, task}: TaskAssigneeSelectorModalPro sections={areOptionsInitialized ? sections : []} ListItem={UserListItem} onSelectRow={selectReport} + shouldDebounceRowSelect onChangeText={setSearchValue} textInputValue={searchValue} headerMessage={headerMessage} diff --git a/src/pages/tasks/TaskShareDestinationSelectorModal.tsx b/src/pages/tasks/TaskShareDestinationSelectorModal.tsx index 4d731d59a9e..55c2f54b5e4 100644 --- a/src/pages/tasks/TaskShareDestinationSelectorModal.tsx +++ b/src/pages/tasks/TaskShareDestinationSelectorModal.tsx @@ -105,6 +105,7 @@ function TaskShareDestinationSelectorModal() { ListItem={UserListItem} sections={areOptionsInitialized ? options.sections : []} onSelectRow={selectReportHandler} + shouldDebounceRowSelect onChangeText={setSearchValue} textInputValue={searchValue} headerMessage={options.headerMessage} diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index fe88c12e677..4b2eca431a8 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -574,6 +574,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, headerMessage={getHeaderMessage()} headerContent={!isSmallScreenWidth && getHeaderContent()} onSelectRow={openMemberDetails} + shouldDebounceRowSelect={!isPolicyAdmin} onCheckboxPress={(item) => toggleUser(item.accountID)} onSelectAll={() => toggleAllUsers(data)} onDismissError={dismissError} diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx index e9cc481eb23..f96daaefff4 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx @@ -75,6 +75,7 @@ function QuickbooksAccountSelectPage({policy}: WithPolicyConnectionsProps) { ListItem={RadioListItem} headerContent={listHeaderComponent} onSelectRow={saveSelection} + shouldDebounceRowSelect initiallyFocusedOptionKey={initiallyFocusedOptionKey} /> diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx index 346c74e35fe..4c1eba8f216 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx @@ -76,6 +76,7 @@ function QuickbooksInvoiceAccountSelectPage({policy}: WithPolicyConnectionsProps ListItem={RadioListItem} headerContent={listHeaderComponent} onSelectRow={updateAccount} + shouldDebounceRowSelect initiallyFocusedOptionKey={initiallyFocusedOptionKey} /> diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx index 4f757eab253..a40dc86c051 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx @@ -101,6 +101,7 @@ function QuickbooksCompanyCardExpenseAccountSelectCardPage({policy}: WithPolicyC sections={sections} ListItem={RadioListItem} onSelectRow={selectExportCompanyCard} + shouldDebounceRowSelect initiallyFocusedOptionKey={sections[0].data.find((option) => option.isSelected)?.keyForList} footerContent={ isLocationEnabled && {translate('workspace.qbo.companyCardsLocationEnabledDescription')} diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx index 98d81a480dd..892a84f9dfd 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx @@ -85,6 +85,7 @@ function QuickbooksCompanyCardExpenseAccountSelectPage({policy}: WithPolicyConne sections={[{data}]} ListItem={RadioListItem} onSelectRow={selectExportAccount} + shouldDebounceRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} /> diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx index 16e9a20668c..4e162c8984b 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx @@ -58,6 +58,7 @@ function QuickbooksExportDateSelectPage({policy}: WithPolicyConnectionsProps) { sections={[{data}]} ListItem={RadioListItem} onSelectRow={selectExportDate} + shouldDebounceRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} /> diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx index b7c95811b90..5f72beb8d89 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx @@ -61,6 +61,7 @@ function QuickbooksExportInvoiceAccountSelectPage({policy}: WithPolicyConnection sections={[{data}]} ListItem={RadioListItem} onSelectRow={selectExportInvoice} + shouldDebounceRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} /> diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx index 729914176a0..5264f6c0c45 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx @@ -60,6 +60,7 @@ function QuickbooksNonReimbursableDefaultVendorSelectPage({policy}: WithPolicyCo sections={sections} ListItem={RadioListItem} onSelectRow={selectVendor} + shouldDebounceRowSelect initiallyFocusedOptionKey={sections[0].data.find((mode) => mode.isSelected)?.keyForList} /> diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx index ebac7546341..e9944a28992 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx @@ -76,6 +76,7 @@ function QuickbooksOutOfPocketExpenseAccountSelectPage({policy}: WithPolicyConne sections={[{data}]} ListItem={RadioListItem} onSelectRow={selectExportAccount} + shouldDebounceRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} /> diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx index 612fc3755ad..1c74b146eea 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx @@ -105,6 +105,7 @@ function QuickbooksOutOfPocketExpenseEntitySelectPage({policy}: WithPolicyConnec sections={sections} ListItem={RadioListItem} onSelectRow={selectExportEntity} + shouldDebounceRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} footerContent={isTaxesEnabled && {translate('workspace.qbo.outOfPocketTaxEnabledDescription')}} /> diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx index a55b293fc3a..ee61b2be1fb 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx @@ -80,6 +80,7 @@ function QuickbooksPreferredExporterConfigurationPage({policy}: WithPolicyConnec sections={[{data}]} ListItem={RadioListItem} onSelectRow={selectExporter} + shouldDebounceRowSelect initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} /> diff --git a/src/pages/workspace/accounting/xero/XeroMapCostCentersToConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroMapCostCentersToConfigurationPage.tsx index b4f0fe04f6c..eec92252246 100644 --- a/src/pages/workspace/accounting/xero/XeroMapCostCentersToConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroMapCostCentersToConfigurationPage.tsx @@ -61,6 +61,7 @@ function XeroMapCostCentersToConfigurationPage({policy}: WithPolicyProps) { sections={[{data: optionsList}]} ListItem={RadioListItem} onSelectRow={updateMapping} + shouldDebounceRowSelect /> ); diff --git a/src/pages/workspace/accounting/xero/XeroMapRegionsToConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroMapRegionsToConfigurationPage.tsx index bb5870da8fc..e5ec85b05c3 100644 --- a/src/pages/workspace/accounting/xero/XeroMapRegionsToConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroMapRegionsToConfigurationPage.tsx @@ -60,6 +60,7 @@ function XeroMapRegionsToConfigurationPage({policy}: WithPolicyProps) { sections={[{data: optionsList}]} ListItem={RadioListItem} onSelectRow={updateMapping} + shouldDebounceRowSelect /> ); diff --git a/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx index 1c4b9373c67..85b0f20071a 100644 --- a/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx @@ -67,6 +67,7 @@ function XeroOrganizationConfigurationPage({ diff --git a/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionModal.tsx b/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionModal.tsx index f1d4334f706..30040fb2fd6 100644 --- a/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionModal.tsx +++ b/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionModal.tsx @@ -56,6 +56,7 @@ function WorkspaceMemberDetailsRoleSelectionModal({isVisible, items, onRoleChang sections={[{data: items}]} ListItem={RadioListItem} onSelectRow={onRoleChange} + shouldDebounceRowSelect initiallyFocusedOptionKey={items.find((item) => item.isSelected)?.keyForList} /> diff --git a/src/pages/workspace/tags/WorkspaceTagsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsPage.tsx index 64e9a661cd2..a2c0efb2dc0 100644 --- a/src/pages/workspace/tags/WorkspaceTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsPage.tsx @@ -339,6 +339,7 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) { sections={[{data: tagList, isDisabled: false}]} onCheckboxPress={toggleTag} onSelectRow={navigateToTagSettings} + shouldDebounceRowSelect={!canSelectMultiple} onSelectAll={toggleAllTags} ListItem={TableListItem} customListHeader={getCustomListHeader()} diff --git a/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx b/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx index 0732b924801..4d1be42b6f2 100644 --- a/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx @@ -98,6 +98,7 @@ function WorkspaceAutoReportingMonthlyOffsetPage({policy, route}: WorkspaceAutoR headerMessage={headerMessage} ListItem={RadioListItem} onSelectRow={onSelectDayOfMonth} + shouldDebounceRowSelect initiallyFocusedOptionKey={offset.toString()} showScrollIndicator /> diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx index 6125fef9318..68e0746c1ed 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx @@ -182,6 +182,7 @@ function WorkspaceWorkflowsApproverPage({policy, personalDetails, isLoadingRepor headerMessage={headerMessage} ListItem={UserListItem} onSelectRow={setPolicyApprover} + shouldDebounceRowSelect showScrollIndicator /> diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx index ef373e7d78a..ae48f6675ac 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx @@ -192,6 +192,7 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR headerMessage={headerMessage} ListItem={UserListItem} onSelectRow={setPolicyAuthorizedPayer} + shouldDebounceRowSelect showScrollIndicator />