Skip to content

Commit 0c33312

Browse files
Trim verbose comments to the non-obvious whys
Co-authored-by: Aimane Chnaif <aimane-chnaif@users.noreply.github.com>
1 parent 3ffdfd2 commit 0c33312

4 files changed

Lines changed: 13 additions & 46 deletions

File tree

src/hooks/useIsOneTransactionThread.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,15 @@ import useOneTransactionThreadReportID from './useOneTransactionThreadReportID';
99
import useParentReportAction from './useParentReportAction';
1010

1111
/**
12-
* Whether the report is the transaction thread of its parent report's only expense.
13-
*
14-
* Reactive counterpart of `ReportUtils.isOneTransactionThread`, which reads module globals and so cannot drive
15-
* rendering. The shared derivation does not exclude send money, hence the `isSentMoneyReportAction` guard: a send
16-
* money thread is not interchangeable with its report.
12+
* Whether the report is the transaction thread of its parent report's only expense. Reactive counterpart of
13+
* `ReportUtils.isOneTransactionThread`, which reads module globals and so cannot drive rendering.
1714
*/
1815
function useIsOneTransactionThread(report: OnyxEntry<Report>): boolean {
1916
const parentReportID = getNonEmptyStringOnyxID(report?.parentReportID);
2017
const oneTransactionThreadReportID = useOneTransactionThreadReportID(parentReportID);
2118
const parentReportAction = useParentReportAction(report);
2219

20+
// A send money thread is not interchangeable with its report, and the shared derivation doesn't exclude it.
2321
return !!report?.reportID && oneTransactionThreadReportID === report.reportID && !isSentMoneyReportAction(parentReportAction);
2422
}
2523

src/pages/inbox/OneTransactionThreadRedirectHandler.tsx

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,7 @@ type ExpenseReportRouteParams = {
3838
backTo: string | undefined;
3939
};
4040

41-
/**
42-
* The report a `backTo` points at, whatever route shape it uses. The same report is reachable as `r/`, `e/`,
43-
* `search/view/` and `search/r/`, so the path alone cannot be compared - resolving it the way the navigator itself
44-
* would avoids hard-coding that list.
45-
*/
41+
/** The report a `backTo` points at. Resolved through the navigator because the same report is reachable as `r/`, `e/`, `search/view/` and `search/r/`. */
4642
function getBackToReportID(backTo: Route): string | undefined {
4743
const focusedRoute = findFocusedRoute(getStateFromPath(backTo));
4844
const params = focusedRoute?.params;
@@ -55,22 +51,17 @@ function getExpenseReportRoute({routeName, reportID, referrer, backTo}: ExpenseR
5551
return ROUTES.REPORT_WITH_ID.getRoute(reportID, undefined, referrer, backTo);
5652
}
5753

58-
// Clicking the expense of a single-expense report in Search opens the report on this same RHP route rather than a
59-
// money request report one, so staying here and swapping the report is what the user would have got by clicking it.
6054
if (isSearchTopmostFullScreenRoute()) {
6155
return ROUTES.SEARCH_REPORT.getRoute({reportID, backTo});
6256
}
6357

64-
// Outside Search an expense report belongs in the RHP, which is full screen on a narrow layout anyway. Swapping
65-
// one RHP route for another keeps the redirect inside the navigator it started in - replacing it with the central
66-
// pane `r/` route instead leaves the back stack straddling two navigators.
58+
// Swapping one RHP route for another keeps the redirect inside the navigator it started in.
6759
return ROUTES.EXPENSE_REPORT_RHP.getRoute({reportID, backTo});
6860
}
6961

7062
/**
7163
* Renders nothing. A single-expense report renders its only expense inline (see `shouldDisplayReportTableView`), so
72-
* that expense's transaction thread duplicates the report. This replaces such a route with the report itself - the
73-
* route-level backstop for entry points that don't check the transaction count themselves.
64+
* that expense's transaction thread duplicates the report. This replaces such a route with the report itself.
7465
*/
7566
function OneTransactionThreadRedirectHandler() {
7667
const route = useRoute<ReportScreenRoute>();
@@ -84,20 +75,16 @@ function OneTransactionThreadRedirectHandler() {
8475
// check below, so gate on the count the server keeps on the report itself first.
8576
const [isParentOneTransactionReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${parentReportID}`, {selector: isOneTransactionReport});
8677

87-
// The same definition `HeaderView` and `SidebarUtils` use, so the redirect and the thread's own views agree.
8878
// Passing `undefined` keeps the call inert, so plain comment threads don't subscribe to their chat's action list.
8979
const isOneTransactionThread = useIsOneTransactionThread(isParentOneTransactionReport ? report : undefined);
9080

91-
// The prev/next arrows only exist in a thread's header, so the flows that seed a sibling set to step through
92-
// expenses (Home "Recently added", "Review N flagged expenses", the duplicate review list) would dead-end
93-
// mid-review if we redirected out of the thread.
81+
// The prev/next arrows only exist in a thread's header, so redirecting out of a thread that is part of a sibling
82+
// set (Home "Recently added", "Review N flagged expenses", the duplicate review list) would dead-end mid-review.
9483
const [isSteppingThroughExpenses] = useOnyx(ONYXKEYS.TRANSACTION_THREAD_NAVIGATION_TRANSACTION_IDS, {selector: selectIsSteppingThroughExpenses});
9584

9685
// A message deep link points at an action inside the thread, so dropping the thread route would drop its anchor.
9786
const hasLinkedReportAction = !!route.params?.reportActionID;
9887

99-
// `referrer=notification` is what lets `useMarkAsRead` mark the report read without waiting on window focus, so it
100-
// has to survive the redirect.
10188
const referrer = route.name === SCREENS.REPORT ? route.params?.referrer : undefined;
10289
const backTo = route.params?.backTo;
10390

@@ -108,15 +95,12 @@ function OneTransactionThreadRedirectHandler() {
10895
return;
10996
}
11097

111-
// A thread opened from its own report carries that report as `backTo`. Handing it back to the report would
112-
// point the report at itself, which `linkTo` refuses to navigate to at all on a wide layout, and which sends
113-
// Back round in circles between the report's two route shapes on a narrow one. Inherit the report's own
114-
// nested `backTo` instead - where it would have returned to had the user opened it directly.
98+
// A thread opened from its own report carries that report as `backTo`, which would point the report at itself.
99+
// Inherit that route's own nested `backTo` instead.
115100
const isBackToParentReport = !!backTo && getBackToReportID(backTo) === parentReportID;
116101
const resolvedBackTo = isBackToParentReport ? (getSearchParamFromPath(backTo ?? '', 'backTo') ?? undefined) : backTo;
117102

118-
// Replacing rather than pushing keeps the thread we are leaving out of the history, so going back doesn't
119-
// land on it again.
103+
// Replace rather than push, so going back doesn't land on the thread again.
120104
Navigation.navigate(getExpenseReportRoute({routeName: route.name, reportID: parentReportID, referrer, backTo: resolvedBackTo}), {forceReplace: true});
121105
}, [backTo, isFocused, parentReportID, referrer, route.name, shouldRedirectToParentReport]);
122106

tests/navigation/OneTransactionThreadRedirectHandlerOnyxTest.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ jest.mock('@libs/Navigation/Navigation', () => ({
2828
},
2929
}));
3030

31-
// Onyx, not layout, is what this suite pins down, and the inbox route below never reads the narrow-layout branch.
3231
jest.mock('@libs/getIsNarrowLayout', () => ({
3332
__esModule: true,
3433
default: () => false,
@@ -95,10 +94,7 @@ async function seedOnyx(transactionCount: number, actions: Array<ReportAction<ty
9594
});
9695
}
9796

98-
/**
99-
* `OneTransactionThreadRedirectHandlerTest` mocks the hooks to pin down the decision table. This suite feeds the
100-
* handler real Onyx data, so it catches a wrong Onyx key or reportID that the mocked suite would pass.
101-
*/
97+
/** Feeds the handler real Onyx data, catching a wrong Onyx key or reportID that the mocked suite would pass. */
10298
describe('OneTransactionThreadRedirectHandler with real Onyx data', () => {
10399
beforeAll(() => {
104100
Onyx.init({keys: ONYXKEYS});
@@ -131,7 +127,6 @@ describe('OneTransactionThreadRedirectHandler with real Onyx data', () => {
131127
});
132128

133129
it('keeps the thread route while a multi-expense report is still paginating in', async () => {
134-
// The server counter says three expenses, but only one IOU action has arrived so far.
135130
await seedOnyx(3, [createIOUAction('action1', 'transaction1', THREAD_REPORT_ID)]);
136131

137132
render(<OneTransactionThreadRedirectHandler />, {wrapper: OnyxListItemProvider});

tests/navigation/OneTransactionThreadRedirectHandlerTest.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ const EXPENSE_REPORT_ID = '54321';
1818
const TRANSACTION_ID = '11111';
1919
const SIBLING_TRANSACTION_ID = '22222';
2020

21-
// Inlined because a `jest.mock` factory may only close over locals initialized with a literal. A test below asserts
22-
// the two stay in sync.
21+
// Inlined because a `jest.mock` factory may only close over locals initialized with a literal.
2322
const TRANSACTION_THREAD_NAVIGATION_TRANSACTION_IDS_KEY = 'transactionThreadNavigationTransactionIDs';
2423

2524
const mockNavigate = jest.fn();
@@ -117,8 +116,6 @@ describe('OneTransactionThreadRedirectHandler', () => {
117116
});
118117

119118
it('keeps the thread route while the prev/next carousel is stepping through a sibling set', async () => {
120-
// Home "Recently added", "Review N flagged expenses" and the duplicate review list open a thread precisely for
121-
// the prev/next arrows, which only exist in the thread's header. Redirecting would dead-end them mid-review.
122119
mockSiblingTransactionIDs = [TRANSACTION_ID, SIBLING_TRANSACTION_ID];
123120

124121
render(<OneTransactionThreadRedirectHandler />);
@@ -158,7 +155,6 @@ describe('OneTransactionThreadRedirectHandler', () => {
158155
});
159156

160157
it('still redirects when the parent report only loads after the thread has mounted', async () => {
161-
// A cold open: nothing about the parent is in Onyx yet.
162158
mockParentTransactionCount = undefined;
163159

164160
const {rerender} = render(<OneTransactionThreadRedirectHandler />);
@@ -204,7 +200,6 @@ describe('OneTransactionThreadRedirectHandler', () => {
204200
});
205201

206202
it('stays in the RHP when redirecting from the search RHP outside Search', async () => {
207-
// Swapping one RHP route for another keeps the redirect inside the navigator it started in, on every layout.
208203
mockRouteName = SCREENS.RIGHT_MODAL.SEARCH_REPORT;
209204

210205
render(<OneTransactionThreadRedirectHandler />);
@@ -223,8 +218,6 @@ describe('OneTransactionThreadRedirectHandler', () => {
223218
});
224219

225220
it('inherits the nested backTo when the route came from the parent report itself', async () => {
226-
// A thread opened from its own report carries that report as `backTo`. Keeping it would leave the report
227-
// pointing at itself, which makes `linkTo` refuse to navigate at all.
228221
mockRouteParams = {reportID: THREAD_REPORT_ID, backTo: `/r/${EXPENSE_REPORT_ID}?backTo=${encodeURIComponent('/search')}`};
229222

230223
render(<OneTransactionThreadRedirectHandler />);
@@ -252,7 +245,6 @@ describe('OneTransactionThreadRedirectHandler', () => {
252245
});
253246

254247
it('drops a parent backTo anchored at one of the report actions', async () => {
255-
// `/r/<parent>/<actionID>` still resolves to the parent, so it is a self-reference like the bare path is.
256248
mockRouteParams = {reportID: THREAD_REPORT_ID, backTo: `/r/${EXPENSE_REPORT_ID}/9999`};
257249

258250
render(<OneTransactionThreadRedirectHandler />);
@@ -262,8 +254,6 @@ describe('OneTransactionThreadRedirectHandler', () => {
262254
});
263255

264256
it('drops a parent backTo that reaches the report through another route shape', async () => {
265-
// The same report is reachable as `r/`, `e/`, `search/view/` and `search/r/`, and all of them resolve to the
266-
// same reportID, so none of them may be handed back to the report.
267257
mockRouteParams = {reportID: THREAD_REPORT_ID, backTo: `/e/${EXPENSE_REPORT_ID}`};
268258

269259
render(<OneTransactionThreadRedirectHandler />);

0 commit comments

Comments
 (0)