From 47b9f1a82ed6d5d66098eabb0519001b394d6684 Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 15 Apr 2024 13:37:34 +0200 Subject: [PATCH 1/8] mvp --- .../BaseAutoCompleteSuggestions.tsx | 17 +++++++- .../AutoCompleteSuggestions/types.ts | 3 ++ src/components/MentionSuggestions.tsx | 14 ++++++- .../SearchForRoomsToMentionParams.ts | 6 +++ src/libs/API/parameters/index.ts | 1 + src/libs/API/types.ts | 2 + src/libs/actions/Report.ts | 15 ++++--- .../ReportActionCompose/SuggestionMention.tsx | 42 ++++++++----------- 8 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 src/libs/API/parameters/SearchForRoomsToMentionParams.ts diff --git a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx index ccd0f21626a0..0b4007389caf 100644 --- a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx +++ b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx @@ -2,12 +2,14 @@ import {FlashList} from '@shopify/flash-list'; import type {ForwardedRef, ReactElement} from 'react'; import React, {forwardRef, useCallback, useEffect, useMemo, useRef} from 'react'; import type {View} from 'react-native'; +import {ActivityIndicator} from 'react-native'; // We take ScrollView from this package to properly handle the scrolling of AutoCompleteSuggestions in chats since one scroll is nested inside another import {ScrollView} from 'react-native-gesture-handler'; import Animated, {Easing, FadeOutDown, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; import ColorSchemeWrapper from '@components/ColorSchemeWrapper'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import useStyleUtils from '@hooks/useStyleUtils'; +import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import variables from '@styles/variables'; @@ -39,11 +41,13 @@ function BaseAutoCompleteSuggestions( suggestions, isSuggestionPickerLarge, keyExtractor, + isSearchingForMentions, }: AutoCompleteSuggestionsProps, ref: ForwardedRef, ) { const {windowWidth, isLargeScreenWidth} = useWindowDimensions(); const styles = useThemeStyles(); + const theme = useTheme(); const StyleUtils = useStyleUtils(); const rowHeight = useSharedValue(0); const scrollRef = useRef>(null); @@ -77,11 +81,11 @@ function BaseAutoCompleteSuggestions( [isLargeScreenWidth, suggestions.length, windowWidth], ); useEffect(() => { - rowHeight.value = withTiming(measureHeightOfSuggestionRows(suggestions.length, isSuggestionPickerLarge), { + rowHeight.value = withTiming(measureHeightOfSuggestionRows(suggestions.length + (isSearchingForMentions ? 1 : 0), isSuggestionPickerLarge), { duration: 100, easing: Easing.inOut(Easing.ease), }); - }, [suggestions.length, isSuggestionPickerLarge, rowHeight]); + }, [suggestions.length, isSuggestionPickerLarge, rowHeight, isSearchingForMentions]); useEffect(() => { if (!scrollRef.current) { @@ -109,6 +113,15 @@ function BaseAutoCompleteSuggestions( removeClippedSubviews={false} showsVerticalScrollIndicator={innerHeight > rowHeight.value} extraData={[highlightedSuggestionIndex, renderSuggestionMenuItem]} + ListFooterComponent={ + isSearchingForMentions ? ( + + ) : undefined + } /> diff --git a/src/components/AutoCompleteSuggestions/types.ts b/src/components/AutoCompleteSuggestions/types.ts index 61d614dcf2e4..e35731d7062c 100644 --- a/src/components/AutoCompleteSuggestions/types.ts +++ b/src/components/AutoCompleteSuggestions/types.ts @@ -33,6 +33,9 @@ type AutoCompleteSuggestionsProps = { /** Meaures the parent container's position and dimensions. */ measureParentContainer?: (callback: MeasureParentContainerCallback) => void; + + /** Show ActivityIndicator when searching for mentions */ + isSearchingForMentions?: boolean; }; export type {AutoCompleteSuggestionsProps, RenderSuggestionMenuItemProps}; diff --git a/src/components/MentionSuggestions.tsx b/src/components/MentionSuggestions.tsx index 3866911fff9e..3296fdac9487 100644 --- a/src/components/MentionSuggestions.tsx +++ b/src/components/MentionSuggestions.tsx @@ -55,6 +55,9 @@ type MentionSuggestionsProps = { /** Measures the parent container's position and dimensions. */ measureParentContainer: (callback: MeasureInWindowOnSuccessCallback) => void; + + /** Show ActivityIndicator when searching for mentions */ + isSearchingForMentions?: boolean; }; /** @@ -62,7 +65,15 @@ type MentionSuggestionsProps = { */ const keyExtractor = (item: Mention) => item.alternateText; -function MentionSuggestions({prefix, mentions, highlightedMentionIndex = 0, onSelect, isMentionPickerLarge, measureParentContainer = () => {}}: MentionSuggestionsProps) { +function MentionSuggestions({ + prefix, + mentions, + highlightedMentionIndex = 0, + onSelect, + isMentionPickerLarge, + measureParentContainer = () => {}, + isSearchingForMentions, +}: MentionSuggestionsProps) { const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); @@ -148,6 +159,7 @@ function MentionSuggestions({prefix, mentions, highlightedMentionIndex = 0, onSe isSuggestionPickerLarge={isMentionPickerLarge} accessibilityLabelExtractor={keyExtractor} measureParentContainer={measureParentContainer} + isSearchingForMentions={isSearchingForMentions} /> ); } diff --git a/src/libs/API/parameters/SearchForRoomsToMentionParams.ts b/src/libs/API/parameters/SearchForRoomsToMentionParams.ts new file mode 100644 index 000000000000..db0411954766 --- /dev/null +++ b/src/libs/API/parameters/SearchForRoomsToMentionParams.ts @@ -0,0 +1,6 @@ +type SearchForRoomsToMentionParams = { + searchInput: string; + policyID: string; +}; + +export default SearchForRoomsToMentionParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 385aabf8acff..7cbc8a774014 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -47,6 +47,7 @@ export type {default as RequestAccountValidationLinkParams} from './RequestAccou export type {default as ResolveActionableMentionWhisperParams} from './ResolveActionableMentionWhisperParams'; export type {default as RevealExpensifyCardDetailsParams} from './RevealExpensifyCardDetailsParams'; export type {default as SearchForReportsParams} from './SearchForReportsParams'; +export type {default as SearchForRoomsToMentionParams} from './SearchForRoomsToMentionParams'; export type {default as SendPerformanceTimingParams} from './SendPerformanceTimingParams'; export type {default as SetContactMethodAsDefaultParams} from './SetContactMethodAsDefaultParams'; export type {default as SignInUserWithLinkParams} from './SignInUserWithLinkParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 91b95dd6327e..991e2f7ec95f 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -428,6 +428,7 @@ const READ_COMMANDS = { GET_REPORT_PRIVATE_NOTE: 'GetReportPrivateNote', OPEN_ROOM_MEMBERS_PAGE: 'OpenRoomMembersPage', SEARCH_FOR_REPORTS: 'SearchForReports', + SEARCH_FOR_ROOMS_TO_MENTION: 'SearchForRoomsToMention', SEND_PERFORMANCE_TIMING: 'SendPerformanceTiming', GET_ROUTE: 'GetRoute', GET_ROUTE_FOR_DRAFT: 'GetRouteForDraft', @@ -468,6 +469,7 @@ type ReadCommandParameters = { [READ_COMMANDS.GET_REPORT_PRIVATE_NOTE]: Parameters.GetReportPrivateNoteParams; [READ_COMMANDS.OPEN_ROOM_MEMBERS_PAGE]: Parameters.OpenRoomMembersPageParams; [READ_COMMANDS.SEARCH_FOR_REPORTS]: Parameters.SearchForReportsParams; + [READ_COMMANDS.SEARCH_FOR_ROOMS_TO_MENTION]: Parameters.SearchForRoomsToMentionParams; [READ_COMMANDS.SEND_PERFORMANCE_TIMING]: Parameters.SendPerformanceTimingParams; [READ_COMMANDS.GET_ROUTE]: Parameters.GetRouteParams; [READ_COMMANDS.GET_ROUTE_FOR_DRAFT]: Parameters.GetRouteParams; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 1e59cf21f542..1abb0fb25b36 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -33,6 +33,7 @@ import type { RemoveFromRoomParams, ResolveActionableMentionWhisperParams, SearchForReportsParams, + SearchForRoomsToMentionParams, SetNameValuePairParams, TogglePinnedChatParams, UpdateCommentParams, @@ -3062,7 +3063,7 @@ function savePrivateNotesDraft(reportID: string, note: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT}${reportID}`, note); } -function searchForReports(searchInput: string) { +function searchForReports(searchInput: string, policyID?: string) { // We do not try to make this request while offline because it sets a loading indicator optimistically if (isNetworkOffline) { Onyx.set(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, false); @@ -3085,12 +3086,16 @@ function searchForReports(searchInput: string) { }, ]; - const parameters: SearchForReportsParams = {searchInput}; + const searchForRoomToMentionParams: SearchForRoomsToMentionParams = {searchInput, policyID: policyID ?? ''}; + const searchForReportsParams: SearchForReportsParams = {searchInput}; - API.read(READ_COMMANDS.SEARCH_FOR_REPORTS, parameters, {successData, failureData}); + API.read(policyID ? READ_COMMANDS.SEARCH_FOR_ROOMS_TO_MENTION : READ_COMMANDS.SEARCH_FOR_REPORTS, policyID ? searchForRoomToMentionParams : searchForReportsParams, { + successData, + failureData, + }); } -function searchInServer(searchInput: string) { +function searchInServer(searchInput: string, policyID?: string) { if (isNetworkOffline || !searchInput.trim().length) { Onyx.set(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, false); return; @@ -3100,7 +3105,7 @@ function searchInServer(searchInput: string) { // we want to show the loading state right away. Otherwise, we will see a flashing UI where the client options are sorted and // tell the user there are no options, then we start searching, and tell them there are no options again. Onyx.set(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, true); - searchForReports(searchInput); + searchForReports(searchInput, policyID); } function updateLastVisitTime(reportID: string) { diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx index 147799ee118b..7ba9660cf711 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx @@ -1,8 +1,8 @@ import Str from 'expensify-common/lib/str'; import lodashSortBy from 'lodash/sortBy'; -import type {ForwardedRef, RefAttributes} from 'react'; +import type {ForwardedRef} from 'react'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import type {OnyxCollection} from 'react-native-onyx'; import * as Expensicons from '@components/Icon/Expensicons'; import type {Mention} from '@components/MentionSuggestions'; @@ -17,6 +17,7 @@ import * as ReportUtils from '@libs/ReportUtils'; import * as SuggestionsUtils from '@libs/SuggestionUtils'; import * as UserUtils from '@libs/UserUtils'; import {isValidRoomName} from '@libs/ValidationUtils'; +import * as ReportUserActions from '@userActions/Report'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetailsList, Report} from '@src/types/onyx'; @@ -31,11 +32,6 @@ type SuggestionValues = { prefixType: string; }; -type RoomMentionOnyxProps = { - /** All reports shared with the user */ - reports: OnyxCollection; -}; - /** * Check if this piece of string looks like a mention */ @@ -50,26 +46,18 @@ const defaultSuggestionsValues: SuggestionValues = { }; function SuggestionMention( - { - value, - selection, - setSelection, - updateComment, - isAutoSuggestionPickerLarge, - measureParentContainer, - isComposerFocused, - reports, - isGroupPolicyReport, - policyID, - }: SuggestionProps & RoomMentionOnyxProps, + {value, selection, setSelection, updateComment, isAutoSuggestionPickerLarge, measureParentContainer, isComposerFocused, isGroupPolicyReport, policyID}: SuggestionProps, ref: ForwardedRef, ) { const personalDetails = usePersonalDetails() ?? CONST.EMPTY_OBJECT; const {translate, formatPhoneNumber} = useLocalize(); const [suggestionValues, setSuggestionValues] = useState(defaultSuggestionsValues); + const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); + const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - const isMentionSuggestionsMenuVisible = !!suggestionValues.suggestedMentions.length && suggestionValues.shouldShowSuggestionMenu; + const isMentionSuggestionsMenuVisible = (!!suggestionValues.suggestedMentions.length || (isSearchingForReports ?? false)) && suggestionValues.shouldShowSuggestionMenu; const [highlightedMentionIndex, setHighlightedMentionIndex] = useArrowKeyFocusManager({ isActive: isMentionSuggestionsMenuVisible, @@ -354,6 +342,13 @@ function SuggestionMention( calculateMentionSuggestion(selection.end); }, [selection, calculateMentionSuggestion]); + useEffect(() => { + const foundSuggestionsCount = suggestionValues.suggestedMentions.length; + if (suggestionValues.prefixType === '#' && foundSuggestionsCount < 5) { + ReportUserActions.searchInServer(value, policyID); + } + }, [suggestionValues.suggestedMentions, policyID, suggestionValues.prefixType, value]); + const updateShouldShowSuggestionMenuToFalse = useCallback(() => { setSuggestionValues((prevState) => { if (prevState.shouldShowSuggestionMenu) { @@ -396,14 +391,11 @@ function SuggestionMention( onSelect={insertSelectedMention} isMentionPickerLarge={!!isAutoSuggestionPickerLarge} measureParentContainer={measureParentContainer} + isSearchingForMentions={isSearchingForReports ?? false} /> ); } SuggestionMention.displayName = 'SuggestionMention'; -export default withOnyx, RoomMentionOnyxProps>({ - reports: { - key: ONYXKEYS.COLLECTION.REPORT, - }, -})(forwardRef(SuggestionMention)); +export default forwardRef(SuggestionMention); From d99842f5212efe5d6b973f3e9ef93981f710faaf Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 15 Apr 2024 14:23:36 +0200 Subject: [PATCH 2/8] do not show suggestions after one was chosen --- .../home/report/ReportActionCompose/SuggestionMention.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx index 7ba9660cf711..31aa14422864 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx @@ -125,6 +125,7 @@ function SuggestionMention( setSuggestionValues((prevState) => ({ ...prevState, suggestedMentions: [], + shouldShowSuggestionMenu: false, })); }, [ @@ -324,9 +325,8 @@ function SuggestionMention( const shouldDisplayRoomMentionsSuggestions = isGroupPolicyReport && (isValidRoomName(suggestionWord.toLowerCase()) || prefix === ''); if (!isCursorBeforeTheMention && prefixType === '#' && shouldDisplayRoomMentionsSuggestions) { // filter reports by room name and current policy - const filteredRoomMentions = getRoomMentionOptions(prefix, reports); - nextState.suggestedMentions = filteredRoomMentions; - nextState.shouldShowSuggestionMenu = !!filteredRoomMentions.length; + nextState.suggestedMentions = getRoomMentionOptions(prefix, reports); + nextState.shouldShowSuggestionMenu = true; } setSuggestionValues((prevState) => ({ @@ -347,7 +347,7 @@ function SuggestionMention( if (suggestionValues.prefixType === '#' && foundSuggestionsCount < 5) { ReportUserActions.searchInServer(value, policyID); } - }, [suggestionValues.suggestedMentions, policyID, suggestionValues.prefixType, value]); + }, [suggestionValues.suggestedMentions.length, suggestionValues.prefixType, policyID, value]); const updateShouldShowSuggestionMenuToFalse = useCallback(() => { setSuggestionValues((prevState) => { From b43c4ee4b2ed064966a6b99a354cdbc5c3f2fcb8 Mon Sep 17 00:00:00 2001 From: Robert Kozik Date: Thu, 18 Apr 2024 11:55:41 +0200 Subject: [PATCH 3/8] add initial value for useOnyx & add comments --- .../BaseAutoCompleteSuggestions.tsx | 5 ++++- .../home/report/ReportActionCompose/SuggestionMention.tsx | 8 +++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx index 0b4007389caf..4e355663fee3 100644 --- a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx +++ b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx @@ -81,7 +81,10 @@ function BaseAutoCompleteSuggestions( [isLargeScreenWidth, suggestions.length, windowWidth], ); useEffect(() => { - rowHeight.value = withTiming(measureHeightOfSuggestionRows(suggestions.length + (isSearchingForMentions ? 1 : 0), isSuggestionPickerLarge), { + // add 1 to the expected row number if we are searching for mentions - this will add place for loading spinner at the bottom of the list + const expectedRowNumber = suggestions.length + (isSearchingForMentions ? 1 : 0); + + rowHeight.value = withTiming(measureHeightOfSuggestionRows(expectedRowNumber, isSuggestionPickerLarge), { duration: 100, easing: Easing.inOut(Easing.ease), }); diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx index 31aa14422864..1b1047530b27 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx @@ -54,10 +54,10 @@ function SuggestionMention( const [suggestionValues, setSuggestionValues] = useState(defaultSuggestionsValues); const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); - const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS); + const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initialValue: false}); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - const isMentionSuggestionsMenuVisible = (!!suggestionValues.suggestedMentions.length || (isSearchingForReports ?? false)) && suggestionValues.shouldShowSuggestionMenu; + const isMentionSuggestionsMenuVisible = (!!suggestionValues.suggestedMentions.length || isSearchingForReports) && suggestionValues.shouldShowSuggestionMenu; const [highlightedMentionIndex, setHighlightedMentionIndex] = useArrowKeyFocusManager({ isActive: isMentionSuggestionsMenuVisible, @@ -326,6 +326,8 @@ function SuggestionMention( if (!isCursorBeforeTheMention && prefixType === '#' && shouldDisplayRoomMentionsSuggestions) { // filter reports by room name and current policy nextState.suggestedMentions = getRoomMentionOptions(prefix, reports); + + // even if there are no reports, we should show the suggestion menu - to perform live search nextState.shouldShowSuggestionMenu = true; } @@ -391,7 +393,7 @@ function SuggestionMention( onSelect={insertSelectedMention} isMentionPickerLarge={!!isAutoSuggestionPickerLarge} measureParentContainer={measureParentContainer} - isSearchingForMentions={isSearchingForReports ?? false} + isSearchingForMentions={isSearchingForReports} /> ); } From 7baf5e1657a1a33c0d810a8e802724c29d843f1b Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 19 Apr 2024 12:29:45 +0200 Subject: [PATCH 4/8] debounce searchInServer --- .../ReportActionCompose/SuggestionMention.tsx | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx index 9a35b0fb3000..fb612daa393f 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx @@ -10,6 +10,7 @@ import MentionSuggestions from '@components/MentionSuggestions'; import {usePersonalDetails} from '@components/OnyxProvider'; import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; +import useDebounce from '@hooks/useDebounce'; import useLocalize from '@hooks/useLocalize'; import * as LoginUtils from '@libs/LoginUtils'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; @@ -78,6 +79,18 @@ function SuggestionMention( // Used to decide whether to block the suggestions list from showing to prevent flickering const shouldBlockCalc = useRef(false); + /** + * Search for reports suggestions in server. + * + * The function is debounced to not perform requests on every keystroke. + */ + const debouncedSearchInServer = useDebounce(() => { + const foundSuggestionsCount = suggestionValues.suggestedMentions.length; + if (suggestionValues.prefixType === '#' && foundSuggestionsCount < 5) { + ReportUserActions.searchInServer(value, policyID); + } + }, CONST.TIMING.SEARCH_OPTION_LIST_DEBOUNCE_TIME); + const formatLoginPrivateDomain = useCallback( (displayText = '', userLogin = '') => { if (userLogin !== displayText) { @@ -312,10 +325,10 @@ function SuggestionMention( const shouldDisplayRoomMentionsSuggestions = isGroupPolicyReport && (isValidRoomName(suggestionWord.toLowerCase()) || prefix === ''); if (prefixType === '#' && shouldDisplayRoomMentionsSuggestions) { - // filter reports by room name and current policy + // Filter reports by room name and current policy nextState.suggestedMentions = getRoomMentionOptions(prefix, reports); - // even if there are no reports, we should show the suggestion menu - to perform live search + // Even if there are no reports, we should show the suggestion menu - to perform live search nextState.shouldShowSuggestionMenu = true; } @@ -333,11 +346,8 @@ function SuggestionMention( }, [selection, calculateMentionSuggestion]); useEffect(() => { - const foundSuggestionsCount = suggestionValues.suggestedMentions.length; - if (suggestionValues.prefixType === '#' && foundSuggestionsCount < 5) { - ReportUserActions.searchInServer(value, policyID); - } - }, [suggestionValues.suggestedMentions.length, suggestionValues.prefixType, policyID, value]); + debouncedSearchInServer(); + }, [suggestionValues.suggestedMentions.length, suggestionValues.prefixType, policyID, value, debouncedSearchInServer]); const updateShouldShowSuggestionMenuToFalse = useCallback(() => { setSuggestionValues((prevState) => { From dfbb8c90be00c774eba4845174eb27e22b851c34 Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 19 Apr 2024 12:30:04 +0200 Subject: [PATCH 5/8] align search indicator to left --- .../AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx index 4e355663fee3..8d06d9e32f87 100644 --- a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx +++ b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx @@ -81,7 +81,7 @@ function BaseAutoCompleteSuggestions( [isLargeScreenWidth, suggestions.length, windowWidth], ); useEffect(() => { - // add 1 to the expected row number if we are searching for mentions - this will add place for loading spinner at the bottom of the list + // Add 1 to the expected row number if we are searching for mentions - this will add place for loading spinner at the bottom of the list const expectedRowNumber = suggestions.length + (isSearchingForMentions ? 1 : 0); rowHeight.value = withTiming(measureHeightOfSuggestionRows(expectedRowNumber, isSuggestionPickerLarge), { @@ -125,6 +125,7 @@ function BaseAutoCompleteSuggestions( /> ) : undefined } + ListFooterComponentStyle={[styles.ml4, styles.alignSelfStart]} /> From e9d051588cef9a74eb54b9051c14fcd07f18e77e Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 19 Apr 2024 17:11:40 +0200 Subject: [PATCH 6/8] fix missing server calls --- .../ReportActionCompose/SuggestionMention.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx index fb612daa393f..34610811f3f2 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx @@ -84,12 +84,15 @@ function SuggestionMention( * * The function is debounced to not perform requests on every keystroke. */ - const debouncedSearchInServer = useDebounce(() => { - const foundSuggestionsCount = suggestionValues.suggestedMentions.length; - if (suggestionValues.prefixType === '#' && foundSuggestionsCount < 5) { - ReportUserActions.searchInServer(value, policyID); - } - }, CONST.TIMING.SEARCH_OPTION_LIST_DEBOUNCE_TIME); + const debouncedSearchInServer = useDebounce( + useCallback(() => { + const foundSuggestionsCount = suggestionValues.suggestedMentions.length; + if (suggestionValues.prefixType === '#' && foundSuggestionsCount < 5) { + ReportUserActions.searchInServer(value, policyID); + } + }, [suggestionValues.suggestedMentions.length, suggestionValues.prefixType, policyID, value]), + CONST.TIMING.SEARCH_OPTION_LIST_DEBOUNCE_TIME, + ); const formatLoginPrivateDomain = useCallback( (displayText = '', userLogin = '') => { From fcf70cb7f5d5a00d0e1838189ce9d0e3f38b31e7 Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 22 Apr 2024 17:27:31 +0200 Subject: [PATCH 7/8] remove loading indicator --- .../BaseAutoCompleteSuggestions.tsx | 21 ++----------------- .../AutoCompleteSuggestions/types.ts | 3 --- src/components/MentionSuggestions.tsx | 14 +------------ .../ReportActionCompose/SuggestionMention.tsx | 4 +--- 4 files changed, 4 insertions(+), 38 deletions(-) diff --git a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx index 8d06d9e32f87..ccd0f21626a0 100644 --- a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx +++ b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.tsx @@ -2,14 +2,12 @@ import {FlashList} from '@shopify/flash-list'; import type {ForwardedRef, ReactElement} from 'react'; import React, {forwardRef, useCallback, useEffect, useMemo, useRef} from 'react'; import type {View} from 'react-native'; -import {ActivityIndicator} from 'react-native'; // We take ScrollView from this package to properly handle the scrolling of AutoCompleteSuggestions in chats since one scroll is nested inside another import {ScrollView} from 'react-native-gesture-handler'; import Animated, {Easing, FadeOutDown, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; import ColorSchemeWrapper from '@components/ColorSchemeWrapper'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import useStyleUtils from '@hooks/useStyleUtils'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import variables from '@styles/variables'; @@ -41,13 +39,11 @@ function BaseAutoCompleteSuggestions( suggestions, isSuggestionPickerLarge, keyExtractor, - isSearchingForMentions, }: AutoCompleteSuggestionsProps, ref: ForwardedRef, ) { const {windowWidth, isLargeScreenWidth} = useWindowDimensions(); const styles = useThemeStyles(); - const theme = useTheme(); const StyleUtils = useStyleUtils(); const rowHeight = useSharedValue(0); const scrollRef = useRef>(null); @@ -81,14 +77,11 @@ function BaseAutoCompleteSuggestions( [isLargeScreenWidth, suggestions.length, windowWidth], ); useEffect(() => { - // Add 1 to the expected row number if we are searching for mentions - this will add place for loading spinner at the bottom of the list - const expectedRowNumber = suggestions.length + (isSearchingForMentions ? 1 : 0); - - rowHeight.value = withTiming(measureHeightOfSuggestionRows(expectedRowNumber, isSuggestionPickerLarge), { + rowHeight.value = withTiming(measureHeightOfSuggestionRows(suggestions.length, isSuggestionPickerLarge), { duration: 100, easing: Easing.inOut(Easing.ease), }); - }, [suggestions.length, isSuggestionPickerLarge, rowHeight, isSearchingForMentions]); + }, [suggestions.length, isSuggestionPickerLarge, rowHeight]); useEffect(() => { if (!scrollRef.current) { @@ -116,16 +109,6 @@ function BaseAutoCompleteSuggestions( removeClippedSubviews={false} showsVerticalScrollIndicator={innerHeight > rowHeight.value} extraData={[highlightedSuggestionIndex, renderSuggestionMenuItem]} - ListFooterComponent={ - isSearchingForMentions ? ( - - ) : undefined - } - ListFooterComponentStyle={[styles.ml4, styles.alignSelfStart]} /> diff --git a/src/components/AutoCompleteSuggestions/types.ts b/src/components/AutoCompleteSuggestions/types.ts index e35731d7062c..61d614dcf2e4 100644 --- a/src/components/AutoCompleteSuggestions/types.ts +++ b/src/components/AutoCompleteSuggestions/types.ts @@ -33,9 +33,6 @@ type AutoCompleteSuggestionsProps = { /** Meaures the parent container's position and dimensions. */ measureParentContainer?: (callback: MeasureParentContainerCallback) => void; - - /** Show ActivityIndicator when searching for mentions */ - isSearchingForMentions?: boolean; }; export type {AutoCompleteSuggestionsProps, RenderSuggestionMenuItemProps}; diff --git a/src/components/MentionSuggestions.tsx b/src/components/MentionSuggestions.tsx index 3296fdac9487..3866911fff9e 100644 --- a/src/components/MentionSuggestions.tsx +++ b/src/components/MentionSuggestions.tsx @@ -55,9 +55,6 @@ type MentionSuggestionsProps = { /** Measures the parent container's position and dimensions. */ measureParentContainer: (callback: MeasureInWindowOnSuccessCallback) => void; - - /** Show ActivityIndicator when searching for mentions */ - isSearchingForMentions?: boolean; }; /** @@ -65,15 +62,7 @@ type MentionSuggestionsProps = { */ const keyExtractor = (item: Mention) => item.alternateText; -function MentionSuggestions({ - prefix, - mentions, - highlightedMentionIndex = 0, - onSelect, - isMentionPickerLarge, - measureParentContainer = () => {}, - isSearchingForMentions, -}: MentionSuggestionsProps) { +function MentionSuggestions({prefix, mentions, highlightedMentionIndex = 0, onSelect, isMentionPickerLarge, measureParentContainer = () => {}}: MentionSuggestionsProps) { const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); @@ -159,7 +148,6 @@ function MentionSuggestions({ isSuggestionPickerLarge={isMentionPickerLarge} accessibilityLabelExtractor={keyExtractor} measureParentContainer={measureParentContainer} - isSearchingForMentions={isSearchingForMentions} /> ); } diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx index 34610811f3f2..dbd550e1cd7c 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx @@ -55,10 +55,9 @@ function SuggestionMention( const [suggestionValues, setSuggestionValues] = useState(defaultSuggestionsValues); const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); - const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initialValue: false}); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - const isMentionSuggestionsMenuVisible = (!!suggestionValues.suggestedMentions.length || isSearchingForReports) && suggestionValues.shouldShowSuggestionMenu; + const isMentionSuggestionsMenuVisible = !!suggestionValues.suggestedMentions.length && suggestionValues.shouldShowSuggestionMenu; const [highlightedMentionIndex, setHighlightedMentionIndex] = useArrowKeyFocusManager({ isActive: isMentionSuggestionsMenuVisible, @@ -394,7 +393,6 @@ function SuggestionMention( onSelect={insertSelectedMention} isMentionPickerLarge={!!isAutoSuggestionPickerLarge} measureParentContainer={measureParentContainer} - isSearchingForMentions={isSearchingForReports} /> ); } From 91d22c1207b18562e138937119e92ae847446a2a Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 23 Apr 2024 08:43:14 +0200 Subject: [PATCH 8/8] fix request params --- src/libs/API/parameters/SearchForRoomsToMentionParams.ts | 2 +- src/libs/actions/Report.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/API/parameters/SearchForRoomsToMentionParams.ts b/src/libs/API/parameters/SearchForRoomsToMentionParams.ts index db0411954766..6a4efe7aed6b 100644 --- a/src/libs/API/parameters/SearchForRoomsToMentionParams.ts +++ b/src/libs/API/parameters/SearchForRoomsToMentionParams.ts @@ -1,5 +1,5 @@ type SearchForRoomsToMentionParams = { - searchInput: string; + query: string; policyID: string; }; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index eb5f504cb08e..9de059acd1d7 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -3450,7 +3450,7 @@ function searchForReports(searchInput: string, policyID?: string) { }, ]; - const searchForRoomToMentionParams: SearchForRoomsToMentionParams = {searchInput, policyID: policyID ?? ''}; + const searchForRoomToMentionParams: SearchForRoomsToMentionParams = {query: searchInput, policyID: policyID ?? ''}; const searchForReportsParams: SearchForReportsParams = {searchInput}; API.read(policyID ? READ_COMMANDS.SEARCH_FOR_ROOMS_TO_MENTION : READ_COMMANDS.SEARCH_FOR_REPORTS, policyID ? searchForRoomToMentionParams : searchForReportsParams, {