authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-10-08 16:59:32-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-08 16:59:32-07:00
log393ff4c968073d8419e5bade06000998602af6ad
tree1e47e050a569891b5d5a0ca1e7834b49624374a3
parent6308db4ff500b89821e22605f964b1701cead8ee
signature Signed by PGP key B5690EEEBB952194

fix(mobile): restore chat image previews in the v5 stack (#17361)


4 files changed, 153 insertions(+), 5 deletions(-)

apps/mobile/src/features/layout/createWorkspaceStackNavigator.ios.tsx+1
......@@ -247,6 +247,7 @@ function WorkspaceStackView(props: ViewProps) {
247247 const routes = [baseRoute, ...overlays.map((group) => group[0]!)];
248248 return (
249249 <NativeStackView
250 presentationEnvelope
250251 {...props}
251252 state={{ ...props.state, routes, index: routes.length - 1, preloadedRoutes: [] }}
252253 descriptors={{
apps/mobile/src/native/createV5StackNavigator.ios.tsx+1
......@@ -279,6 +279,7 @@ export function V5StackView(props: V5StackViewProps) {
279279 );
280280 return (
281281 <NativeStackView
282 presentationEnvelope
282283 {...props}
283284 descriptors={descriptors}
284285 state={{ ...props.state, routes, index: routes.length - 1, preloadedRoutes: [] }}
patches/@react-navigation%2Fnative-stack@7.17.6.patch+148-2
......@@ -1,8 +1,39 @@
11diff --git a/lib/module/views/NativeStackView.native.js b/lib/module/views/NativeStackView.native.js
2index c342e90bffde9ad5044b6167bdde2e19be219270..5d3e4407aa1bb68b873cf164adf5a9f0b487bb0b 100644
2index c342e90bffde9ad5044b6167bdde2e19be219270..4a045490f0650b4a0c821b3e799cf3d18531417f 100644
33--- a/lib/module/views/NativeStackView.native.js
44+++ b/lib/module/views/NativeStackView.native.js
5@@ -370,6 +370,17 @@ export function NativeStackView({
5@@ -17,8 +17,12 @@ const ANDROID_DEFAULT_HEADER_HEIGHT = 56;
6 function isFabric() {
7 return 'nativeFabricUIManager' in global;
8 }
9+function SceneNavigationProvider({ presentationEnvelope, ...props }) {
10+ return presentationEnvelope ? props.children : /*#__PURE__*/_jsx(NavigationProvider, props);
11+}
12 const useNativeDriver = Platform.OS !== 'web';
13 const SceneView = ({
14+ presentationEnvelope,
15 index,
16 focused,
17 shouldFreeze,
18@@ -231,7 +235,8 @@ const SceneView = ({
19 }
20 }
21 });
22- return /*#__PURE__*/_jsx(NavigationProvider, {
23+ return /*#__PURE__*/_jsx(SceneNavigationProvider, {
24+ presentationEnvelope,
25 route: route,
26 navigation: navigation,
27 children: /*#__PURE__*/_jsx(ScreenStackItem, {
28@@ -353,6 +358,7 @@ const SceneView = ({
29 });
30 };
31 export function NativeStackView({
32+ presentationEnvelope,
33 state,
34 navigation,
35 descriptors,
36@@ -370,6 +376,17 @@ export function NativeStackView({
637 return /*#__PURE__*/_jsx(SafeAreaProviderCompat, {
738 children: /*#__PURE__*/_jsx(ScreenStack, {
839 style: styles.container,
......@@ -20,6 +51,14 @@ index c342e90bffde9ad5044b6167bdde2e19be219270..5d3e4407aa1bb68b873cf164adf5a9f0
2051 children: state.routes.concat(state.preloadedRoutes).map((route, index) => {
2152 const descriptor = descriptors[route.key] ?? preloadedDescriptors[route.key];
2253 const isFocused = state.index === index;
54@@ -386,6 +403,7 @@ export function NativeStackView({
55 // due to component being unmounted. To avoid this, we don't freeze the previous screen there
56 const shouldFreeze = isFabric() ? !isPreloaded && !isFocused && !isBelowFocused && !isModalOnIos : !isPreloaded && !isFocused && !isModalOnIos;
57 return /*#__PURE__*/_jsx(SceneView, {
58+ presentationEnvelope,
59 index: index,
60 focused: isFocused,
61 shouldFreeze: shouldFreeze,
2362diff --git a/lib/module/views/useHeaderConfigProps.js b/lib/module/views/useHeaderConfigProps.js
2463index 9c21aa48cb580704aa17e59d9cdadcc612a1e4ff..a1b3a38368c5ef2257570f382e87df5d6f55b11e 100644
2564--- a/lib/module/views/useHeaderConfigProps.js
......@@ -189,3 +228,110 @@ index 3f3fff405048b3c2250afbe99dd7f35cecb9a6d5..bb062b898cfa77f8c02f951dc9d81b51
189228 >
190229 {item.element}
191230 </ScreenStackHeaderRightView>
231diff --git a/lib/typescript/src/views/NativeStackView.native.d.ts b/lib/typescript/src/views/NativeStackView.native.d.ts
232index c0d37db3b4a2a4e9340c76333821f44a87cd624b..eb3db8f511799b335a17edea31a2acd17627f909 100644
233--- a/lib/typescript/src/views/NativeStackView.native.d.ts
234+++ b/lib/typescript/src/views/NativeStackView.native.d.ts
235@@ -1,11 +1,12 @@
236 import { type ParamListBase, type RouteProp, type StackNavigationState } from '@react-navigation/native';
237 import type { NativeStackDescriptor, NativeStackDescriptorMap, NativeStackNavigationHelpers } from '../types.js';
238 type Props = {
239+ presentationEnvelope?: boolean;
240 state: StackNavigationState<ParamListBase>;
241 navigation: NativeStackNavigationHelpers;
242 descriptors: NativeStackDescriptorMap;
243 describe: (route: RouteProp<ParamListBase>, placeholder: boolean) => NativeStackDescriptor;
244 };
245-export declare function NativeStackView({ state, navigation, descriptors, describe, }: Props): import("react/jsx-runtime").JSX.Element;
246+export declare function NativeStackView({ presentationEnvelope, state, navigation, descriptors, describe, }: Props): import("react/jsx-runtime").JSX.Element;
247 export {};
248 //# sourceMappingURL=NativeStackView.native.d.ts.map
249\ No newline at end of file
250diff --git a/src/views/NativeStackView.native.tsx b/src/views/NativeStackView.native.tsx
251index 416cd90057cea362371a4308dd9985b086c5ccaa..7188a3daf0af2004303b21f89d3c0c7073517ef8 100644
252--- a/src/views/NativeStackView.native.tsx
253+++ b/src/views/NativeStackView.native.tsx
254@@ -51,7 +51,14 @@ function isFabric() {
255 return 'nativeFabricUIManager' in global;
256 }
257
258+// A presentation envelope contains descriptors from its owning navigator.
259+// Its synthetic route must not override those descriptors' focus state.
260+function SceneNavigationProvider({ presentationEnvelope, ...props }: React.ComponentProps<typeof NavigationProvider> & { presentationEnvelope?: boolean }) {
261+ return presentationEnvelope ? props.children : <NavigationProvider {...props} />;
262+}
263+
264 type SceneViewProps = {
265+ presentationEnvelope?: boolean;
266 index: number;
267 focused: boolean;
268 shouldFreeze: boolean;
269@@ -74,6 +81,7 @@ type SceneViewProps = {
270 const useNativeDriver = Platform.OS !== 'web';
271
272 const SceneView = ({
273+ presentationEnvelope,
274 index,
275 focused,
276 shouldFreeze,
277@@ -356,7 +364,7 @@ const SceneView = ({
278 );
279
280 return (
281- <NavigationProvider route={route} navigation={navigation}>
282+ <SceneNavigationProvider presentationEnvelope={presentationEnvelope} route={route} navigation={navigation}>
283 <ScreenStackItem
284 screenId={route.key}
285 activityState={isPreloaded ? 0 : 2}
286@@ -493,11 +501,12 @@ const SceneView = ({
287 </HeaderHeightContext.Provider>
288 </AnimatedHeaderHeightContext.Provider>
289 </ScreenStackItem>
290- </NavigationProvider>
291+ </SceneNavigationProvider>
292 );
293 };
294
295 type Props = {
296+ presentationEnvelope?: boolean;
297 state: StackNavigationState<ParamListBase>;
298 navigation: NativeStackNavigationHelpers;
299 descriptors: NativeStackDescriptorMap;
300@@ -508,6 +517,7 @@ type Props = {
301 };
302
303 export function NativeStackView({
304+ presentationEnvelope,
305 state,
306 navigation,
307 descriptors,
308@@ -555,6 +565,7 @@ export function NativeStackView({
309
310 return (
311 <SceneView
312+ presentationEnvelope={presentationEnvelope}
313 key={route.key}
314 index={index}
315 focused={isFocused}
316diff --git a/lib/typescript/src/views/NativeStackView.d.ts b/lib/typescript/src/views/NativeStackView.d.ts
317--- a/lib/typescript/src/views/NativeStackView.d.ts
318+++ b/lib/typescript/src/views/NativeStackView.d.ts
319@@ -1,6 +1,7 @@
320 import { type ParamListBase, type RouteProp, type StackNavigationState } from '@react-navigation/native';
321 import type { NativeStackDescriptor, NativeStackDescriptorMap, NativeStackNavigationHelpers } from '../types.js';
322 type Props = {
323+ presentationEnvelope?: boolean;
324 state: StackNavigationState<ParamListBase>;
325 navigation: NativeStackNavigationHelpers;
326 descriptors: NativeStackDescriptorMap;
327diff --git a/src/views/NativeStackView.tsx b/src/views/NativeStackView.tsx
328--- a/src/views/NativeStackView.tsx
329+++ b/src/views/NativeStackView.tsx
330@@ -24,6 +24,7 @@
331 import { AnimatedHeaderHeightContext } from '../utils/useAnimatedHeaderHeight';
332
333 type Props = {
334+ presentationEnvelope?: boolean;
335 state: StackNavigationState<ParamListBase>;
336 // This is used for the native implementation of the stack.
337 navigation: NativeStackNavigationHelpers;
pnpm-lock.yaml+3-3
......@@ -139,7 +139,7 @@ patchedDependencies:
139139 '@pierre/diffs@1.5.2': b33a575eb1382270ed0df956307e4b6ffe4b8e4349cefeb43e14f648c0fdc3b0
140140 '@react-native-ai/apple@0.12.0': 2d09870c2848d185cb05b53ed823a46e12dba519324d8dd8e584e28731990f9d
141141 '@react-native-menu/menu@2.0.0': a4866ecfcd44f318043de839d20110c17e14909004900f002ffe12050376f2ba
142 '@react-navigation/native-stack@7.17.6': e667c3cef8c78bb9ff4882ee5bd23a432247b843060a9499eb5f07e9e2295552
142 '@react-navigation/native-stack@7.17.6': 3a53ec9b92f5db5f083f3ada585da75d62a13c82250c6ae47d92be91a828ad87
143143 alchemy@2.0.0-beta.80: bea1b6c0c0b23157fd5f439a1d7feff430f28ac1621ba135d8a13eeec60ccacd
144144 dbus-next@0.10.2: cfff57561b0ee59b5addb3b2e6c6f20906e967507a530ab67e8db8108e520ba4
145145 effect@4.0.1: a33cba07c41f32374c2aaa86ea4a84d3ab9a872a78c94b65e929b19f8361856f
......@@ -325,7 +325,7 @@ importers:
325325 version: 7.3.4(react-native@0.88.0-rc.3(@babel/core@7.29.7)(@react-native/metro-config@0.88.0-rc.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)
326326 '@react-navigation/native-stack':
327327 specifier: 7.17.6
328 version: 7.17.6(patch_hash=e667c3cef8c78bb9ff4882ee5bd23a432247b843060a9499eb5f07e9e2295552)(141a742cd91f55378cde709a48a3af06)
328 version: 7.17.6(patch_hash=3a53ec9b92f5db5f083f3ada585da75d62a13c82250c6ae47d92be91a828ad87)(141a742cd91f55378cde709a48a3af06)
329329 '@shikijs/core':
330330 specifier: 4.2.0
331331 version: 4.2.0
......@@ -15420,7 +15420,7 @@ snapshots:
1542015420 optionalDependencies:
1542115421 '@react-native-masked-view/masked-view': 0.3.2(react-native@0.88.0-rc.3(@babel/core@7.29.7)(@react-native/metro-config@0.88.0-rc.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)
1542215422
15423 '@react-navigation/native-stack@7.17.6(patch_hash=e667c3cef8c78bb9ff4882ee5bd23a432247b843060a9499eb5f07e9e2295552)(141a742cd91f55378cde709a48a3af06)':
15423 '@react-navigation/native-stack@7.17.6(patch_hash=3a53ec9b92f5db5f083f3ada585da75d62a13c82250c6ae47d92be91a828ad87)(141a742cd91f55378cde709a48a3af06)':
1542415424 dependencies:
1542515425 '@react-navigation/elements': 2.9.26(83de68753219ecf7f3321e065bd378be)
1542615426 '@react-navigation/native': 7.3.4(react-native@0.88.0-rc.3(@babel/core@7.29.7)(@react-native/metro-config@0.88.0-rc.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(utf-8-validate@6.0.6))(react@19.3.0)