Skip to content

Commit eca0ed1

Browse files
committed
improve docs
1 parent 80441da commit eca0ed1

3 files changed

Lines changed: 15 additions & 4 deletions

File tree

src/CONST/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6410,7 +6410,8 @@ const CONST = {
64106410

64116411
NAVIGATION: {
64126412
CUSTOM_HISTORY_ENTRY_SIDE_PANEL: 'CUSTOM_HISTORY-SIDE_PANEL',
6413-
// Leading padding sentinel; consumed by addRootHistoryRouterExtension. See its file for the contract.
6413+
// Fake history entry used to keep browser Back behavior correct after revealing a route under an RHP.
6414+
// addRootHistoryRouterExtension owns when this is added, carried forward, and removed.
64146415
CUSTOM_HISTORY_ENTRY_REVEAL_PADDING: 'CUSTOM_HISTORY-REVEAL_PADDING',
64156416
ACTION_TYPE: {
64166417
REPLACE: 'REPLACE',

src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,21 @@ const STALE_DEEP_LINK_PARAM_KEYS = new Set(['state', 'screen', 'params', 'path',
5959
/** Removes the RN deep-link hint chain from `route.params` when triggered by `params.screen`. */
6060
function withSanitizedDeepLinkParams<R extends {params?: unknown}>(route: R, focusParams: Record<string, unknown> | undefined): R {
6161
const rParamsRecord = route.params as Record<string, unknown> | undefined;
62+
// RN stores nested deep-link instructions under params.screen/params.params.
6263
const looksLikeDeepLinkInitialState = !!rParamsRecord && typeof rParamsRecord.screen === 'string';
6364
const shouldSanitizeExistingParams = looksLikeDeepLinkInitialState && !!rParamsRecord;
65+
// Remove only RN's hint keys; keep any real params that were stored next to them.
6466
const sanitizedExistingParams = shouldSanitizeExistingParams ? Object.fromEntries(Object.entries(rParamsRecord).filter(([key]) => !STALE_DEEP_LINK_PARAM_KEYS.has(key))) : rParamsRecord;
6567
const hasSanitizedExistingParams = !!sanitizedExistingParams && Object.keys(sanitizedExistingParams).length > 0;
6668
const fallbackParams = hasSanitizedExistingParams ? sanitizedExistingParams : undefined;
69+
// The new focused tab params win; otherwise keep the cleaned existing params.
6770
const nextParams = focusParams ?? fallbackParams;
6871

6972
if (nextParams !== undefined) {
7073
return {...route, params: nextParams};
7174
}
7275
if (looksLikeDeepLinkInitialState) {
73-
// Delete (don't assign undefined) so `'params' in result` stays false.
76+
// If params only contained stale RN hints, remove params entirely.
7477
const routeWithoutParams = {...route};
7578
delete (routeWithoutParams as {params?: unknown}).params;
7679
return routeWithoutParams;

src/libs/Navigation/AppNavigator/routerExtensions/addRootHistoryRouterExtensionUtils.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ function countLeadingRevealPadding(history: CustomHistoryEntry[] | undefined): n
4242
return 0;
4343
}
4444
let count = 0;
45+
// Count how many fake history slots we previously added to keep browser history aligned.
4546
for (const entry of history) {
4647
if (entry === CONST.NAVIGATION.CUSTOM_HISTORY_ENTRY_REVEAL_PADDING) {
4748
count += 1;
@@ -73,6 +74,7 @@ function getFrozenHistoryStateForReplaceFullscreenUnderRHP(
7374
return {pendingReveal, state: rehydrate(newState, configOptions)};
7475
}
7576

77+
// Capture the RHP that should be dismissed in the second half of the reveal.
7678
const topRoute = state.routes.at(-1);
7779
const postReplaceRoutesLength = (newState.routes ?? state.routes).length;
7880
const nextPendingReveal =
@@ -84,6 +86,7 @@ function getFrozenHistoryStateForReplaceFullscreenUnderRHP(
8486
}
8587
: pendingReveal;
8688

89+
// Use the new routes but freeze old history for this hidden intermediate frame.
8790
// Defensive copy of state.history (shared reference; freeze must not alias).
8891
return {pendingReveal: nextPendingReveal, state: {...rehydrate(newState, configOptions), history: [...state.history]}};
8992
}
@@ -99,6 +102,7 @@ function getFrozenHistoryStateForRemoveFullscreenUnderRHP(
99102
return rehydrate(newState, configOptions);
100103
}
101104

105+
// Cancel path: remove the pre-inserted screen while keeping browser history still.
102106
return {...rehydrate(newState, configOptions), history: [...state.history]};
103107
}
104108

@@ -109,11 +113,12 @@ function getRevealDismissState(
109113
pendingReveal: PendingReveal,
110114
rehydrate: RehydrateRootHistoryState,
111115
): {pendingReveal: PendingReveal | null; state?: RootHistoryState} {
112-
// `state` is the pre-DISMISS state; `state.routes.at(-1)` is what will be popped.
116+
// This is the stack before closing the RHP; the top route is the one DISMISS removes.
113117
const dismissingTopKey = state.routes.at(-1)?.key;
114118
const depthMatches = state.routes.length === pendingReveal.routesLengthAtCapture;
115119
const historyDepthMatches = state.history?.length === pendingReveal.historyLengthAtCapture;
116120

121+
// Apply the reveal fix only when this DISMISS closes the same RHP we snapshotted.
117122
if (dismissingTopKey === pendingReveal.rhpKey && depthMatches && historyDepthMatches) {
118123
const rehydrated = rehydrate(newState, configOptions);
119124
const rehydratedHistory = asCustomHistory(rehydrated.history) ?? [];
@@ -122,14 +127,15 @@ function getRevealDismissState(
122127
const lengthDelta = (state.history?.length ?? 0) - rehydratedHistory.length;
123128
if (lengthDelta > 0) {
124129
Log.hmmm(`[addRootHistoryRouterExtension] reveal committed; freezing history with offset ${lengthDelta}`);
130+
// Keep the pre-dismiss history length so web linking replaces instead of going back.
125131
return {pendingReveal: null, state: {...rehydrated, history: buildPaddedHistory(rehydratedHistory, lengthDelta)}};
126132
}
127133
Log.hmmm('[addRootHistoryRouterExtension] reveal committed with non-positive lengthDelta; no freeze', {lengthDelta});
128134
return {pendingReveal: null};
129135
}
130136

131137
if (dismissingTopKey === pendingReveal.rhpKey) {
132-
// Key match but depth divergence: drop snapshot, let DISMISS proceed naturally.
138+
// Same RHP, but the stack/history changed unexpectedly; skip the special reveal fix.
133139
Log.hmmm('[addRootHistoryRouterExtension] reveal snapshot key matched but depth diverged; clearing without freeze', {
134140
capturedRoutesLength: pendingReveal.routesLengthAtCapture,
135141
currentRoutesLength: state.routes.length,
@@ -143,6 +149,7 @@ function getRevealDismissState(
143149
}
144150

145151
function applyRevealPaddingOffset(state: RootHistoryState, rehydrated: RootHistoryState): RootHistoryState {
152+
// Regular navigation rebuilds history from routes; put back any fake slots already in use.
146153
const offset = countLeadingRevealPadding(asCustomHistory(state.history));
147154
if (offset > 0) {
148155
return {...rehydrated, history: buildPaddedHistory(asCustomHistory(rehydrated.history) ?? [], offset)};

0 commit comments

Comments
 (0)