Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/components/Search/SearchContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const defaultSearchContextData: SearchContextData = {
selectedReports: [],
isOnSearch: false,
shouldTurnOffSelectionMode: false,
shouldResetSearchQuery: false,
};

const defaultSearchContext: SearchContext = {
Expand All @@ -31,6 +32,7 @@ const defaultSearchContext: SearchContext = {
setShouldShowFiltersBarLoading: () => {},
shouldShowSelectAllMatchingItems: () => {},
selectAllMatchingItems: () => {},
setShouldResetSearchQuery: () => {},
};

const Context = React.createContext<SearchContext>(defaultSearchContext);
Expand Down Expand Up @@ -173,6 +175,13 @@ function SearchContextProvider({children}: ChildrenProps) {
[searchContextData.selectedTransactionIDs, searchContextData.selectedTransactions],
);

const setShouldResetSearchQuery = useCallback((shouldReset: boolean) => {
setSearchContextData((prevState) => ({
...prevState,
shouldResetSearchQuery: shouldReset,
}));
}, []);

const searchContext = useMemo<SearchContext>(
() => ({
...searchContextData,
Expand All @@ -188,6 +197,7 @@ function SearchContextProvider({children}: ChildrenProps) {
shouldShowSelectAllMatchingItems,
areAllMatchingItemsSelected,
selectAllMatchingItems,
setShouldResetSearchQuery,
}),
[
searchContextData,
Expand All @@ -200,6 +210,7 @@ function SearchContextProvider({children}: ChildrenProps) {
shouldShowSelectAllMatchingItems,
showSelectAllMatchingItems,
areAllMatchingItemsSelected,
setShouldResetSearchQuery,
],
);

Expand Down
7 changes: 6 additions & 1 deletion src/components/Search/SearchRouter/SearchRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {usePersonalDetails} from '@components/OnyxListItemProvider';
import type {AnimatedTextInputRef} from '@components/RNTextInput';
import type {GetAdditionalSectionsCallback} from '@components/Search/SearchAutocompleteList';
import SearchAutocompleteList from '@components/Search/SearchAutocompleteList';
import {useSearchContext} from '@components/Search/SearchContext';
import SearchInputSelectionWrapper from '@components/Search/SearchInputSelectionWrapper';
import type {SearchQueryString} from '@components/Search/types';
import type {SearchQueryItem} from '@components/SelectionList/Search/SearchQueryListItem';
Expand Down Expand Up @@ -82,6 +83,7 @@ type SearchRouterProps = {
function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDisplayed}: SearchRouterProps, ref: React.Ref<View>) {
const {translate} = useLocalize();
const styles = useThemeStyles();
const {setShouldResetSearchQuery} = useSearchContext();
const [, recentSearchesMetadata] = useOnyx(ONYXKEYS.RECENT_SEARCHES, {canBeMissing: true});
const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true});
const personalDetails = usePersonalDetails();
Expand Down Expand Up @@ -259,6 +261,9 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
return;
}

// Reset the search query flag when performing a new search
setShouldResetSearchQuery(false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@huult Could you please explain why this is needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For case 3, I used a flag to control resetting the query to the default. As I checked, we don’t have any flag to indicate when the app restarts, so I introduced this flag to differentiate between restarting the app or using the top-right corner search. This ensures the query is reset correctly.

if (hasErrors && (currentRoute === '/' ||

This condition means that if we have an error, the search route is not initialized, and the search page is already mounted, then the query should be reset. This prevents the case where a search error occurs but no error page is displayed because the error was reset. This condition ensures that scenario is handled correctly.

(shouldResetSearchQuery && currentRoute === '/search'))) {

Next, when we have an error but the search data is undefined due to restarting the app, we must wait for the search route to initialize before resetting the query. Therefore, we need a flag to determine when the query should be reset.

(shouldResetSearchQuery && currentRoute === '/search'))) {

Lastly, when we restart the app and use the top-right corner search with a valid query, we don’t need to reset the query. This condition handles that case.

Case 3:

Open the Expensify app.
Navigate to the Reports tab.
Enter a search query, for example: type:abcd.
Switch to another tab, such as Workspace or Account, or go to Account → Troubleshoot → Clear cache and restart.
Tap the Search icon at the top-right corner and search for something (e.g., abcd).
Verify that:

  • No error page is displayed.
  • The user is navigated to Reports/Chats with the search results displayed.

backHistory(() => {
onRouterClose();
Navigation.navigate(ROUTES.SEARCH_ROOT.getRoute({query: updatedQuery}));
Expand All @@ -267,7 +272,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
setTextInputValue('');
setAutocompleteQueryValue('');
},
[autocompleteSubstitutions, onRouterClose, setTextInputValue],
[autocompleteSubstitutions, onRouterClose, setTextInputValue, setShouldResetSearchQuery],
);

const setTextAndUpdateSelection = useCallback(
Expand Down
17 changes: 16 additions & 1 deletion src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNa
import Performance from '@libs/Performance';
import {getIOUActionForTransactionID, isExportIntegrationAction, isIntegrationMessageAction} from '@libs/ReportActionsUtils';
import {canEditFieldOfMoneyRequest, generateReportID, isArchivedReport} from '@libs/ReportUtils';
import {buildSearchQueryString} from '@libs/SearchQueryUtils';
import {buildCannedSearchQuery, buildSearchQueryString} from '@libs/SearchQueryUtils';
import {
getListItem,
getSections,
Expand Down Expand Up @@ -162,6 +162,8 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS
shouldShowSelectAllMatchingItems,
areAllMatchingItemsSelected,
selectAllMatchingItems,
shouldResetSearchQuery,
setShouldResetSearchQuery,
} = useSearchContext();
const [offset, setOffset] = useState(0);

Expand Down Expand Up @@ -630,6 +632,19 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS

const hasErrors = Object.keys(searchResults?.errors ?? {}).length > 0 && !isOffline;

useEffect(() => {
const currentRoute = Navigation.getActiveRouteWithoutParams();
if (hasErrors && (currentRoute === '/' || (shouldResetSearchQuery && currentRoute === '/search'))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@huult Could you please explain the conditions?

// Use requestAnimationFrame to safely update navigation params without overriding the current route
requestAnimationFrame(() => {
Navigation.setParams({q: buildCannedSearchQuery()});
});
if (shouldResetSearchQuery) {
setShouldResetSearchQuery(false);
}
}
}, [hasErrors, queryJSON, searchResults, shouldResetSearchQuery, setShouldResetSearchQuery]);

const fetchMoreResults = useCallback(() => {
if (!isFocused || !searchResults?.search?.hasMoreResults || shouldShowLoadingState || shouldShowLoadingMoreItems) {
return;
Expand Down
2 changes: 2 additions & 0 deletions src/components/Search/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type SearchContextData = {
selectedReports: SelectedReports[];
isOnSearch: boolean;
shouldTurnOffSelectionMode: boolean;
shouldResetSearchQuery: boolean;
};

type SearchContext = SearchContextData & {
Expand All @@ -99,6 +100,7 @@ type SearchContext = SearchContextData & {
shouldShowSelectAllMatchingItems: (shouldShow: boolean) => void;
areAllMatchingItemsSelected: boolean;
selectAllMatchingItems: (on: boolean) => void;
setShouldResetSearchQuery: (shouldReset: boolean) => void;
};

type ASTNode = {
Expand Down
4 changes: 3 additions & 1 deletion src/pages/settings/Troubleshoot/TroubleshootPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import RecordTroubleshootDataToolMenu from '@components/RecordTroubleshootDataTo
import RenderHTML from '@components/RenderHTML';
import ScreenWrapper from '@components/ScreenWrapper';
import ScrollView from '@components/ScrollView';
import {useSearchContext} from '@components/Search/SearchContext';
import Section from '@components/Section';
import Switch from '@components/Switch';
import TestToolMenu from '@components/TestToolMenu';
Expand Down Expand Up @@ -51,7 +52,7 @@ function TroubleshootPage() {
const [shouldStoreLogs] = useOnyx(ONYXKEYS.SHOULD_STORE_LOGS, {canBeMissing: true});
const [shouldMaskOnyxState = true] = useOnyx(ONYXKEYS.SHOULD_MASK_ONYX_STATE, {canBeMissing: true});
const {resetOptions} = useOptionsList({shouldInitialize: false});

const {setShouldResetSearchQuery} = useSearchContext();
const exportOnyxState = useCallback(() => {
ExportOnyxState.readFromOnyxDatabase().then((value: Record<string, unknown>) => {
const dataToShare = ExportOnyxState.maskOnyxState(value, shouldMaskOnyxState);
Expand Down Expand Up @@ -152,6 +153,7 @@ function TroubleshootPage() {
onConfirm={() => {
setIsConfirmationModalVisible(false);
resetOptions();
setShouldResetSearchQuery(true);
clearOnyxAndResetApp();
}}
onCancel={() => setIsConfirmationModalVisible(false)}
Expand Down
Loading