From ee4608ee04de563df07512bb1a2bd9e20057f295 Mon Sep 17 00:00:00 2001 From: Sylvan Mably Date: Fri, 8 Mar 2024 20:08:30 -0500 Subject: [PATCH] Fix flaky search behaviour with minimized left pane --- ts/components/LeftPane.stories.tsx | 6 +++ ts/components/LeftPane.tsx | 6 +++ ts/components/LeftPaneSearchInput.tsx | 33 +++++++++----- .../leftPane/LeftPaneArchiveHelper.tsx | 11 +++++ ts/components/leftPane/LeftPaneHelper.tsx | 2 + .../leftPane/LeftPaneInboxHelper.tsx | 12 +++++ .../leftPane/LeftPaneSearchHelper.tsx | 12 +++++ ts/state/ducks/search.ts | 45 ++++++++++++++++++- ts/state/selectors/search.ts | 2 +- ts/state/smart/LeftPane.tsx | 10 +++-- .../leftPane/LeftPaneArchiveHelper_test.ts | 1 + .../leftPane/LeftPaneInboxHelper_test.tsx | 1 + .../leftPane/LeftPaneSearchHelper_test.ts | 30 +++++++++++++ 13 files changed, 154 insertions(+), 17 deletions(-) diff --git a/ts/components/LeftPane.stories.tsx b/ts/components/LeftPane.stories.tsx index 4099a9baa9..aa861b5a2a 100644 --- a/ts/components/LeftPane.stories.tsx +++ b/ts/components/LeftPane.stories.tsx @@ -62,6 +62,7 @@ const defaultConversations: Array = [ ]; const defaultSearchProps = { + isSearchingGlobally: true, searchConversation: undefined, searchDisabled: false, searchTerm: 'hello', @@ -145,6 +146,8 @@ const useProps = (overrideProps: OverridePropsType = {}): PropsType => { composeReplaceAvatar: action('composeReplaceAvatar'), composeSaveAvatarToDisk: action('composeSaveAvatarToDisk'), createGroup: action('createGroup'), + endConversationSearch: action('endConversationSearch'), + endSearch: action('endSearch'), getPreferredBadge: () => undefined, hasFailedStorySends: false, hasPendingUpdate: false, @@ -608,6 +611,7 @@ export function ArchiveNoArchivedConversations(): JSX.Element { modeSpecificProps: { mode: LeftPaneMode.Archive, archivedConversations: [], + isSearchingGlobally: false, searchConversation: undefined, searchTerm: '', startSearchCounter: 0, @@ -624,6 +628,7 @@ export function ArchiveArchivedConversations(): JSX.Element { modeSpecificProps: { mode: LeftPaneMode.Archive, archivedConversations: defaultConversations, + isSearchingGlobally: false, searchConversation: undefined, searchTerm: '', startSearchCounter: 0, @@ -640,6 +645,7 @@ export function ArchiveSearchingAConversation(): JSX.Element { modeSpecificProps: { mode: LeftPaneMode.Archive, archivedConversations: defaultConversations, + isSearchingGlobally: false, searchConversation: undefined, searchTerm: '', startSearchCounter: 0, diff --git a/ts/components/LeftPane.tsx b/ts/components/LeftPane.tsx index 5fdb86bf5c..144a1d875f 100644 --- a/ts/components/LeftPane.tsx +++ b/ts/components/LeftPane.tsx @@ -121,6 +121,8 @@ export type PropsType = { composeReplaceAvatar: ReplaceAvatarActionType; composeSaveAvatarToDisk: SaveAvatarToDiskActionType; createGroup: () => void; + endConversationSearch: () => void; + endSearch: () => void; navTabsCollapsed: boolean; openUsernameReservationModal: () => void; onOutgoingAudioCallInConversation: (conversationId: string) => void; @@ -184,6 +186,8 @@ export function LeftPane({ composeSaveAvatarToDisk, crashReportCount, createGroup, + endConversationSearch, + endSearch, getPreferredBadge, hasExpiredDialog, hasFailedStorySends, @@ -705,6 +709,8 @@ export function LeftPane({ {helper.getSearchInput({ clearConversationSearch, clearSearch, + endConversationSearch, + endSearch, i18n, onChangeComposeSearchTerm: event => { setComposeSearchTerm(event.target.value); diff --git a/ts/components/LeftPaneSearchInput.tsx b/ts/components/LeftPaneSearchInput.tsx index f38f656924..a0699223f9 100644 --- a/ts/components/LeftPaneSearchInput.tsx +++ b/ts/components/LeftPaneSearchInput.tsx @@ -15,7 +15,10 @@ type PropsType = { clearConversationSearch: () => void; clearSearch: () => void; disabled?: boolean; + endConversationSearch: () => void; + endSearch: () => void; i18n: LocalizerType; + isSearchingGlobally: boolean; onEnterKeyDown?: ( clearSearch: () => void, showConversation: ShowConversationType @@ -31,7 +34,10 @@ export function LeftPaneSearchInput({ clearConversationSearch, clearSearch, disabled, + endConversationSearch, + endSearch, i18n, + isSearchingGlobally, onEnterKeyDown, searchConversation, searchTerm, @@ -46,6 +52,7 @@ export function LeftPaneSearchInput({ searchConversation?.id ); const prevSearchCounter = usePrevious(startSearchCounter, startSearchCounter); + const wasSearchingGlobally = usePrevious(false, isSearchingGlobally); useEffect(() => { // When user chooses to search in a given conversation we focus the field for them @@ -56,7 +63,10 @@ export function LeftPaneSearchInput({ inputRef.current?.focus(); } // When user chooses to start a new search, we focus the field - if (startSearchCounter !== prevSearchCounter) { + if ( + (isSearchingGlobally && !wasSearchingGlobally) || + startSearchCounter !== prevSearchCounter + ) { inputRef.current?.select(); } }, [ @@ -64,6 +74,8 @@ export function LeftPaneSearchInput({ prevSearchCounter, searchConversation, startSearchCounter, + isSearchingGlobally, + wasSearchingGlobally, ]); const changeValue = (nextSearchTerm: string) => { @@ -82,11 +94,6 @@ export function LeftPaneSearchInput({ } }; - const clearAndFocus = () => { - clearSearch(); - inputRef.current?.focus(); - }; - const label = searchConversation ? i18n('icu:searchIn') : i18n('icu:search'); return ( @@ -98,7 +105,7 @@ export function LeftPaneSearchInput({ moduleClassName="LeftPaneSearchInput" onBlur={() => { if (!searchConversation && !searchTerm) { - clearSearch(); + endSearch(); } }} onKeyDown={event => { @@ -112,10 +119,14 @@ export function LeftPaneSearchInput({ changeValue(event.currentTarget.value); }} onClear={() => { - if (searchConversation && searchTerm) { - changeValue(''); + if (searchTerm) { + clearSearch(); + inputRef.current?.focus(); + } else if (searchConversation) { + endConversationSearch(); + inputRef.current?.focus(); } else { - clearAndFocus(); + inputRef.current?.blur(); } }} ref={inputRef} @@ -151,7 +162,7 @@ export function LeftPaneSearchInput({