-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Fix: smooth post-submit navigation and rendering on Spend tab #88728
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
mountiny
merged 20 commits into
Expensify:main
from
software-mansion-labs:korytko/perf/fix-search-dismiss
May 5, 2026
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
5a8fa53
fix: search dismiss
JakubKorytko 72f5346
fix: empty report in between
JakubKorytko 12ceaea
fix: search flickering
JakubKorytko e7fe0da
refactor: cleanup the code
JakubKorytko 9415615
fix: empty report state
JakubKorytko 8b025f5
address codex comments
JakubKorytko bb59642
Merge branch 'main' into korytko/perf/fix-search-dismiss
JakubKorytko 1b426f9
fix: checks after merge
JakubKorytko 34bfe8c
address codex comment
JakubKorytko e01237d
Merge branch 'main' into korytko/perf/fix-search-dismiss
JakubKorytko d91d6de
fix: stale submit-to-destination-visible spans
JakubKorytko 21b8a99
address ai comments
JakubKorytko 05af831
Merge branch 'main' into korytko/perf/fix-search-dismiss
JakubKorytko 19cfbdb
remove listener from App
JakubKorytko 0ef88eb
address ai comments pt 2
JakubKorytko ea6439e
fix IOURequestStepConfirmationPageTest
JakubKorytko cd3071f
address ai comments pt 3
JakubKorytko 8882e4b
address ai comments pt 4
JakubKorytko aadc532
address ai comments pt 5
JakubKorytko 879c2ea
address ai comments pt 6
JakubKorytko File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| import {useFocusEffect} from '@react-navigation/native'; | ||
| import React, {useCallback, useEffect, useState} from 'react'; | ||
| import type {StyleProp, ViewStyle} from 'react-native'; | ||
| import {useSession} from '@components/OnyxListItemProvider'; | ||
| import SearchStaticList from '@components/Search/SearchStaticList'; | ||
| import type {SearchQueryJSON} from '@components/Search/types'; | ||
| import {hasDeferredWrite} from '@libs/deferredLayoutWrite'; | ||
| import Navigation from '@libs/Navigation/Navigation'; | ||
| import {isDefaultExpensesQuery} from '@libs/SearchQueryUtils'; | ||
| import {getColumnsToShow, getValidGroupBy, isTransactionSearchType} from '@libs/SearchUIUtils'; | ||
| import CONST from '@src/CONST'; | ||
| import ONYXKEYS from '@src/ONYXKEYS'; | ||
| import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm'; | ||
| import type {SearchResults} from '@src/types/onyx'; | ||
| import useOnyx from './useOnyx'; | ||
|
|
||
| const OVERLAY_SAFETY_TIMEOUT_MS = 5000; | ||
|
|
||
| type UseSearchOverlayParams = { | ||
| searchResults: SearchResults | undefined; | ||
|
JakubKorytko marked this conversation as resolved.
|
||
| queryJSON: SearchQueryJSON | undefined; | ||
| shouldUseNarrowLayout: boolean; | ||
| isMobileSelectionModeEnabled: boolean; | ||
| currentSearchKey: string | undefined; | ||
| /** FlatList content padding for narrow layout (accounts for filter bars). */ | ||
| contentContainerStyle?: StyleProp<ViewStyle>; | ||
| }; | ||
|
|
||
| type UseSearchOverlayResult = { | ||
| searchOverlayContent: React.ReactNode; | ||
|
JakubKorytko marked this conversation as resolved.
|
||
| onSearchContentReady: () => void; | ||
| /** Whether the overlay lifecycle is active (armed but not yet ready). */ | ||
| isOverlayActive: boolean; | ||
| }; | ||
|
|
||
| /** | ||
| * Manages the SearchStaticList overlay shown above the Search content area | ||
| * during expense-creation flows. The overlay is displayed when a deferred | ||
| * write is pending or a fullscreen route has been pre-inserted under the RHP, | ||
| * and dismissed once the real Search component signals readiness via | ||
| * onContentReady, or after a safety timeout. | ||
| */ | ||
| function useSearchOverlay({ | ||
| searchResults, | ||
| queryJSON, | ||
| shouldUseNarrowLayout, | ||
| isMobileSelectionModeEnabled, | ||
| currentSearchKey, | ||
| contentContainerStyle, | ||
| }: UseSearchOverlayParams): UseSearchOverlayResult { | ||
| const session = useSession(); | ||
| const accountID = session?.accountID ?? CONST.DEFAULT_NUMBER_ID; | ||
| const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {selector: columnsSelector}); | ||
|
|
||
| const [isSearchReady, setIsSearchReady] = useState(() => !hasDeferredWrite(CONST.DEFERRED_LAYOUT_WRITE_KEYS.SEARCH) && !Navigation.getIsFullscreenPreInsertedUnderRHP()); | ||
|
JakubKorytko marked this conversation as resolved.
|
||
|
|
||
| const onSearchContentReady = () => { | ||
| setIsSearchReady(true); | ||
| }; | ||
|
|
||
| // Re-arm the overlay on focus when a new deferred write was registered | ||
| // (e.g. a subsequent submit flow while Search stays mounted). | ||
| useFocusEffect( | ||
| useCallback(() => { | ||
| if (!hasDeferredWrite(CONST.DEFERRED_LAYOUT_WRITE_KEYS.SEARCH) && !Navigation.getIsFullscreenPreInsertedUnderRHP()) { | ||
| return; | ||
| } | ||
| setIsSearchReady(false); | ||
| }, []), | ||
| ); | ||
|
|
||
| useEffect(() => { | ||
| if (isSearchReady) { | ||
| return; | ||
| } | ||
| const id = setTimeout(() => setIsSearchReady(true), OVERLAY_SAFETY_TIMEOUT_MS); | ||
| return () => clearTimeout(id); | ||
| }, [isSearchReady]); | ||
|
|
||
| // When the overlay is dismissed, skip column computation and JSX creation. | ||
| // The hook subscriptions (useSession, useOnyx) must remain unconditional per | ||
| // rules-of-hooks, but the derived work below is the expensive part. | ||
| if (isSearchReady) { | ||
| return {searchOverlayContent: null, onSearchContentReady, isOverlayActive: false}; | ||
| } | ||
|
|
||
| const isTransaction = isTransactionSearchType(queryJSON?.type); | ||
| const canSelectMultiple = isTransaction && (!shouldUseNarrowLayout || isMobileSelectionModeEnabled); | ||
|
|
||
| const validGroupBy = queryJSON ? getValidGroupBy(queryJSON.groupBy) : undefined; | ||
| const shouldUseStrictDefaultExpenseColumns = currentSearchKey === CONST.SEARCH.SEARCH_KEYS.EXPENSES && !!queryJSON && isDefaultExpensesQuery(queryJSON); | ||
|
|
||
| const searchData = searchResults?.data; | ||
| const overlayColumns = (() => { | ||
| if (!searchData || !queryJSON) { | ||
| return []; | ||
| } | ||
| return getColumnsToShow({ | ||
| currentAccountID: accountID, | ||
| data: searchData, | ||
| visibleColumns: visibleColumns ?? [], | ||
| type: queryJSON.type, | ||
| groupBy: validGroupBy, | ||
| shouldUseStrictDefaultExpenseColumns, | ||
| }); | ||
| })(); | ||
|
|
||
| // Narrow layout gets the custom contentContainerStyle (accounts for filter bars); | ||
| // wide layout uses SearchStaticList's own internal padding (styles.pb3). | ||
| const searchOverlayContent = | ||
| isTransaction && searchData && queryJSON ? ( | ||
| <SearchStaticList | ||
|
JakubKorytko marked this conversation as resolved.
JakubKorytko marked this conversation as resolved.
|
||
| searchResults={searchResults} | ||
| queryJSON={queryJSON} | ||
| shouldUseNarrowLayout={shouldUseNarrowLayout} | ||
| canSelectMultiple={canSelectMultiple} | ||
| columns={overlayColumns} | ||
| contentContainerStyle={shouldUseNarrowLayout ? contentContainerStyle : undefined} | ||
| /> | ||
| ) : null; | ||
|
|
||
| return {searchOverlayContent, onSearchContentReady, isOverlayActive: true}; | ||
| } | ||
|
|
||
| export default useSearchOverlay; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.