From ae5a99f1f178b87f2d18712928a59b5a0aa07155 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Mon, 21 Aug 2023 21:58:39 +0500 Subject: [PATCH 01/37] Added debounce row selection prop to selection list --- .../BaseSelectionListRadio.js | 19 ++++++++++++++++--- .../selectionListRadioPropTypes.js | 4 ++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/components/SelectionListRadio/BaseSelectionListRadio.js b/src/components/SelectionListRadio/BaseSelectionListRadio.js index c9e4c14d6b81..c2655a26cf25 100644 --- a/src/components/SelectionListRadio/BaseSelectionListRadio.js +++ b/src/components/SelectionListRadio/BaseSelectionListRadio.js @@ -1,4 +1,4 @@ -import React, {useEffect, useRef, useState} from 'react'; +import React, {useEffect, useRef, useState, useCallback} from 'react'; import {View} from 'react-native'; import _ from 'underscore'; import lodashGet from 'lodash/get'; @@ -102,6 +102,11 @@ function BaseSelectionListRadio(props) { return defaultIndex; }); + const onSelectRow = useCallback(props.shouldDebounceRowSelect ? _.debounce(props.onSelectRow, 1000, {leading: true}) : props.onSelectRow, [ + props.shouldDebounceRowSelect, + props.onSelectRow, + ]); + /** * Scrolls to the desired item index in the section list * @@ -166,7 +171,7 @@ function BaseSelectionListRadio(props) { item={item} isFocused={isFocused} isDisabled={isDisabled} - onSelectRow={props.onSelectRow} + onSelectRow={onSelectRow} /> ); }; @@ -189,6 +194,14 @@ function BaseSelectionListRadio(props) { }; }, [props.shouldDelayFocus, shouldShowTextInput]); + useEffect(() => { + return () => { + if (props.shouldDebounceRowSelect && onSelectRow.cancel) { + onSelectRow.cancel(); + } + }; + }, [onSelectRow, props.shouldDebounceRowSelect]); + const selectFocusedOption = () => { const focusedOption = flattenedSections.allOptions[focusedIndex]; @@ -196,7 +209,7 @@ function BaseSelectionListRadio(props) { return; } - props.onSelectRow(focusedOption); + onSelectRow(focusedOption); }; useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ENTER, selectFocusedOption, { diff --git a/src/components/SelectionListRadio/selectionListRadioPropTypes.js b/src/components/SelectionListRadio/selectionListRadioPropTypes.js index 14e41b195d7b..0999ef814cf6 100644 --- a/src/components/SelectionListRadio/selectionListRadioPropTypes.js +++ b/src/components/SelectionListRadio/selectionListRadioPropTypes.js @@ -36,6 +36,9 @@ const propTypes = { /** Callback to fire when a row is tapped */ onSelectRow: PropTypes.func, + /** Boolean to indicate if onSelectRow should be debounced */ + shouldDebounceRowSelect: PropTypes.bool, + /** Label for the text input */ textInputLabel: PropTypes.string, @@ -72,6 +75,7 @@ const propTypes = { const defaultProps = { onSelectRow: () => {}, + shouldDebounceRowSelect: false, textInputLabel: '', textInputPlaceholder: '', textInputValue: '', From 9213d0d23c1a41cddf39a967709811b7c62bd486 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Mon, 21 Aug 2023 22:09:45 +0500 Subject: [PATCH 02/37] Updated pages to use debounced onSelectRow on selection list for side effects --- src/pages/settings/Preferences/LanguagePage.js | 1 + src/pages/settings/Preferences/PriorityModePage.js | 1 + src/pages/settings/Profile/PronounsPage.js | 10 +++++++--- src/pages/settings/Profile/TimezoneSelectPage.js | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/pages/settings/Preferences/LanguagePage.js b/src/pages/settings/Preferences/LanguagePage.js index 7075c998a56d..adf2e624f66b 100644 --- a/src/pages/settings/Preferences/LanguagePage.js +++ b/src/pages/settings/Preferences/LanguagePage.js @@ -33,6 +33,7 @@ function LanguagePage(props) { App.setLocaleAndNavigate(language.value)} + shouldDebounceRowSelect initiallyFocusedOptionKey={_.find(localesToLanguages, (locale) => locale.isSelected).keyForList} /> diff --git a/src/pages/settings/Preferences/PriorityModePage.js b/src/pages/settings/Preferences/PriorityModePage.js index 17f86c6eb1d8..03a1953efaaf 100644 --- a/src/pages/settings/Preferences/PriorityModePage.js +++ b/src/pages/settings/Preferences/PriorityModePage.js @@ -55,6 +55,7 @@ function PriorityModePage(props) { mode.isSelected).keyForList} /> diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index 90f934658def..6d3fffda6603 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -70,9 +70,12 @@ function PronounsPage(props) { /** * @param {Object} selectedPronouns */ - const updatePronouns = (selectedPronouns) => { - PersonalDetails.updatePronouns(selectedPronouns.keyForList === initiallyFocusedOption.keyForList ? '' : lodashGet(selectedPronouns, 'value', '')); - }; + const updatePronouns = useCallback( + (selectedPronouns) => { + PersonalDetails.updatePronouns(selectedPronouns.keyForList === initiallyFocusedOption.keyForList ? '' : lodashGet(selectedPronouns, 'value', '')); + }, + [initiallyFocusedOption], + ); /** * Pronouns list filtered by searchValue needed for the OptionsSelector. @@ -111,6 +114,7 @@ function PronounsPage(props) { textInputValue={searchValue} sections={[{data: filteredPronounsList, indexOffset: 0}]} onSelectRow={updatePronouns} + shouldDebounceRowSelect onChangeText={onChangeText} initiallyFocusedOptionKey={initiallyFocusedOption.keyForList} /> diff --git a/src/pages/settings/Profile/TimezoneSelectPage.js b/src/pages/settings/Profile/TimezoneSelectPage.js index 1bed325c435a..e50c6f41cf7e 100644 --- a/src/pages/settings/Profile/TimezoneSelectPage.js +++ b/src/pages/settings/Profile/TimezoneSelectPage.js @@ -76,6 +76,7 @@ function TimezoneSelectPage(props) { textInputValue={timezoneInputText} onChangeText={filterShownTimezones} onSelectRow={saveSelectedTimezone} + shouldDebounceRowSelect sections={[{data: timezoneOptions, indexOffset: 0, isDisabled: timezone.automatic}]} initiallyFocusedOptionKey={_.get(_.filter(timezoneOptions, (tz) => tz.text === timezone.selected)[0], 'keyForList')} /> From e2ea6277140033a699d2af1dd319c57ce3a393ad Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Mon, 21 Aug 2023 22:11:13 +0500 Subject: [PATCH 03/37] Added debounce row selection prop to options list --- src/components/OptionRow.js | 17 +++++++++++++++-- src/components/OptionsList/BaseOptionsList.js | 1 + .../OptionsList/optionsListPropTypes.js | 4 ++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index adaa4457bbd9..d8b674723cea 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -36,6 +36,9 @@ const propTypes = { /** A function that is called when an option is selected. Selected option is passed as a param */ onSelectRow: PropTypes.func, + /** Boolean to indicate if onSelectRow should be debounced */ + shouldDebounceRowSelect: PropTypes.bool, + /** Whether we should show the selected state */ showSelectedState: PropTypes.bool, @@ -69,6 +72,7 @@ const defaultProps = { boldStyle: false, showTitleTooltip: false, onSelectRow: undefined, + shouldDebounceRowSelect: false, isDisabled: false, optionIsFocused: false, style: null, @@ -82,6 +86,8 @@ class OptionRow extends Component { this.state = { isDisabled: this.props.isDisabled, }; + + this.onSelectRow = this.props.shouldDebounceRowSelect ? _.debounce(this.props.onSelectRow, 1000, {leading: true}) : this.props.onSelectRow; } // It is very important to use shouldComponentUpdate here so SectionList items will not unnecessarily re-render @@ -103,7 +109,8 @@ class OptionRow extends Component { this.props.option.ownerAccountID !== nextProps.option.ownerAccountID || this.props.option.subtitle !== nextProps.option.subtitle || this.props.option.pendingAction !== nextProps.option.pendingAction || - this.props.option.customIcon !== nextProps.option.customIcon + this.props.option.customIcon !== nextProps.option.customIcon || + this.props.shouldDebounceRowSelect !== nextProps.shouldDebounceRowSelect ); } @@ -115,6 +122,12 @@ class OptionRow extends Component { this.setState({isDisabled: this.props.isDisabled}); } + componentWillUnmount() { + if (this.props.shouldDebounceRowSelect && this.onSelectRow.cancel) { + this.onSelectRow.cancel(); + } + } + render() { let pressableRef = null; const textStyle = this.props.optionIsFocused ? styles.sidebarLinkActiveText : styles.sidebarLinkText; @@ -164,7 +177,7 @@ class OptionRow extends Component { if (e) { e.preventDefault(); } - let result = this.props.onSelectRow(this.props.option, pressableRef); + let result = this.onSelectRow(this.props.option, pressableRef); if (!(result instanceof Promise)) { result = Promise.resolve(); } diff --git a/src/components/OptionsList/BaseOptionsList.js b/src/components/OptionsList/BaseOptionsList.js index e417234bb14a..e096ef106e5e 100644 --- a/src/components/OptionsList/BaseOptionsList.js +++ b/src/components/OptionsList/BaseOptionsList.js @@ -168,6 +168,7 @@ class BaseOptionsList extends Component { hoverStyle={this.props.optionHoveredStyle} optionIsFocused={!this.props.disableFocusOptions && !isDisabled && this.props.focusedIndex === index + section.indexOffset} onSelectRow={this.props.onSelectRow} + shouldDebounceRowSelect={this.props.shouldDebounceRowSelect} isSelected={Boolean(_.find(this.props.selectedOptions, (option) => option.accountID === item.accountID))} showSelectedState={this.props.canSelectMultipleOptions} boldStyle={this.props.boldStyle} diff --git a/src/components/OptionsList/optionsListPropTypes.js b/src/components/OptionsList/optionsListPropTypes.js index 74c13c7f2455..731e3c078cab 100644 --- a/src/components/OptionsList/optionsListPropTypes.js +++ b/src/components/OptionsList/optionsListPropTypes.js @@ -52,6 +52,9 @@ const propTypes = { /** Callback to fire when a row is selected */ onSelectRow: PropTypes.func, + /** Boolean to indicate if onSelectRow should be debounced */ + shouldDebounceRowSelect: PropTypes.bool, + /** Optional header message */ headerMessage: PropTypes.string, @@ -92,6 +95,7 @@ const defaultProps = { disableFocusOptions: false, boldStyle: false, onSelectRow: undefined, + shouldDebounceRowSelect: false, headerMessage: '', innerRef: null, showTitleTooltip: false, From 4754aa78080caa4968c1ef407f3292e966b8c7e2 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Mon, 21 Aug 2023 22:12:16 +0500 Subject: [PATCH 04/37] Updated pages to use debounced onSelectRow on options list for side effects --- src/pages/ReportParticipantsPage.js | 1 + src/pages/home/report/ReactionList/BaseReactionList.js | 1 + src/pages/settings/Report/NotificationPreferencePage.js | 1 + src/pages/settings/Report/WriteCapabilityPage.js | 1 + 4 files changed, 4 insertions(+) diff --git a/src/pages/ReportParticipantsPage.js b/src/pages/ReportParticipantsPage.js index 267e7f7b60a5..4ab2040a07dd 100755 --- a/src/pages/ReportParticipantsPage.js +++ b/src/pages/ReportParticipantsPage.js @@ -122,6 +122,7 @@ function ReportParticipantsPage(props) { onSelectRow={(option) => { Navigation.navigate(ROUTES.getProfileRoute(option.accountID)); }} + shouldDebounceRowSelect hideSectionHeaders showTitleTooltip showScrollIndicator diff --git a/src/pages/home/report/ReactionList/BaseReactionList.js b/src/pages/home/report/ReactionList/BaseReactionList.js index 0b77fca7c645..2a8a977de370 100755 --- a/src/pages/home/report/ReactionList/BaseReactionList.js +++ b/src/pages/home/report/ReactionList/BaseReactionList.js @@ -81,6 +81,7 @@ function BaseReactionList(props) { props.onClose(); Navigation.navigate(ROUTES.getProfileRoute(item.accountID)); }} + shouldDebounceRowSelect option={{ text: Str.removeSMSDomain(item.displayName), alternateText: Str.removeSMSDomain(item.login || ''), diff --git a/src/pages/settings/Report/NotificationPreferencePage.js b/src/pages/settings/Report/NotificationPreferencePage.js index 9765cf1ae0b4..5f9dd110ac43 100644 --- a/src/pages/settings/Report/NotificationPreferencePage.js +++ b/src/pages/settings/Report/NotificationPreferencePage.js @@ -48,6 +48,7 @@ function NotificationPreferencePage(props) { Report.updateNotificationPreferenceAndNavigate(props.report.reportID, props.report.notificationPreference, option.value)} + shouldDebounceRowSelect hideSectionHeaders optionHoveredStyle={{ ...styles.hoveredComponentBG, diff --git a/src/pages/settings/Report/WriteCapabilityPage.js b/src/pages/settings/Report/WriteCapabilityPage.js index 59ad90a2cd1f..9c1255434a87 100644 --- a/src/pages/settings/Report/WriteCapabilityPage.js +++ b/src/pages/settings/Report/WriteCapabilityPage.js @@ -61,6 +61,7 @@ function WriteCapabilityPage(props) { Report.updateWriteCapabilityAndNavigate(props.report, option.value)} + shouldDebounceRowSelect hideSectionHeaders optionHoveredStyle={{ ...styles.hoveredComponentBG, From c289d5ac6a351b808eee11e84abaf46142ccf78a Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Mon, 21 Aug 2023 22:14:00 +0500 Subject: [PATCH 05/37] Added debounce row selection prop to options selector --- src/components/OptionsSelector/BaseOptionsSelector.js | 1 + src/components/OptionsSelector/optionsSelectorPropTypes.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index 7273616ea57e..a421cbd7c082 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -336,6 +336,7 @@ class BaseOptionsSelector extends Component { ref={(el) => (this.list = el)} optionHoveredStyle={this.props.optionHoveredStyle} onSelectRow={this.props.onSelectRow ? this.selectRow : undefined} + shouldDebounceRowSelect={this.props.shouldDebounceRowSelect} sections={this.props.sections} focusedIndex={this.state.focusedIndex} selectedOptions={this.props.selectedOptions} diff --git a/src/components/OptionsSelector/optionsSelectorPropTypes.js b/src/components/OptionsSelector/optionsSelectorPropTypes.js index 02b807bf66c1..8e7c98aaea6e 100644 --- a/src/components/OptionsSelector/optionsSelectorPropTypes.js +++ b/src/components/OptionsSelector/optionsSelectorPropTypes.js @@ -6,6 +6,9 @@ const propTypes = { /** Callback to fire when a row is tapped */ onSelectRow: PropTypes.func, + /** Boolean to indicate if onSelectRow should be debounced */ + shouldDebounceRowSelect: PropTypes.bool, + /** Sections for the section list */ sections: PropTypes.arrayOf( PropTypes.shape({ @@ -110,6 +113,7 @@ const propTypes = { const defaultProps = { onSelectRow: undefined, + shouldDebounceRowSelect: false, textInputLabel: '', placeholderText: '', keyboardType: 'default', From 54e0fe032c2ba6de43396d8ab69dc274af036e37 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Mon, 21 Aug 2023 22:14:36 +0500 Subject: [PATCH 06/37] Updated pages to use debounced onSelectRow on options selector for side effects --- src/components/MoneyRequestConfirmationList.js | 1 + src/pages/NewChatPage.js | 1 + src/pages/SearchPage.js | 1 + src/pages/iou/IOUCurrencySelection.js | 1 + .../MoneyRequestParticipantsSelector.js | 1 + src/pages/tasks/TaskAssigneeSelectorModal.js | 1 + src/pages/tasks/TaskShareDestinationSelectorModal.js | 1 + 7 files changed, 7 insertions(+) diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 2cc458d0e4ad..f10300fa22ab 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -352,6 +352,7 @@ function MoneyRequestConfirmationList(props) { sections={optionSelectorSections} value="" onSelectRow={canModifyParticipants ? selectParticipant : navigateToReportOrUserDetail} + shouldDebounceRowSelect={!canModifyParticipants} onConfirmSelection={confirm} selectedOptions={selectedOptions} canSelectMultipleOptions={canModifyParticipants} diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 4a753c8632bd..bbb3dff38e10 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -195,6 +195,7 @@ function NewChatPage(props) { selectedOptions={selectedOptions} value={searchTerm} onSelectRow={(option) => (props.isGroupChat ? toggleOption(option) : createChat(option))} + shouldDebounceRowSelect={!props.isGroupChat} onChangeText={setSearchTerm} headerMessage={headerMessage} boldStyle diff --git a/src/pages/SearchPage.js b/src/pages/SearchPage.js index 6505b604b614..25f65ebe2868 100755 --- a/src/pages/SearchPage.js +++ b/src/pages/SearchPage.js @@ -178,6 +178,7 @@ class SearchPage extends Component { sections={sections} value={this.state.searchValue} onSelectRow={this.selectReport} + shouldDebounceRowSelect onChangeText={this.onChangeText} headerMessage={headerMessage} hideSectionHeaders diff --git a/src/pages/iou/IOUCurrencySelection.js b/src/pages/iou/IOUCurrencySelection.js index f9dc03c66f90..c6e8bf5eb8c9 100644 --- a/src/pages/iou/IOUCurrencySelection.js +++ b/src/pages/iou/IOUCurrencySelection.js @@ -122,6 +122,7 @@ function IOUCurrencySelection(props) { Date: Mon, 21 Aug 2023 22:17:36 +0500 Subject: [PATCH 07/37] Updated debounce callback in option row --- src/components/OptionRow.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index d8b674723cea..428c9daaf75d 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -87,7 +87,7 @@ class OptionRow extends Component { isDisabled: this.props.isDisabled, }; - this.onSelectRow = this.props.shouldDebounceRowSelect ? _.debounce(this.props.onSelectRow, 1000, {leading: true}) : this.props.onSelectRow; + this.onSelectRow = this.props.shouldDebounceRowSelect && this.props.onSelectRow ? _.debounce(this.props.onSelectRow, 1000, {leading: true}) : this.props.onSelectRow; } // It is very important to use shouldComponentUpdate here so SectionList items will not unnecessarily re-render From 6e3c7ac7c76720532d176a43499923827495b951 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Tue, 22 Aug 2023 00:03:23 +0500 Subject: [PATCH 08/37] Fix lint --- src/components/OptionRow.js | 5 ++--- .../SelectionListRadio/BaseSelectionListRadio.js | 7 +++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index 428c9daaf75d..06d0421b4a14 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -123,9 +123,8 @@ class OptionRow extends Component { } componentWillUnmount() { - if (this.props.shouldDebounceRowSelect && this.onSelectRow.cancel) { - this.onSelectRow.cancel(); - } + if (!(this.props.shouldDebounceRowSelect && this.onSelectRow.cancel)) return; + this.onSelectRow.cancel(); } render() { diff --git a/src/components/SelectionListRadio/BaseSelectionListRadio.js b/src/components/SelectionListRadio/BaseSelectionListRadio.js index c2655a26cf25..d949363ba90f 100644 --- a/src/components/SelectionListRadio/BaseSelectionListRadio.js +++ b/src/components/SelectionListRadio/BaseSelectionListRadio.js @@ -102,7 +102,7 @@ function BaseSelectionListRadio(props) { return defaultIndex; }); - const onSelectRow = useCallback(props.shouldDebounceRowSelect ? _.debounce(props.onSelectRow, 1000, {leading: true}) : props.onSelectRow, [ + const onSelectRow = useCallback(props.shouldDebounceRowSelect ? _.debounce((item) => props.onSelectRow(item), 1000, {leading: true}) : (item) => props.onSelectRow(item), [ props.shouldDebounceRowSelect, props.onSelectRow, ]); @@ -196,9 +196,8 @@ function BaseSelectionListRadio(props) { useEffect(() => { return () => { - if (props.shouldDebounceRowSelect && onSelectRow.cancel) { - onSelectRow.cancel(); - } + if (!(props.shouldDebounceRowSelect && onSelectRow.cancel)) return; + onSelectRow.cancel(); }; }, [onSelectRow, props.shouldDebounceRowSelect]); From e50bb84f504ff541706c161fa82ef7b051bfb010 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Tue, 22 Aug 2023 00:30:18 +0500 Subject: [PATCH 09/37] Fix lint --- src/components/SelectionListRadio/BaseSelectionListRadio.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/SelectionListRadio/BaseSelectionListRadio.js b/src/components/SelectionListRadio/BaseSelectionListRadio.js index d949363ba90f..74d1f31ad1e9 100644 --- a/src/components/SelectionListRadio/BaseSelectionListRadio.js +++ b/src/components/SelectionListRadio/BaseSelectionListRadio.js @@ -102,6 +102,7 @@ function BaseSelectionListRadio(props) { return defaultIndex; }); + // eslint-disable-next-line react-hooks/exhaustive-deps const onSelectRow = useCallback(props.shouldDebounceRowSelect ? _.debounce((item) => props.onSelectRow(item), 1000, {leading: true}) : (item) => props.onSelectRow(item), [ props.shouldDebounceRowSelect, props.onSelectRow, @@ -194,6 +195,7 @@ function BaseSelectionListRadio(props) { }; }, [props.shouldDelayFocus, shouldShowTextInput]); + // eslint-disable-next-line arrow-body-style useEffect(() => { return () => { if (!(props.shouldDebounceRowSelect && onSelectRow.cancel)) return; From 4adf2632ddd6c728b06497e231f988432eda64dd Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Tue, 22 Aug 2023 01:06:36 +0500 Subject: [PATCH 10/37] Fix debounced onSelectRow implementation in OptionRow --- src/components/OptionRow.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index 06d0421b4a14..959e76147d04 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -87,7 +87,7 @@ class OptionRow extends Component { isDisabled: this.props.isDisabled, }; - this.onSelectRow = this.props.shouldDebounceRowSelect && this.props.onSelectRow ? _.debounce(this.props.onSelectRow, 1000, {leading: true}) : this.props.onSelectRow; + this.updateOnSelectRow(); } // It is very important to use shouldComponentUpdate here so SectionList items will not unnecessarily re-render @@ -115,11 +115,13 @@ class OptionRow extends Component { } componentDidUpdate(prevProps) { - if (this.props.isDisabled === prevProps.isDisabled) { - return; + if (this.props.isDisabled !== prevProps.isDisabled) { + this.setState({isDisabled: this.props.isDisabled}); } - this.setState({isDisabled: this.props.isDisabled}); + if (prevProps.onSelectRow !== this.props.onSelectRow || prevProps.shouldDebounceRowSelect !== this.props.shouldDebounceRowSelect) { + this.updateOnSelectRow(); + } } componentWillUnmount() { @@ -127,6 +129,10 @@ class OptionRow extends Component { this.onSelectRow.cancel(); } + updateOnSelectRow() { + this.onSelectRow = this.props.shouldDebounceRowSelect && this.props.onSelectRow ? _.debounce(this.props.onSelectRow, 1000, {leading: true}) : this.props.onSelectRow; + } + render() { let pressableRef = null; const textStyle = this.props.optionIsFocused ? styles.sidebarLinkActiveText : styles.sidebarLinkText; @@ -177,6 +183,7 @@ class OptionRow extends Component { e.preventDefault(); } let result = this.onSelectRow(this.props.option, pressableRef); + result = this.onSelectRow(this.props.option, pressableRef); if (!(result instanceof Promise)) { result = Promise.resolve(); } From d375d2da4a08230a7f343a52d138ad12eb728643 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Tue, 22 Aug 2023 01:09:44 +0500 Subject: [PATCH 11/37] Removed extra call to onSelectRow --- src/components/OptionRow.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index 959e76147d04..77538a58600e 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -183,7 +183,6 @@ class OptionRow extends Component { e.preventDefault(); } let result = this.onSelectRow(this.props.option, pressableRef); - result = this.onSelectRow(this.props.option, pressableRef); if (!(result instanceof Promise)) { result = Promise.resolve(); } From 7be2135a893519f9191135fdc6bb3f9665d8e8a6 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Wed, 23 Aug 2023 04:35:13 +0500 Subject: [PATCH 12/37] Updated new selection list to conditionally debounce onSelectRow --- .../SelectionList/BaseSelectionList.js | 19 +++++++++++++++++-- .../SelectionList/selectionListPropTypes.js | 3 +++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index c7244093396e..16c377d65c07 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -1,4 +1,4 @@ -import React, {useEffect, useMemo, useRef, useState} from 'react'; +import React, {useEffect, useMemo, useRef, useState, useCallback} from 'react'; import {View} from 'react-native'; import _ from 'underscore'; import lodashGet from 'lodash/get'; @@ -32,6 +32,7 @@ function BaseSelectionList({ sections, canSelectMultiple = false, onSelectRow, + shouldDebounceRowSelect = false, onSelectAll, onDismissError, textInputLabel = '', @@ -145,6 +146,12 @@ function BaseSelectionList({ return defaultIndex; }); + // eslint-disable-next-line react-hooks/exhaustive-deps + const debouncedOnSelectRow = useCallback(shouldDebounceRowSelect ? _.debounce((item) => onSelectRow(item), 1000, {leading: true}) : (item) => onSelectRow(item), [ + shouldDebounceRowSelect, + onSelectRow, + ]); + /** * Scrolls to the desired item index in the section list * @@ -188,7 +195,7 @@ function BaseSelectionList({ } } - onSelectRow(item); + debouncedOnSelectRow(item); }; const selectFocusedOption = () => { @@ -268,6 +275,14 @@ function BaseSelectionList({ ); }; + // eslint-disable-next-line arrow-body-style + useEffect(() => { + return () => { + if (!(shouldDebounceRowSelect && debouncedOnSelectRow.cancel)) return; + debouncedOnSelectRow.cancel(); + }; + }, [debouncedOnSelectRow, shouldDebounceRowSelect]); + /** Focuses the text input when the component mounts. If `props.shouldDelayFocus` is true, we wait for the animation to finish */ useEffect(() => { if (shouldShowTextInput) { diff --git a/src/components/SelectionList/selectionListPropTypes.js b/src/components/SelectionList/selectionListPropTypes.js index 414a838d269f..d0d5cbb15602 100644 --- a/src/components/SelectionList/selectionListPropTypes.js +++ b/src/components/SelectionList/selectionListPropTypes.js @@ -103,6 +103,9 @@ const propTypes = { /** Callback to fire when a row is pressed */ onSelectRow: PropTypes.func.isRequired, + /** Boolean to indicate if onSelectRow should be debounced */ + shouldDebounceRowSelect: PropTypes.bool, + /** Callback to fire when "Select All" checkbox is pressed. Only use along with `canSelectMultiple` */ onSelectAll: PropTypes.func, From c57dbbadaf7ac02a341a1f093a634a831f70e8d4 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Mon, 28 Aug 2023 13:50:40 +0500 Subject: [PATCH 13/37] Added debounced row select to ThemePage --- src/pages/settings/Preferences/ThemePage.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/settings/Preferences/ThemePage.js b/src/pages/settings/Preferences/ThemePage.js index a260caa283e3..49a6a4b54f05 100644 --- a/src/pages/settings/Preferences/ThemePage.js +++ b/src/pages/settings/Preferences/ThemePage.js @@ -48,6 +48,7 @@ function ThemePage(props) { User.updateTheme(theme.value)} + shouldDebounceRowSelect initiallyFocusedOptionKey={_.find(localesToThemes, (theme) => theme.isSelected).keyForList} /> From 9d0d6978ec6e62c9125552fd2705d5571dd77f88 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Mon, 28 Aug 2023 13:50:51 +0500 Subject: [PATCH 14/37] Added debounced row select to CategoryPicker --- src/components/CategoryPicker/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/CategoryPicker/index.js b/src/components/CategoryPicker/index.js index 163ab6673ca2..df80509bc939 100644 --- a/src/components/CategoryPicker/index.js +++ b/src/components/CategoryPicker/index.js @@ -39,6 +39,7 @@ function CategoryPicker({policyCategories, reportID, iouType}) { contentContainerStyles={[safeAreaPaddingBottomStyle]} sections={sections} onSelectRow={navigateBack} + shouldDebounceRowSelect /> )} From 3712746c468e14a2184f2ca2db662e197e0c7164 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Mon, 28 Aug 2023 13:53:07 +0500 Subject: [PATCH 15/37] Updated early return syntax --- src/components/OptionRow.js | 5 ++++- src/components/SelectionList/BaseSelectionList.js | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index 77538a58600e..bcdadb5ed9d6 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -125,7 +125,10 @@ class OptionRow extends Component { } componentWillUnmount() { - if (!(this.props.shouldDebounceRowSelect && this.onSelectRow.cancel)) return; + if (!(this.props.shouldDebounceRowSelect && this.onSelectRow.cancel)) { + return; + } + this.onSelectRow.cancel(); } diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 16c377d65c07..0b7b8cbee19d 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -278,7 +278,10 @@ function BaseSelectionList({ // eslint-disable-next-line arrow-body-style useEffect(() => { return () => { - if (!(shouldDebounceRowSelect && debouncedOnSelectRow.cancel)) return; + if (!(shouldDebounceRowSelect && debouncedOnSelectRow.cancel)) { + return; + } + debouncedOnSelectRow.cancel(); }; }, [debouncedOnSelectRow, shouldDebounceRowSelect]); From 995f33d56fb796d8bd488bc7e91ec20b67994bf8 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Mon, 28 Aug 2023 13:53:50 +0500 Subject: [PATCH 16/37] Added comment explaining updateOnSelectRow in OptionRow --- src/components/OptionRow.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index bcdadb5ed9d6..86756f4ac178 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -119,6 +119,7 @@ class OptionRow extends Component { this.setState({isDisabled: this.props.isDisabled}); } + // update onRowSelect to be either the normal or debounced version whenever shouldDebounceRowSelect changes if (prevProps.onSelectRow !== this.props.onSelectRow || prevProps.shouldDebounceRowSelect !== this.props.shouldDebounceRowSelect) { this.updateOnSelectRow(); } @@ -132,6 +133,7 @@ class OptionRow extends Component { this.onSelectRow.cancel(); } + /** sets the onSelectRow callback to be either the normal or debounced version */ updateOnSelectRow() { this.onSelectRow = this.props.shouldDebounceRowSelect && this.props.onSelectRow ? _.debounce(this.props.onSelectRow, 1000, {leading: true}) : this.props.onSelectRow; } From 0abd5d2e94b884c6a97f8ee30917dc3f09757ae1 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed <68777211+huzaifa-99@users.noreply.github.com> Date: Mon, 28 Aug 2023 13:54:43 +0500 Subject: [PATCH 17/37] Cancel debounced function version when props change --- src/components/OptionRow.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index 86756f4ac178..a58c64564c8d 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -121,6 +121,11 @@ class OptionRow extends Component { // update onRowSelect to be either the normal or debounced version whenever shouldDebounceRowSelect changes if (prevProps.onSelectRow !== this.props.onSelectRow || prevProps.shouldDebounceRowSelect !== this.props.shouldDebounceRowSelect) { + // cancel the existing onSelectRow debounce if switched to use non-debounced version + if (prevProps.shouldDebounceRowSelect && !this.props.shouldDebounceRowSelect && this.onSelectRow) { + this.onSelectRow.cancel(); + } + this.updateOnSelectRow(); } } From 329767cb0344ba1b21f7fae09b8e6af6a1a14b99 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Mon, 28 Aug 2023 14:13:39 +0500 Subject: [PATCH 18/37] Removed unnecessary callback --- src/pages/settings/Profile/PronounsPage.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/pages/settings/Profile/PronounsPage.js b/src/pages/settings/Profile/PronounsPage.js index fb68fd2d98b7..4bf1e3fd0cf8 100644 --- a/src/pages/settings/Profile/PronounsPage.js +++ b/src/pages/settings/Profile/PronounsPage.js @@ -70,12 +70,9 @@ function PronounsPage(props) { /** * @param {Object} selectedPronouns */ - const updatePronouns = useCallback( - (selectedPronouns) => { - PersonalDetails.updatePronouns(selectedPronouns.keyForList === initiallyFocusedOption.keyForList ? '' : lodashGet(selectedPronouns, 'value', '')); - }, - [initiallyFocusedOption], - ); + const updatePronouns = (selectedPronouns) => { + PersonalDetails.updatePronouns(selectedPronouns.keyForList === initiallyFocusedOption.keyForList ? '' : lodashGet(selectedPronouns, 'value', '')); + }; /** * Pronouns list filtered by searchValue needed for the OptionsSelector. From b2b25faadaeecb4ccc9a101dd8b5f7890b8664f9 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Mon, 28 Aug 2023 18:37:20 +0500 Subject: [PATCH 19/37] Updated comments lettercase --- src/components/OptionRow.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index a58c64564c8d..911335df5abd 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -119,9 +119,9 @@ class OptionRow extends Component { this.setState({isDisabled: this.props.isDisabled}); } - // update onRowSelect to be either the normal or debounced version whenever shouldDebounceRowSelect changes + // Update onRowSelect to be either the normal or debounced version whenever shouldDebounceRowSelect changes if (prevProps.onSelectRow !== this.props.onSelectRow || prevProps.shouldDebounceRowSelect !== this.props.shouldDebounceRowSelect) { - // cancel the existing onSelectRow debounce if switched to use non-debounced version + // Cancel the existing onSelectRow debounce if switched to use non-debounced version if (prevProps.shouldDebounceRowSelect && !this.props.shouldDebounceRowSelect && this.onSelectRow) { this.onSelectRow.cancel(); } @@ -138,7 +138,7 @@ class OptionRow extends Component { this.onSelectRow.cancel(); } - /** sets the onSelectRow callback to be either the normal or debounced version */ + /** Sets the onSelectRow callback to be either the normal or debounced version */ updateOnSelectRow() { this.onSelectRow = this.props.shouldDebounceRowSelect && this.props.onSelectRow ? _.debounce(this.props.onSelectRow, 1000, {leading: true}) : this.props.onSelectRow; } From 44c5f323c421ce1a3ed41ae592dd1ce566b08ad8 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Mon, 28 Aug 2023 18:39:02 +0500 Subject: [PATCH 20/37] Fixed comment syntax --- src/components/OptionRow.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js index 911335df5abd..2249778d038e 100644 --- a/src/components/OptionRow.js +++ b/src/components/OptionRow.js @@ -138,7 +138,9 @@ class OptionRow extends Component { this.onSelectRow.cancel(); } - /** Sets the onSelectRow callback to be either the normal or debounced version */ + /** + * Sets the onSelectRow callback to be either the normal or debounced version + */ updateOnSelectRow() { this.onSelectRow = this.props.shouldDebounceRowSelect && this.props.onSelectRow ? _.debounce(this.props.onSelectRow, 1000, {leading: true}) : this.props.onSelectRow; } From 1f2d67abe81fb2ce639c9ab25194a6848b89134e Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Mon, 28 Aug 2023 18:45:56 +0500 Subject: [PATCH 21/37] Remove eslint disable rule --- src/components/SelectionList/BaseSelectionList.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 26c8268dc0a2..82166e93fdb5 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -273,13 +273,12 @@ function BaseSelectionList({ ); }; - // eslint-disable-next-line arrow-body-style useEffect(() => { - return () => { - if (!(shouldDebounceRowSelect && debouncedOnSelectRow.cancel)) { - return; - } + if (!(shouldDebounceRowSelect && debouncedOnSelectRow.cancel)) { + return; + } + return () => { debouncedOnSelectRow.cancel(); }; }, [debouncedOnSelectRow, shouldDebounceRowSelect]); From f5aacccbf819343822a800b3449b05a720fbcd4f Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Wed, 27 Sep 2023 15:53:51 +0500 Subject: [PATCH 22/37] Added debounce for arrow selection on selection list --- .../SelectionList/BaseSelectionList.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 9aba14edc6bf..c9395fc67611 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -222,6 +222,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. This is solved by running the debounce on trailing edge. + // eslint-disable-next-line react-hooks/exhaustive-deps + const debouncedSelectFocusedOption = useCallback(shouldDebounceRowSelect ? _.debounce(selectFocusedOption, 50) : selectFocusedOption, [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. @@ -303,6 +308,16 @@ function BaseSelectionList({ }; }, [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(() => { @@ -319,7 +334,7 @@ function BaseSelectionList({ ); /** Selects row when pressing Enter */ - useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ENTER, selectFocusedOption, { + useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ENTER, debouncedSelectFocusedOption, { captureOnInputs: true, shouldBubble: () => !flattenedSections.allOptions[focusedIndex], isActive: !shouldDisableHotkeys && isFocused, @@ -359,7 +374,7 @@ function BaseSelectionList({ keyboardType={keyboardType} selectTextOnFocus spellCheck={false} - onSubmitEditing={selectFocusedOption} + onSubmitEditing={debouncedSelectFocusedOption} /> )} From 57696cc34b8344932192fb5adcddfbbd1e3e7bf8 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Wed, 27 Sep 2023 16:02:49 +0500 Subject: [PATCH 23/37] Added row select debounce on tag picker --- src/components/TagPicker/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/TagPicker/index.js b/src/components/TagPicker/index.js index 8e7cf11f7e5a..05686cb44a19 100644 --- a/src/components/TagPicker/index.js +++ b/src/components/TagPicker/index.js @@ -70,6 +70,7 @@ function TagPicker({selectedTag, tag, policyTags, policyRecentlyUsedTags, onSubm initialFocusedIndex={initialFocusedIndex} onChangeText={setSearchValue} onSelectRow={onSubmit} + shouldDebounceRowSelect /> ); } From 21ce3df31f0c3aa55f823159ebfa44462cf516ea Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Tue, 10 Oct 2023 04:47:17 +0500 Subject: [PATCH 24/37] Updated debounce function --- src/components/SelectionList/BaseSelectionList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 806d7924973d..9bac5b2dd51c 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -243,7 +243,7 @@ function BaseSelectionList({ // 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. This is solved by running the debounce on trailing edge. // eslint-disable-next-line react-hooks/exhaustive-deps - const debouncedSelectFocusedOption = useCallback(shouldDebounceRowSelect ? _.debounce(selectFocusedOption, 50) : selectFocusedOption, [selectFocusedOption]); + const debouncedSelectFocusedOption = useCallback(shouldDebounceRowSelect ? _.debounce(selectFocusedOption, 50) : selectFocusedOption, [shouldDebounceRowSelect, selectFocusedOption]); /** * This function is used to compute the layout of any given item in our list. From 2b81ebf367c15e26920d2da52ad44959aa2e8939 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Wed, 11 Oct 2023 16:04:47 +0500 Subject: [PATCH 25/37] Use seperate callback for debounced func --- .../SelectionList/BaseSelectionList.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 9bac5b2dd51c..f4f1bba2087c 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -145,10 +145,7 @@ function BaseSelectionList({ const [focusedIndex, setFocusedIndex] = useState(() => _.findIndex(flattenedSections.allOptions, (option) => option.keyForList === initiallyFocusedOptionKey)); // eslint-disable-next-line react-hooks/exhaustive-deps - const debouncedOnSelectRow = useCallback(shouldDebounceRowSelect ? _.debounce((item) => onSelectRow(item), 1000, {leading: true}) : (item) => onSelectRow(item), [ - shouldDebounceRowSelect, - onSelectRow, - ]); + const debouncedOnSelectRow = useCallback(_.debounce(onSelectRow, 1000, {leading: true}), [onSelectRow]); // Disable `Enter` shortcut if the active element is a button or checkbox const disableEnterShortcut = activeElement && [CONST.ACCESSIBILITY_ROLE.BUTTON, CONST.ACCESSIBILITY_ROLE.CHECKBOX].includes(activeElement.role); @@ -216,7 +213,11 @@ function BaseSelectionList({ } } - debouncedOnSelectRow(item); + if (shouldDebounceRowSelect) { + debouncedOnSelectRow(item); + } else { + onSelectRow(item); + } if (shouldShowTextInput && shouldFocusOnSelectRow && textInputRef.current) { textInputRef.current.focus(); @@ -243,7 +244,7 @@ function BaseSelectionList({ // 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. This is solved by running the debounce on trailing edge. // eslint-disable-next-line react-hooks/exhaustive-deps - const debouncedSelectFocusedOption = useCallback(shouldDebounceRowSelect ? _.debounce(selectFocusedOption, 50) : selectFocusedOption, [shouldDebounceRowSelect, selectFocusedOption]); + const debouncedSelectFocusedOption = useCallback(_.debounce(selectFocusedOption, 50), [selectFocusedOption]); /** * This function is used to compute the layout of any given item in our list. @@ -367,7 +368,7 @@ function BaseSelectionList({ ); /** Selects row when pressing Enter */ - useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ENTER, debouncedSelectFocusedOption, { + useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ENTER, shouldDebounceRowSelect ? debouncedSelectFocusedOption : selectFocusedOption, { captureOnInputs: true, shouldBubble: () => !flattenedSections.allOptions[focusedIndex], isActive: !disableKeyboardShortcuts && !disableEnterShortcut && isFocused, @@ -410,7 +411,7 @@ function BaseSelectionList({ keyboardType={keyboardType} selectTextOnFocus spellCheck={false} - onSubmitEditing={debouncedSelectFocusedOption} + onSubmitEditing={shouldDebounceRowSelect ? debouncedSelectFocusedOption : selectFocusedOption} blurOnSubmit={Boolean(flattenedSections.allOptions.length)} /> From fe8f1855eba6f93da39d8fcaa4999a381768df64 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Wed, 24 Jan 2024 19:17:35 +0500 Subject: [PATCH 26/37] Added single execution logic on web --- .../index.native.ts => useSingleExecution.ts} | 0 src/hooks/useSingleExecution/index.ts | 22 ------------------- 2 files changed, 22 deletions(-) rename src/hooks/{useSingleExecution/index.native.ts => useSingleExecution.ts} (100%) delete mode 100644 src/hooks/useSingleExecution/index.ts diff --git a/src/hooks/useSingleExecution/index.native.ts b/src/hooks/useSingleExecution.ts similarity index 100% rename from src/hooks/useSingleExecution/index.native.ts rename to src/hooks/useSingleExecution.ts diff --git a/src/hooks/useSingleExecution/index.ts b/src/hooks/useSingleExecution/index.ts deleted file mode 100644 index 909416dd848b..000000000000 --- a/src/hooks/useSingleExecution/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import {useCallback} from 'react'; - -type Action = (...params: T) => void | Promise; - -/** - * This hook was specifically written for native issue - * more information: https://github.com/Expensify/App/pull/24614 https://github.com/Expensify/App/pull/24173 - * on web we don't need this mechanism so we just call the action directly. - */ -export default function useSingleExecution() { - const singleExecution = useCallback( - (action?: Action) => - (...params: T) => { - action?.(...params); - }, - [], - ); - - return {isExecuting: false, singleExecution}; -} - -export type {Action}; From 4e71b31fffb85a2e9a50c90c99f81ccb2e6946a7 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Wed, 24 Jan 2024 19:26:50 +0500 Subject: [PATCH 27/37] Removed debounced onRowSelect from OptionsList, OptionsSelector and OptionRow --- src/components/CategoryPicker/index.js | 1 - .../MoneyRequestConfirmationList.js | 1 - src/components/OptionRow.tsx | 25 +++---------------- .../OptionsList/BaseOptionsList.tsx | 2 -- src/components/OptionsList/types.ts | 3 --- .../OptionsSelector/BaseOptionsSelector.js | 1 - .../optionsSelectorPropTypes.js | 4 --- src/components/TagPicker/index.js | 1 - src/pages/NewChatPage.js | 1 - src/pages/ReportParticipantsPage.js | 1 - src/pages/SearchPage.js | 1 - .../report/ReactionList/BaseReactionList.js | 1 - src/pages/tasks/TaskAssigneeSelectorModal.js | 1 - .../TaskShareDestinationSelectorModal.js | 1 - 14 files changed, 3 insertions(+), 41 deletions(-) diff --git a/src/components/CategoryPicker/index.js b/src/components/CategoryPicker/index.js index fde6372eb832..a957e31a9de4 100644 --- a/src/components/CategoryPicker/index.js +++ b/src/components/CategoryPicker/index.js @@ -74,7 +74,6 @@ function CategoryPicker({selectedCategory, policyCategories, policyRecentlyUsedC isRowMultilineSupported onChangeText={setSearchValue} onSelectRow={onSubmit} - shouldDebounceRowSelect /> ); } diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 4d711273d318..590154b48bca 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -585,7 +585,6 @@ function MoneyRequestConfirmationList(props) { void | Promise; - /** Boolean to indicate if onSelectRow should be debounced */ - shouldDebounceRowSelect?: boolean; - /** Whether we should show the selected state */ showSelectedState?: boolean; @@ -91,7 +87,6 @@ type OptionRowProps = { function OptionRow({ option, onSelectRow, - shouldDebounceRowSelect = false, style, hoverStyle, selectedStateButtonText, @@ -118,23 +113,10 @@ function OptionRow({ const pressableRef = useRef(null); const [isDisabled, setIsDisabled] = useState(isOptionDisabled); - // eslint-disable-next-line react-hooks/exhaustive-deps - const debouncedOnSelectRow = useCallback(_.debounce(onSelectRow ?? (() => {}), 1000, {leading: true}), [onSelectRow]); - useEffect(() => { setIsDisabled(isOptionDisabled); }, [isOptionDisabled]); - useEffect(() => { - if (!(shouldDebounceRowSelect && debouncedOnSelectRow.cancel)) { - return; - } - - return () => { - debouncedOnSelectRow.cancel(); - }; - }, [debouncedOnSelectRow, shouldDebounceRowSelect]); - const text = option.text ?? ''; const fullTitle = isMultilineSupported ? text.trimStart() : text; const indentsLength = text.length - fullTitle.length; @@ -192,7 +174,7 @@ function OptionRow({ if (e) { e.preventDefault(); } - let result = shouldDebounceRowSelect ? debouncedOnSelectRow(option, pressableRef.current) : onSelectRow(option, pressableRef.current); + let result = onSelectRow(option, pressableRef.current); if (!(result instanceof Promise)) { result = Promise.resolve(); } @@ -347,6 +329,5 @@ export default React.memo( prevProps.option.ownerAccountID === nextProps.option.ownerAccountID && prevProps.option.subtitle === nextProps.option.subtitle && prevProps.option.pendingAction === nextProps.option.pendingAction && - prevProps.option.customIcon === nextProps.option.customIcon && - prevProps.shouldDebounceRowSelect === nextProps.shouldDebounceRowSelect, + prevProps.option.customIcon === nextProps.option.customIcon, ); diff --git a/src/components/OptionsList/BaseOptionsList.tsx b/src/components/OptionsList/BaseOptionsList.tsx index fbd2026c42f8..c1e4562a0c2d 100644 --- a/src/components/OptionsList/BaseOptionsList.tsx +++ b/src/components/OptionsList/BaseOptionsList.tsx @@ -44,7 +44,6 @@ function BaseOptionsList( onAddToSelection, highlightSelectedOptions = false, onSelectRow, - shouldDebounceRowSelect = false, boldStyle = false, isDisabled = false, isRowMultilineSupported = false, @@ -187,7 +186,6 @@ function BaseOptionsList( hoverStyle={optionHoveredStyle} optionIsFocused={!disableFocusOptions && !isItemDisabled && focusedIndex === index + section.indexOffset} onSelectRow={onSelectRow} - shouldDebounceRowSelect={shouldDebounceRowSelect} isSelected={isSelected} showSelectedState={canSelectMultipleOptions} shouldShowSelectedStateAsButton={shouldShowMultipleOptionSelectorAsButton} diff --git a/src/components/OptionsList/types.ts b/src/components/OptionsList/types.ts index e0ce138de4b1..12e44adb5800 100644 --- a/src/components/OptionsList/types.ts +++ b/src/components/OptionsList/types.ts @@ -62,9 +62,6 @@ type OptionsListProps = { /** Callback to fire when a row is selected */ onSelectRow?: (option: OptionData, refElement: View | HTMLDivElement | null) => void | Promise; - /** Boolean to indicate if onSelectRow should be debounced */ - shouldDebounceRowSelect?: boolean; - /** Optional header message */ headerMessage?: string; diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index 76125f3c29b2..412aeedcf965 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -542,7 +542,6 @@ class BaseOptionsSelector extends Component { ref={(el) => (this.list = el)} optionHoveredStyle={optionHoveredStyle} onSelectRow={this.props.onSelectRow ? this.selectRow : undefined} - shouldDebounceRowSelect={this.props.shouldDebounceRowSelect} sections={this.state.sections} focusedIndex={this.state.focusedIndex} selectedOptions={this.props.selectedOptions} diff --git a/src/components/OptionsSelector/optionsSelectorPropTypes.js b/src/components/OptionsSelector/optionsSelectorPropTypes.js index 19a4c11a7cb1..e52187fa76d7 100644 --- a/src/components/OptionsSelector/optionsSelectorPropTypes.js +++ b/src/components/OptionsSelector/optionsSelectorPropTypes.js @@ -7,9 +7,6 @@ const propTypes = { /** Callback to fire when a row is tapped */ onSelectRow: PropTypes.func, - /** Boolean to indicate if onSelectRow should be debounced */ - shouldDebounceRowSelect: PropTypes.bool, - /** Sections for the section list */ sections: PropTypes.arrayOf( PropTypes.shape({ @@ -141,7 +138,6 @@ const propTypes = { const defaultProps = { onSelectRow: undefined, - shouldDebounceRowSelect: false, textInputLabel: '', placeholderText: '', inputMode: CONST.INPUT_MODE.TEXT, diff --git a/src/components/TagPicker/index.js b/src/components/TagPicker/index.js index 341acd2b936b..e258472eae93 100644 --- a/src/components/TagPicker/index.js +++ b/src/components/TagPicker/index.js @@ -76,7 +76,6 @@ function TagPicker({selectedTag, tag, policyTags, policyRecentlyUsedTags, should initiallyFocusedOptionKey={selectedOptionKey} onChangeText={setSearchValue} onSelectRow={onSubmit} - shouldDebounceRowSelect /> ); } diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 99c578c26a4f..b90ce6bbc247 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -264,7 +264,6 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i sections={sections} selectedOptions={selectedOptions} onSelectRow={createChat} - shouldDebounceRowSelect onChangeText={setSearchTermAndSearchInServer} headerMessage={headerMessage} boldStyle diff --git a/src/pages/ReportParticipantsPage.js b/src/pages/ReportParticipantsPage.js index b9a9ab6a20e7..7dbc1c7036c4 100755 --- a/src/pages/ReportParticipantsPage.js +++ b/src/pages/ReportParticipantsPage.js @@ -123,7 +123,6 @@ function ReportParticipantsPage(props) { onSelectRow={(option) => { Navigation.navigate(ROUTES.PROFILE.getRoute(option.accountID)); }} - shouldDebounceRowSelect hideSectionHeaders showTitleTooltip showScrollIndicator diff --git a/src/pages/SearchPage.js b/src/pages/SearchPage.js index 95953526487d..c420371f5a65 100755 --- a/src/pages/SearchPage.js +++ b/src/pages/SearchPage.js @@ -182,7 +182,6 @@ function SearchPage({betas, personalDetails, reports, isSearchingForReports, nav Date: Wed, 24 Jan 2024 19:28:43 +0500 Subject: [PATCH 28/37] Added shouldDebounceRowSelect on all SelectionLists with single item select --- src/components/SelectionList/BaseSelectionList.js | 2 +- src/pages/SearchPage/index.js | 1 + src/pages/iou/IOUCurrencySelection.js | 2 +- .../MoneyTemporaryForRefactorRequestParticipantsSelector.js | 1 + src/pages/iou/request/step/IOURequestStepCurrency.js | 1 + .../settings/Profile/PersonalDetails/CountrySelectionPage.js | 1 + src/pages/settings/Report/NotificationPreferencePage.js | 2 +- src/pages/settings/Report/WriteCapabilityPage.js | 2 +- src/pages/workspace/WorkspaceSettingsCurrencyPage.js | 1 + 9 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.js b/src/components/SelectionList/BaseSelectionList.js index 83c92b3b88f5..936cc256779e 100644 --- a/src/components/SelectionList/BaseSelectionList.js +++ b/src/components/SelectionList/BaseSelectionList.js @@ -261,7 +261,7 @@ function BaseSelectionList({ // 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. This is solved by running the debounce on trailing edge. // eslint-disable-next-line react-hooks/exhaustive-deps - const debouncedSelectFocusedOption = useCallback(_.debounce(selectFocusedOption, 50), [selectFocusedOption]); + const debouncedSelectFocusedOption = useCallback(_.debounce(selectFocusedOption, 100), [selectFocusedOption]); /** * This function is used to compute the layout of any given item in our list. diff --git a/src/pages/SearchPage/index.js b/src/pages/SearchPage/index.js index 211f3622e06c..a1fcbba381fe 100644 --- a/src/pages/SearchPage/index.js +++ b/src/pages/SearchPage/index.js @@ -155,6 +155,7 @@ function SearchPage({betas, reports}) { onLayout={setPerformanceTimersEnd} autoFocus onSelectRow={selectReport} + shouldDebounceRowSelect showLoadingPlaceholder={!didScreenTransitionEnd || !isOptionsDataReady} footerContent={SearchPageFooterInstance} /> diff --git a/src/pages/iou/IOUCurrencySelection.js b/src/pages/iou/IOUCurrencySelection.js index c507dec0c811..4e42d0cc2998 100644 --- a/src/pages/iou/IOUCurrencySelection.js +++ b/src/pages/iou/IOUCurrencySelection.js @@ -168,13 +168,13 @@ function IOUCurrencySelection(props) { textInputLabel={translate('common.search')} textInputValue={searchValue} onChangeText={setSearchValue} - shouldDebounceRowSelect onSelectRow={(option) => { if (!didScreenTransitionEnd) { return; } confirmCurrencySelection(option); }} + shouldDebounceRowSelect headerMessage={headerMessage} initiallyFocusedOptionKey={initiallyFocusedOptionKey} showScrollIndicator diff --git a/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js b/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js index 0949081435c4..cbea833a59ac 100644 --- a/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js +++ b/src/pages/iou/request/MoneyTemporaryForRefactorRequestParticipantsSelector.js @@ -333,6 +333,7 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({ onChangeText={setSearchTermAndSearchInServer} shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} onSelectRow={addSingleParticipant} + shouldDebounceRowSelect footerContent={footerContent} headerMessage={headerMessage} showLoadingPlaceholder={isSearchingForReports} diff --git a/src/pages/iou/request/step/IOURequestStepCurrency.js b/src/pages/iou/request/step/IOURequestStepCurrency.js index b4281de4d16e..353407309c86 100644 --- a/src/pages/iou/request/step/IOURequestStepCurrency.js +++ b/src/pages/iou/request/step/IOURequestStepCurrency.js @@ -141,6 +141,7 @@ function IOURequestStepCurrency({ } confirmCurrencySelection(option); }} + shouldDebounceRowSelect headerMessage={headerMessage} initiallyFocusedOptionKey={initiallyFocusedOptionKey} showScrollIndicator diff --git a/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.js b/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.js index 38c4d1eac449..f4bf59a4e277 100644 --- a/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.js +++ b/src/pages/settings/Profile/PersonalDetails/CountrySelectionPage.js @@ -94,6 +94,7 @@ function CountrySelectionPage({route, navigation}) { textInputValue={searchValue} sections={[{data: searchResults, indexOffset: 0}]} onSelectRow={selectCountry} + shouldDebounceRowSelect onChangeText={setSearchValue} initiallyFocusedOptionKey={currentCountry} shouldUseDynamicMaxToRenderPerBatch diff --git a/src/pages/settings/Report/NotificationPreferencePage.js b/src/pages/settings/Report/NotificationPreferencePage.js index dfcdb57acc7c..81e598b08aec 100644 --- a/src/pages/settings/Report/NotificationPreferencePage.js +++ b/src/pages/settings/Report/NotificationPreferencePage.js @@ -43,10 +43,10 @@ function NotificationPreferencePage(props) { /> Report.updateNotificationPreference(props.report.reportID, props.report.notificationPreference, option.value, true, undefined, undefined, props.report) } + shouldDebounceRowSelect initiallyFocusedOptionKey={_.find(notificationPreferenceOptions, (locale) => locale.isSelected).keyForList} /> diff --git a/src/pages/settings/Report/WriteCapabilityPage.js b/src/pages/settings/Report/WriteCapabilityPage.js index 69f4437a9ffb..cdc59819396d 100644 --- a/src/pages/settings/Report/WriteCapabilityPage.js +++ b/src/pages/settings/Report/WriteCapabilityPage.js @@ -52,8 +52,8 @@ function WriteCapabilityPage(props) { /> Report.updateWriteCapabilityAndNavigate(props.report, option.value)} + shouldDebounceRowSelect initiallyFocusedOptionKey={_.find(writeCapabilityOptions, (locale) => locale.isSelected).keyForList} /> diff --git a/src/pages/workspace/WorkspaceSettingsCurrencyPage.js b/src/pages/workspace/WorkspaceSettingsCurrencyPage.js index ce1e1d7b8966..f8fa8cc1a7b4 100644 --- a/src/pages/workspace/WorkspaceSettingsCurrencyPage.js +++ b/src/pages/workspace/WorkspaceSettingsCurrencyPage.js @@ -96,6 +96,7 @@ function WorkspaceSettingsCurrencyPage({currencyList, policy, isLoadingReportDat textInputValue={searchText} onChangeText={setSearchText} onSelectRow={onSelectCurrency} + shouldDebounceRowSelect headerMessage={headerMessage} initiallyFocusedOptionKey={initiallyFocusedOptionKey} showScrollIndicator From 019e70697e2fa775f15b8b497f5f47781ab55d68 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Mon, 29 Jan 2024 18:01:51 +0500 Subject: [PATCH 29/37] Fix type export --- src/components/MenuItemList.tsx | 2 +- src/hooks/useSingleExecution.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/MenuItemList.tsx b/src/components/MenuItemList.tsx index 4ba9260e23ff..87b157085506 100644 --- a/src/components/MenuItemList.tsx +++ b/src/components/MenuItemList.tsx @@ -50,7 +50,7 @@ function MenuItemList({menuItems = [], shouldUseSingleExecution = false}: MenuIt // eslint-disable-next-line react/jsx-props-no-spreading {...menuItemProps} disabled={!!menuItemProps.disabled || isExecuting} - onPress={shouldUseSingleExecution ? singleExecution(menuItemProps.onPress) : menuItemProps.onPress} + onPress={shouldUseSingleExecution && menuItemProps.onPress ? singleExecution(menuItemProps.onPress) : menuItemProps.onPress} /> ))} diff --git a/src/hooks/useSingleExecution.ts b/src/hooks/useSingleExecution.ts index 16a98152def1..8cf061465136 100644 --- a/src/hooks/useSingleExecution.ts +++ b/src/hooks/useSingleExecution.ts @@ -38,3 +38,5 @@ export default function useSingleExecution() { return {isExecuting, singleExecution}; } + +export type {Action}; From 1a69275c184726d1b9cc05406eee2b570a4769a3 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Wed, 7 Feb 2024 22:54:34 +0500 Subject: [PATCH 30/37] Fix type --- src/components/MenuItemGroup.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MenuItemGroup.tsx b/src/components/MenuItemGroup.tsx index 8dc8586028d8..ed34778dd941 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; }; From dfe0c261617676d64df5c34ad3dd2d3a9cadb95b Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Fri, 1 Mar 2024 20:48:14 +0500 Subject: [PATCH 31/37] Revert useSingleExecution on web --- .../index.native.ts} | 4 +--- src/hooks/useSingleExecution/index.ts | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) rename src/hooks/{useSingleExecution.ts => useSingleExecution/index.native.ts} (98%) create mode 100644 src/hooks/useSingleExecution/index.ts diff --git a/src/hooks/useSingleExecution.ts b/src/hooks/useSingleExecution/index.native.ts similarity index 98% rename from src/hooks/useSingleExecution.ts rename to src/hooks/useSingleExecution/index.native.ts index 8cf061465136..d5f6839427f3 100644 --- a/src/hooks/useSingleExecution.ts +++ b/src/hooks/useSingleExecution/index.native.ts @@ -37,6 +37,4 @@ export default function useSingleExecution() { ); return {isExecuting, singleExecution}; -} - -export type {Action}; +} \ No newline at end of file diff --git a/src/hooks/useSingleExecution/index.ts b/src/hooks/useSingleExecution/index.ts new file mode 100644 index 000000000000..ba316290b7cb --- /dev/null +++ b/src/hooks/useSingleExecution/index.ts @@ -0,0 +1,22 @@ +import {useCallback} from 'react'; + +type Action = (...params: T) => void | Promise; + +/** + * This hook was specifically written for native issue + * more information: https://github.com/Expensify/App/pull/24614 https://github.com/Expensify/App/pull/24173 + * on web we don't need this mechanism so we just call the action directly. + */ +export default function useSingleExecution() { + const singleExecution = useCallback( + (action?: Action) => + (...params: T) => { + action?.(...params); + }, + [], + ); + + return {isExecuting: false, singleExecution}; +} + +export type {Action}; \ No newline at end of file From bfd87a22a64f80574edf7ca545d4302530bbb446 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Fri, 1 Mar 2024 21:07:15 +0500 Subject: [PATCH 32/37] Lint --- src/hooks/useSingleExecution/index.native.ts | 2 +- src/hooks/useSingleExecution/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/useSingleExecution/index.native.ts b/src/hooks/useSingleExecution/index.native.ts index d5f6839427f3..16a98152def1 100644 --- a/src/hooks/useSingleExecution/index.native.ts +++ b/src/hooks/useSingleExecution/index.native.ts @@ -37,4 +37,4 @@ export default function useSingleExecution() { ); return {isExecuting, singleExecution}; -} \ No newline at end of file +} diff --git a/src/hooks/useSingleExecution/index.ts b/src/hooks/useSingleExecution/index.ts index ba316290b7cb..909416dd848b 100644 --- a/src/hooks/useSingleExecution/index.ts +++ b/src/hooks/useSingleExecution/index.ts @@ -19,4 +19,4 @@ export default function useSingleExecution() { return {isExecuting: false, singleExecution}; } -export type {Action}; \ No newline at end of file +export type {Action}; From 2f8f685095b96321bd063ce9b9d6df92922a1064 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Fri, 1 Mar 2024 22:45:56 +0500 Subject: [PATCH 33/37] Added shouldDebounceRowSelect to new pages --- .../BusinessTypePicker/BusinessTypeSelectorModal.tsx | 1 + src/pages/settings/Report/VisibilityPage.tsx | 1 + src/pages/tasks/TaskAssigneeSelectorModal.js | 1 + src/pages/tasks/TaskShareDestinationSelectorModal.js | 1 + .../workspace/reimburse/WorkspaceRateAndUnitPage/UnitPage.tsx | 1 + .../workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx | 1 + 6 files changed, 6 insertions(+) diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/TypeBusiness/BusinessTypePicker/BusinessTypeSelectorModal.tsx index 2db3a4fdf7ad..6f87c4d154a0 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, indexOffset: 0}]} initiallyFocusedOptionKey={currentBusinessType} onSelectRow={onBusinessTypeSelected} + shouldDebounceRowSelect shouldStopPropagation shouldUseDynamicMaxToRenderPerBatch ListItem={RadioListItem} diff --git a/src/pages/settings/Report/VisibilityPage.tsx b/src/pages/settings/Report/VisibilityPage.tsx index d3b8b2656d50..9bcf3b05e83a 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/tasks/TaskAssigneeSelectorModal.js b/src/pages/tasks/TaskAssigneeSelectorModal.js index d6b5d2e62a35..5e266c4aa5db 100644 --- a/src/pages/tasks/TaskAssigneeSelectorModal.js +++ b/src/pages/tasks/TaskAssigneeSelectorModal.js @@ -210,6 +210,7 @@ function TaskAssigneeSelectorModal({reports, task, rootParentReportPolicy}) { sections={didScreenTransitionEnd && !isLoading ? sections : CONST.EMPTY_ARRAY} ListItem={UserListItem} onSelectRow={selectReport} + shouldDebounceRowSelect onChangeText={onChangeText} textInputValue={searchValue} headerMessage={headerMessage} diff --git a/src/pages/tasks/TaskShareDestinationSelectorModal.js b/src/pages/tasks/TaskShareDestinationSelectorModal.js index b62440b22967..db6e86bf49d1 100644 --- a/src/pages/tasks/TaskShareDestinationSelectorModal.js +++ b/src/pages/tasks/TaskShareDestinationSelectorModal.js @@ -98,6 +98,7 @@ function TaskShareDestinationSelectorModal({reports, isSearchingForReports}) { ListItem={UserListItem} sections={didScreenTransitionEnd ? options.sections : CONST.EMPTY_ARRAY} onSelectRow={selectReportHandler} + shouldDebounceRowSelect onChangeText={setSearchValue} textInputValue={searchValue} headerMessage={options.headerMessage} diff --git a/src/pages/workspace/reimburse/WorkspaceRateAndUnitPage/UnitPage.tsx b/src/pages/workspace/reimburse/WorkspaceRateAndUnitPage/UnitPage.tsx index 3bd5a9e01bab..15a762d7475e 100644 --- a/src/pages/workspace/reimburse/WorkspaceRateAndUnitPage/UnitPage.tsx +++ b/src/pages/workspace/reimburse/WorkspaceRateAndUnitPage/UnitPage.tsx @@ -93,6 +93,7 @@ function WorkspaceUnitPage(props: WorkspaceUnitPageProps) { sections={[{data: unitOptions}]} ListItem={RadioListItem} onSelectRow={(unit: OptionRow) => updateUnit(unit.value)} + shouldDebounceRowSelect initiallyFocusedOptionKey={unitOptions.find((unit) => unit.isSelected)?.keyForList} /> diff --git a/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx b/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx index 84d70e799c42..988e67cfd88f 100644 --- a/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage.tsx @@ -90,6 +90,7 @@ function WorkspaceAutoReportingMonthlyOffsetPage({policy}: WorkspaceAutoReportin headerMessage={headerMessage} ListItem={RadioListItem} onSelectRow={onSelectDayOfMonth} + shouldDebounceRowSelect initiallyFocusedOptionKey={offset.toString()} showScrollIndicator /> From dda25b6ad180d5191c6e2b785d8357b2a8b02130 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Tue, 2 Apr 2024 16:33:27 +0500 Subject: [PATCH 34/37] Added debounce to new components --- .../members/WorkspaceMemberDetailsRoleSelectionPage.tsx | 1 + src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx | 1 + src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx | 1 + 3 files changed, 3 insertions(+) diff --git a/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx b/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx index 7958ae93b922..273d1016e651 100644 --- a/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx +++ b/src/pages/workspace/members/WorkspaceMemberDetailsRoleSelectionPage.tsx @@ -73,6 +73,7 @@ function WorkspaceMemberDetailsRoleSelectionPage({policyMembers, route}: Workspa sections={[{data: items}]} ListItem={RadioListItem} onSelectRow={changeRole} + shouldDebounceRowSelect initiallyFocusedOptionKey={items.find((item) => item.isSelected)?.keyForList} /> diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx index 089099d12ce7..330a2c91d531 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsApproverPage.tsx @@ -192,6 +192,7 @@ function WorkspaceWorkflowsApproverPage({policy, policyMembers, personalDetails, 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 e96b19ce4442..983ab8181608 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx @@ -214,6 +214,7 @@ function WorkspaceWorkflowsPayerPage({route, policy, policyMembers, personalDeta headerMessage={headerMessage} ListItem={UserListItem} onSelectRow={setPolicyAuthorizedPayer} + shouldDebounceRowSelect showScrollIndicator /> From f626b5eef28bf7dd1b05d507a8e897192b265a05 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Fri, 17 May 2024 16:41:31 +0500 Subject: [PATCH 35/37] Added `shouldDebounceRowSelect` to newer components --- src/components/MoneyRequestConfirmationList.tsx | 1 + src/components/Search.tsx | 1 + src/pages/NewChatPage.tsx | 1 + src/pages/ReportParticipantRoleSelectionPage.tsx | 1 + src/pages/ReportParticipantsPage.tsx | 1 + src/pages/WorkspaceSwitcherPage/index.tsx | 1 + src/pages/iou/request/step/IOURequestStepDistanceRate.tsx | 1 + src/pages/iou/request/step/IOURequestStepSendFrom.tsx | 1 + src/pages/iou/request/step/IOURequestStepSplitPayer.tsx | 1 + src/pages/settings/AboutPage/ShareLogList/BaseShareLogList.tsx | 1 + .../settings/Profile/PersonalDetails/StateSelectionPage.tsx | 1 + src/pages/workspace/WorkspaceMembersPage.tsx | 1 + .../accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx | 1 + .../qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx | 1 + .../export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx | 1 + .../qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx | 1 + .../accounting/qbo/export/QuickbooksExportDateSelectPage.tsx | 1 + .../qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx | 1 + .../export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx | 1 + .../qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx | 1 + .../qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx | 1 + .../qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx | 1 + .../accounting/xero/XeroMapCostCentersToConfigurationPage.tsx | 1 + .../accounting/xero/XeroMapRegionsToConfigurationPage.tsx | 1 + .../accounting/xero/XeroOrganizationConfigurationPage.tsx | 1 + src/pages/workspace/tags/WorkspaceTagsPage.tsx | 1 + 26 files changed, 26 insertions(+) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 33f1258e60c7..7a11fc2204be 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -1229,6 +1229,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 27e87017bfee..6f3bcacf1023 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/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index 555a7c855d42..b2008ecc2cca 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -309,6 +309,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/ReportParticipantRoleSelectionPage.tsx b/src/pages/ReportParticipantRoleSelectionPage.tsx index 6d8c5d951064..e6a42188e54a 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 a3670d722b34..121c80738b4e 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 d9b9d62bb539..c8c830e530f8 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/step/IOURequestStepDistanceRate.tsx b/src/pages/iou/request/step/IOURequestStepDistanceRate.tsx index 1b9ccf1876cf..a7ebe843e8ab 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 46d8a1ce36af..3bbff502d917 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 c2ee404b1205..48aa4789d6bb 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 05ec664fb4c0..7c874e4efd22 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/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index bf1bb8ad197e..8003c2ce767f 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -105,6 +105,7 @@ function StateSelectionPage() { 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 e9cc481eb23e..f96daaefff47 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 346c74e35fe8..4c1eba8f2167 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 4f757eab253f..a40dc86c051d 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 98d81a480ddd..892a84f9dfde 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 16e9a20668c5..4e162c8984b3 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 b7c95811b90a..5f72beb8d89f 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 729914176a0d..5264f6c0c45e 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 ebac7546341a..e9944a289922 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 612fc3755ada..1c74b146eea5 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 a55b293fc3a1..ee61b2be1fb9 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 b4f0fe04f6ce..eec922522468 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 bb5870da8fc3..e5ec85b05c3a 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 1c4b9373c67e..85b0f20071ab 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/tags/WorkspaceTagsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsPage.tsx index eca339be0fc4..a26ba2565f13 100644 --- a/src/pages/workspace/tags/WorkspaceTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsPage.tsx @@ -335,6 +335,7 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) { sections={[{data: tagList, isDisabled: false}]} onCheckboxPress={toggleTag} onSelectRow={navigateToTagSettings} + shouldDebounceRowSelect={!canSelectMultiple} onSelectAll={toggleAllTags} ListItem={TableListItem} customListHeader={getCustomListHeader()} From 7c9240b98bd221e1b2ba2f53a93c4bf3741bca22 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Sun, 26 May 2024 20:30:58 +0500 Subject: [PATCH 36/37] Removed unnecessary logical check --- src/components/MenuItemList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MenuItemList.tsx b/src/components/MenuItemList.tsx index 87b157085506..4ba9260e23ff 100644 --- a/src/components/MenuItemList.tsx +++ b/src/components/MenuItemList.tsx @@ -50,7 +50,7 @@ function MenuItemList({menuItems = [], shouldUseSingleExecution = false}: MenuIt // eslint-disable-next-line react/jsx-props-no-spreading {...menuItemProps} disabled={!!menuItemProps.disabled || isExecuting} - onPress={shouldUseSingleExecution && menuItemProps.onPress ? singleExecution(menuItemProps.onPress) : menuItemProps.onPress} + onPress={shouldUseSingleExecution ? singleExecution(menuItemProps.onPress) : menuItemProps.onPress} /> ))} From 8dcd2824d6300719cdc90aa74267a5d002f1a511 Mon Sep 17 00:00:00 2001 From: Huzaifa Rasheed Date: Sun, 26 May 2024 20:32:32 +0500 Subject: [PATCH 37/37] Updated comment --- src/components/SelectionList/BaseSelectionList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 9cd807f7c8ec..c142aae9675c 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -308,7 +308,7 @@ function BaseSelectionList( }; // 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. This is solved by running the debounce on trailing edge. + // enter presses runs the debounced function again. // eslint-disable-next-line react-hooks/exhaustive-deps const debouncedSelectFocusedOption = useCallback(lodashDebounce(selectFocusedOption, 100), [selectFocusedOption]);