Skip to content

Commit c144f62

Browse files
authored
Merge pull request #89585 from TaduJR/fix-Reports-Highlight-animation-is-visible-on-added-expense-after-duplication
fix: Reports - Highlight animation is visible on added expense after duplication
2 parents 679a833 + 14e199a commit c144f62

19 files changed

Lines changed: 313 additions & 273 deletions

File tree

src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
4141
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
4242
const [betas] = useOnyx(ONYXKEYS.BETAS);
4343
const {email: currentUserEmail, accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
44-
const {markReportIDAsExpense} = useWideRHPActions();
44+
const {markReportRHPWidth} = useWideRHPActions();
4545

4646
const {prevTransactionID, nextTransactionID} = useMemo(() => {
4747
if (!transactionIDsList || transactionIDsList.length < 2) {
@@ -144,7 +144,7 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
144144
const navigationParams = {reportID: nextThreadReportID, reportActionID: undefined, backTo};
145145

146146
if (nextThreadReportID) {
147-
markReportIDAsExpense(nextThreadReportID);
147+
markReportRHPWidth(nextThreadReportID, 'wide');
148148
}
149149
// We know that the next thread report exists, it just wasn't fetched to Onyx yet, so we set it optimistically.
150150
if (!nextThreadReport && nextThreadReportID) {
@@ -190,7 +190,7 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
190190
const navigationParams = {reportID: prevThreadReportID, reportActionID: undefined, backTo};
191191

192192
if (prevThreadReportID) {
193-
markReportIDAsExpense(prevThreadReportID);
193+
markReportRHPWidth(prevThreadReportID, 'wide');
194194
}
195195
// We know that the previous thread report exists, it just wasn't fetched to Onyx yet, so we set it optimistically.
196196
if (!prevThreadReport && prevThreadReportID) {

src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
153153

154154
const isActionColumnWide = transactions.some((transaction) => !!transaction.isActionColumnWide || isDeletedTransaction(transaction));
155155

156-
const {markReportIDAsExpense} = useWideRHPActions();
156+
const {markReportRHPWidth} = useWideRHPActions();
157157
const selectRow = onSelectRow as (item: TItem, transactionPreviewData?: TransactionPreviewData, event?: ModifiedMouseEvent) => void;
158158
const getTransactionPreviewData = (transactionItem: TransactionListItemType): TransactionPreviewData => {
159159
const parentReportAction = getReportAction(transactionItem?.reportID, transactionItem?.reportAction?.reportActionID);
@@ -212,7 +212,7 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
212212
});
213213
return;
214214
}
215-
markReportIDAsExpense(reportID);
215+
markReportRHPWidth(reportID, 'wide');
216216
const route = ROUTES.SEARCH_REPORT.getRoute({reportID, backTo});
217217
if (openInternalRouteInNewTab(route, event)) {
218218
return;

src/components/Search/index.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ function Search({
134134
const navigation = useNavigation<PlatformStackNavigationProp<SearchFullscreenNavigatorParamList>>();
135135
const isFocused = useIsFocused();
136136

137-
const {markReportIDAsExpense, markReportIDAsMultiTransactionExpense, unmarkReportIDAsMultiTransactionExpense} = useWideRHPActions();
137+
const {markReportRHPWidth, unmarkReportRHPWidth} = useWideRHPActions();
138138
const {currentSearchHash, currentSearchKey, shouldResetSearchQuery, suggestedSearches} = useSearchQueryContext();
139139
const {lastSearchType, shouldUseLiveData} = useSearchResultsContext();
140140

@@ -579,9 +579,9 @@ function Search({
579579
}
580580

581581
if (item.transactions.length > 1) {
582-
markReportIDAsMultiTransactionExpense(reportID);
582+
markReportRHPWidth(reportID, 'super-wide');
583583
} else {
584-
unmarkReportIDAsMultiTransactionExpense(reportID);
584+
unmarkReportRHPWidth(reportID, 'super-wide');
585585
}
586586

587587
// Persist the current search context so prev/next navigation arrows
@@ -626,7 +626,7 @@ function Search({
626626
return;
627627
}
628628

629-
markReportIDAsExpense(reportID);
629+
markReportRHPWidth(reportID, 'wide');
630630

631631
if (isTransactionItem && transactionPreviewData) {
632632
setOptimisticDataForTransactionThreadPreview(transactionItem, transactionPreviewData, transactionItem?.reportAction?.childReportID);
@@ -639,10 +639,9 @@ function Search({
639639
requestAnimationFrame(() => Navigation.navigate(route));
640640
},
641641
[
642-
markReportIDAsExpense,
642+
markReportRHPWidth,
643643
handleSearch,
644-
markReportIDAsMultiTransactionExpense,
645-
unmarkReportIDAsMultiTransactionExpense,
644+
unmarkReportRHPWidth,
646645
introSelected,
647646
betas,
648647
isSelfTourViewed,

src/components/WideRHPContextProvider/default.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,11 @@ const defaultWideRHPStateContextValue: WideRHPStateContextType = {
1212
};
1313

1414
const defaultWideRHPActionsContextValue: WideRHPActionsContextType = {
15-
showWideRHPVersion: () => {},
16-
showSuperWideRHPVersion: () => {},
17-
removeWideRHPRouteKey: () => {},
18-
removeSuperWideRHPRouteKey: () => {},
19-
markReportIDAsExpense: () => {},
20-
markReportIDAsMultiTransactionExpense: () => {},
21-
unmarkReportIDAsMultiTransactionExpense: () => {},
22-
isReportIDMarkedAsExpense: () => false,
23-
isReportIDMarkedAsMultiTransactionExpense: () => false,
15+
setRHPWidth: () => {},
16+
removeRHPRouteKey: () => {},
17+
markReportRHPWidth: () => {},
18+
unmarkReportRHPWidth: () => {},
19+
getReportRHPWidthHint: () => undefined,
2420
syncRHPKeys: () => {},
2521
clearWideRHPKeys: () => {},
2622
setIsWideRHPClosing: () => {},

src/components/WideRHPContextProvider/index.tsx

Lines changed: 61 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import type {Report} from '@src/types/onyx';
1818
import {defaultWideRHPActionsContextValue, defaultWideRHPStateContextValue} from './default';
1919
import getIsRHPDisplayedBelow from './getIsRHPDisplayedBelow';
2020
import getVisibleRHPKeys from './getVisibleRHPRouteKeys';
21-
import type {WideRHPActionsContextType, WideRHPStateContextType} from './types';
21+
import type {RHPWidth, RHPWidthHint, WideRHPActionsContextType, WideRHPStateContextType} from './types';
2222
import useShouldRenderOverlay from './useShouldRenderOverlay';
2323

2424
// 0 is folded/hidden, 1 is expanded/shown
@@ -74,7 +74,7 @@ function showWideRHPRoute(route: NavigationRoute, setAllRHPRouteKeys: React.Disp
7474
// Function to remove a Wide/Super Wide RHP route key to the array including wide/super wide RHP route keys
7575
function removeWideRHPRoute(route: NavigationRoute, setAllRHPRouteKeys: React.Dispatch<React.SetStateAction<string[]>>) {
7676
if (!route.key) {
77-
console.error(`The route passed to removeWideRHPRouteKey should have the "key" property defined.`);
77+
console.error(`The route passed to removeWideRHPRoute should have the "key" property defined.`);
7878
return;
7979
}
8080

@@ -106,9 +106,8 @@ function WideRHPContextProvider({children}: React.PropsWithChildren) {
106106
const [allSuperWideRHPRouteKeys, setAllSuperWideRHPRouteKeys] = useState<string[]>([]);
107107
const [superWideRHPRouteKeys, setSuperWideRHPRouteKeys] = useState<string[]>([]);
108108

109-
// Report IDs that should be displayed in Wide/Super Wide RHP
110-
const [expenseReportIDs, setExpenseReportIDs] = useState<Set<string>>(new Set());
111-
const [multiTransactionExpenseReportIDs, setMultiTransactionExpenseReportIDs] = useState<Set<string>>(new Set());
109+
// A reportID maps to at most one hint, making "wide vs super-wide" structurally mutually exclusive.
110+
const [reportRHPWidthHints, setReportRHPWidthHints] = useState<Map<string, RHPWidthHint>>(() => new Map());
112111

113112
const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: expenseReportSelector});
114113

@@ -186,96 +185,77 @@ function WideRHPContextProvider({children}: React.PropsWithChildren) {
186185
const shouldRenderTertiaryOverlay = useShouldRenderOverlay(isRHPFocused && isWideRHPBelow && isSuperWideRHPBelow, thirdOverlayProgress);
187186

188187
/**
189-
* Removes a route from the super wide RHP route keys list, disabling wide RHP display for that route.
188+
* Removes the route from both wide and super-wide sets. Used on screen unmount.
190189
*/
191-
const removeSuperWideRHPRouteKey = (route: NavigationRoute) => removeWideRHPRoute(route, setAllSuperWideRHPRouteKeys);
192-
193-
/**
194-
* Removes a route from the wide RHP route keys list, disabling wide RHP display for that route.
195-
*/
196-
const removeWideRHPRouteKey = (route: NavigationRoute) => removeWideRHPRoute(route, setAllWideRHPRouteKeys);
197-
198-
/**
199-
* Adds a route to the wide RHP route keys list, enabling wide RHP display for that route.
200-
*/
201-
const showWideRHPVersion = (route: NavigationRoute) => {
202-
removeSuperWideRHPRouteKey(route);
203-
showWideRHPRoute(route, setAllWideRHPRouteKeys);
190+
const removeRHPRouteKey = (route: NavigationRoute) => {
191+
removeWideRHPRoute(route, setAllSuperWideRHPRouteKeys);
192+
removeWideRHPRoute(route, setAllWideRHPRouteKeys);
204193
};
205194

206195
/**
207-
* Adds a route to the super wide RHP route keys list, enabling super wide RHP display for that route.
196+
* Single entry point for setting a route's RHP width. Registrations are mutually exclusive — the
197+
* route lives in at most one of {wide, super-wide} sets at any time (or neither, for 'narrow').
208198
*/
209-
const showSuperWideRHPVersion = (route: NavigationRoute) => {
210-
removeWideRHPRouteKey(route);
211-
showWideRHPRoute(route, setAllSuperWideRHPRouteKeys);
212-
};
213-
214-
/**
215-
* Marks a report ID as an expense report, adding it to the expense reports set.
216-
* This enables optimistic wide RHP display for expense reports.
217-
* It helps us open expense as wide, before it fully loads.
218-
*/
219-
const markReportIDAsExpense = (reportID?: string) => {
220-
if (!reportID) {
199+
const setRHPWidth = (route: NavigationRoute, width: RHPWidth) => {
200+
if (width === 'super-wide') {
201+
removeWideRHPRoute(route, setAllWideRHPRouteKeys);
202+
showWideRHPRoute(route, setAllSuperWideRHPRouteKeys);
221203
return;
222204
}
223-
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
224-
const isInvoice = report?.type === CONST.REPORT.TYPE.INVOICE;
225-
const isTask = report?.type === CONST.REPORT.TYPE.TASK;
226-
if (isInvoice || isTask) {
205+
if (width === 'wide') {
206+
removeWideRHPRoute(route, setAllSuperWideRHPRouteKeys);
207+
showWideRHPRoute(route, setAllWideRHPRouteKeys);
227208
return;
228209
}
229-
setExpenseReportIDs((prev) => {
230-
const newSet = new Set(prev);
231-
newSet.add(reportID);
232-
return newSet;
233-
});
210+
removeWideRHPRoute(route, setAllSuperWideRHPRouteKeys);
211+
removeWideRHPRoute(route, setAllWideRHPRouteKeys);
234212
};
235213

236214
/**
237-
* Checks if a report ID is marked as an expense report.
238-
* Used to determine if wide RHP should be displayed optimistically.
239-
* It helps us open expense as wide, before it fully loads.
215+
* Sets an optimistic width hint for a reportID before its screen renders, so the right width is
216+
* registered on first paint. Invoices and tasks are excluded from the 'wide' hint.
217+
* It helps us open expense as wide / super wide, before it fully loads.
240218
*/
241-
const isReportIDMarkedAsExpense = (reportID: string) => {
242-
return expenseReportIDs.has(reportID);
243-
};
244-
245-
/**
246-
* Marks a report ID as a multi-transaction expense report, adding it to the expense reports set.
247-
* This enables optimistic super wide RHP display for expense reports.
248-
* It helps us open expense as super wide, before it fully loads.
249-
*/
250-
const markReportIDAsMultiTransactionExpense = (reportID: string) => {
251-
setMultiTransactionExpenseReportIDs((prev) => {
252-
const newSet = new Set(prev);
253-
newSet.add(reportID);
254-
return newSet;
219+
const markReportRHPWidth = (reportID: string | undefined, width: RHPWidthHint) => {
220+
if (!reportID) {
221+
return;
222+
}
223+
if (width === 'wide') {
224+
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
225+
if (report?.type === CONST.REPORT.TYPE.INVOICE || report?.type === CONST.REPORT.TYPE.TASK) {
226+
return;
227+
}
228+
}
229+
setReportRHPWidthHints((prev) => {
230+
if (prev.get(reportID) === width) {
231+
return prev;
232+
}
233+
const next = new Map(prev);
234+
next.set(reportID, width);
235+
return next;
255236
});
256237
};
257238

258239
/**
259-
* Removes a report ID from the multi-transaction expense reports set.
260-
* This disables optimistic super wide RHP display for that specific report
261-
* (e.g., when transactions are deleted or report no longer qualifies as multi-transaction)
240+
* Clears the optimistic width hint for a reportID. Pass `width` to clear only when it matches the
241+
* current hint; omit to clear unconditionally. Called when a report no longer qualifies for a hint.
262242
*/
263-
const unmarkReportIDAsMultiTransactionExpense = (reportID: string) => {
264-
setMultiTransactionExpenseReportIDs((prev) => {
265-
const newSet = new Set(prev);
266-
newSet.delete(reportID);
267-
return newSet;
243+
const unmarkReportRHPWidth = (reportID: string, width?: RHPWidthHint) => {
244+
setReportRHPWidthHints((prev) => {
245+
const current = prev.get(reportID);
246+
if (current === undefined) {
247+
return prev;
248+
}
249+
if (width !== undefined && current !== width) {
250+
return prev;
251+
}
252+
const next = new Map(prev);
253+
next.delete(reportID);
254+
return next;
268255
});
269256
};
270257

271-
/**
272-
* Checks if a report ID is marked as a multi-transaction expense report.
273-
* Used to determine if super wide RHP should be displayed optimistically.
274-
* It helps us open expense as super wide, before it fully loads.
275-
*/
276-
const isReportIDMarkedAsMultiTransactionExpense = (reportID: string) => {
277-
return multiTransactionExpenseReportIDs.has(reportID);
278-
};
258+
const getReportRHPWidthHint = (reportID: string): RHPWidthHint | undefined => reportRHPWidthHints.get(reportID);
279259

280260
/**
281261
* Effect that handles responsive RHP width calculation when window dimensions change.
@@ -319,16 +299,12 @@ function WideRHPContextProvider({children}: React.PropsWithChildren) {
319299

320300
// Because of the React Compiler we don't need to memoize it manually
321301
// eslint-disable-next-line react/jsx-no-constructed-context-values
322-
const actionsValue = {
323-
showWideRHPVersion,
324-
showSuperWideRHPVersion,
325-
removeWideRHPRouteKey,
326-
removeSuperWideRHPRouteKey,
327-
markReportIDAsExpense,
328-
markReportIDAsMultiTransactionExpense,
329-
unmarkReportIDAsMultiTransactionExpense,
330-
isReportIDMarkedAsExpense,
331-
isReportIDMarkedAsMultiTransactionExpense,
302+
const actionsValue: WideRHPActionsContextType = {
303+
setRHPWidth,
304+
removeRHPRouteKey,
305+
markReportRHPWidth,
306+
unmarkReportRHPWidth,
307+
getReportRHPWidthHint,
332308
syncRHPKeys,
333309
clearWideRHPKeys,
334310
setIsWideRHPClosing,
@@ -366,3 +342,4 @@ export {
366342
useWideRHPState,
367343
useWideRHPActions,
368344
};
345+
export type {RHPWidth} from './types';

src/components/WideRHPContextProvider/types.ts

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import type {NavigationRoute} from '@libs/Navigation/types';
22

3+
type RHPWidth = 'narrow' | 'wide' | 'super-wide';
4+
5+
type RHPWidthHint = Exclude<RHPWidth, 'narrow'>;
6+
37
type WideRHPStateContextType = {
48
// Route keys of screens that should be displayed in wide format
59
wideRHPRouteKeys: string[];
@@ -27,32 +31,20 @@ type WideRHPStateContextType = {
2731
};
2832

2933
type WideRHPActionsContextType = {
30-
// Show given route as in wide format
31-
showWideRHPVersion: (route: NavigationRoute) => void;
32-
33-
// Show given route as in super wide format
34-
showSuperWideRHPVersion: (route: NavigationRoute) => void;
35-
36-
// Remove given route from the array
37-
removeWideRHPRouteKey: (route: NavigationRoute) => void;
38-
39-
// Remove given route from the array
40-
removeSuperWideRHPRouteKey: (route: NavigationRoute) => void;
41-
42-
// Mark reportID as expense before condition check
43-
markReportIDAsExpense: (reportID?: string) => void;
34+
// Register the route at the given width. 'narrow' removes from both sets.
35+
setRHPWidth: (route: NavigationRoute, width: RHPWidth) => void;
4436

45-
// Mark reportID as multi-transaction expense before condition check
46-
markReportIDAsMultiTransactionExpense: (reportID: string) => void;
37+
// Remove the route from both sets (used on screen unmount).
38+
removeRHPRouteKey: (route: NavigationRoute) => void;
4739

48-
// Unmark reportID as multi-transaction expense before condition check
49-
unmarkReportIDAsMultiTransactionExpense: (reportID: string) => void;
40+
// Set an optimistic width hint for a reportID before navigation.
41+
markReportRHPWidth: (reportID: string | undefined, width: RHPWidthHint) => void;
5042

51-
// Check if reportID is marked as expense
52-
isReportIDMarkedAsExpense: (reportID: string) => boolean;
43+
// Clear the hint(s) for a reportID. Pass `width` to clear only that one.
44+
unmarkReportRHPWidth: (reportID: string, width?: RHPWidthHint) => void;
5345

54-
// Check if reportID is marked as multi-transaction expense
55-
isReportIDMarkedAsMultiTransactionExpense: (reportID: string) => boolean;
46+
// Read the optimistic width hint for a reportID.
47+
getReportRHPWidthHint: (reportID: string) => RHPWidthHint | undefined;
5648

5749
// Sync super wide and wide RHP keys with the visible RHP screens
5850
syncRHPKeys: () => void;
@@ -67,4 +59,4 @@ type WideRHPActionsContextType = {
6759
setIsSuperWideRHPClosing: (isClosing: boolean) => void;
6860
};
6961

70-
export type {WideRHPStateContextType, WideRHPActionsContextType};
62+
export type {RHPWidth, RHPWidthHint, WideRHPStateContextType, WideRHPActionsContextType};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import type {RHPWidth} from '..';
2+
3+
// Wide/Super-Wide RHP is not displayed on native platforms.
4+
const useRHPWidth: (width: RHPWidth) => void = () => {};
5+
6+
export default useRHPWidth;

0 commit comments

Comments
 (0)