authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-08-27 20:47:42-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-27 20:47:42-07:00
logb982847ab201795711884d1dfadfddb3864adb23
tree07fab8122e5c4ef31493d936cd087c2c7b0a7078
parentb0ae3f3a8527bdcccb6a5cbda93548ad66fbcfea
signature Signed by PGP key B5690EEEBB952194

fix(mobile): keep iOS home header stable (#8467)

Co-authored-by: Julius Marminge <julius@mac.lan>

2 files changed, 82 insertions(+), 35 deletions(-)

patches/react-native-screens@4.25.2.patch+75-28
......@@ -226,7 +226,45 @@ index 5970e3e3a624b9498b8dedfc16831df03a274d0c..5ebff085788d813f1139eb6f9129fb21
226226
227227 // appearance does not apply to the tvOS so we need to use lagacy customization
228228 #if TARGET_OS_TV
229@@ -637,10 +675,458 @@ + (void)updateViewController:(UIViewController *)vc
229@@ -550,31 +588,25 @@ + (void)updateViewController:(UIViewController *)vc
230 navitem.titleView = nil;
231- navitem.leftBarButtonItems = nil;
232- navitem.rightBarButtonItems = nil;
233-
234+
235 #if !TARGET_OS_TV
236 // We want to set navitem.searchController to nil only if we are sure
237 // that we are removing the search bar from the header.
238 bool searchBarPresent = false;
239 #endif /* !TARGET_OS_TV */
240-
241+
242+ NSMutableArray<UIBarButtonItem *> *subviewLeftItems = [NSMutableArray array];
243+ NSMutableArray<UIBarButtonItem *> *subviewRightItems = [NSMutableArray array];
244 for (RNSScreenStackHeaderSubview *subview in config.reactSubviews) {
245 // This code should be kept in sync on Fabric with analogous switch statement in
246 // `- [RNSScreenStackHeaderConfig replaceNavigationBarViewsWithSnapshotOfSubview:]` method.
247 switch (subview.type) {
248 case RNSScreenStackHeaderSubviewTypeLeft: {
249- NSArray<UIBarButtonItem *> *currentItems = navitem.leftBarButtonItems ?: @[];
250- NSMutableArray<UIBarButtonItem *> *mutableItems = [currentItems mutableCopy];
251- [mutableItems addObject:[subview getUIBarButtonItem]];
252- navitem.leftBarButtonItems = mutableItems;
253+ [subviewLeftItems addObject:[subview getUIBarButtonItem]];
254 break;
255 }
256 case RNSScreenStackHeaderSubviewTypeRight: {
257- NSArray<UIBarButtonItem *> *currentItems = navitem.rightBarButtonItems ?: @[];
258- NSMutableArray<UIBarButtonItem *> *mutableItems = [currentItems mutableCopy];
259- [mutableItems addObject:[subview getUIBarButtonItem]];
260- navitem.rightBarButtonItems = mutableItems;
261+ [subviewRightItems addObject:[subview getUIBarButtonItem]];
262 break;
263 }
264 case RNSScreenStackHeaderSubviewTypeCenter:
265 case RNSScreenStackHeaderSubviewTypeTitle: {
266 navitem.titleView = subview;
267@@ -637,10 +669,467 @@ + (void)updateViewController:(UIViewController *)vc
230268 // This assignment should be done after `navitem.titleView = ...` assignment (iOS 16.0 bug).
231269 // See: https://github.com/software-mansion/react-native-screens/issues/1570 (comments)
232270 navitem.title = config.title;
......@@ -237,29 +275,43 @@ index 5970e3e3a624b9498b8dedfc16831df03a274d0c..5ebff085788d813f1139eb6f9129fb21
237275+ NSArray *headerLeftConfigs = config.headerLeftBarButtonItems ?: @[];
238276+ NSArray *headerRightConfigs = config.headerRightBarButtonItems ?: @[];
239277+ NSArray *headerCenterConfigs = config.headerCenterBarButtonItems ?: @[];
240+ NSArray<UIBarButtonItem *> *subviewLeftItems = navitem.leftBarButtonItems ?: @[];
241+ NSArray<UIBarButtonItem *> *subviewRightItems = navitem.rightBarButtonItems ?: @[];
242+ // The key includes the config instance's identity: cached items capture
243+ // this config's event emitter in their press handlers, so a remounted
244+ // header-config view with value-equal configs must still rebuild — reusing
245+ // the old items would dispatch presses into the dead config's emitter.
246+ NSArray *headerItemsKey =
247+ @[ @((uintptr_t)config), headerLeftConfigs, headerRightConfigs, headerCenterConfigs ];
278+ // Retain the config in the key so its address cannot be reused while cached.
279+ // Items capture this config's event emitter in their press handlers, so a
280+ // remounted header-config view with value-equal configs must still rebuild
281+ // instead of dispatching presses into the old config's emitter.
282+ // getUIBarButtonItem is stable for the lifetime of its React header
283+ // subview. Include those native identities in the key so React-backed
284+ // items can use the same cache without reusing a group after its view was
285+ // replaced.
286+ NSArray *headerItemsKey = @[
287+ config,
288+ headerLeftConfigs,
289+ headerRightConfigs,
290+ headerCenterConfigs,
291+ subviewLeftItems,
292+ subviewRightItems,
293+ ];
248294+ // Rebuilding bar button items creates brand-new native buttons (glass
249295+ // UIButton custom views on iOS 26). Replacing them while UIKit animates an
250296+ // existing one (menu capsule morph, push/pop glass transitions) strands the
251297+ // animation overlay — a stuck expanded capsule or an unmasked square back
252+ // button. When the JS configs are unchanged, keep the already-applied items.
253+ // Subview-backed items are re-derived every pass, so their presence forces
254+ // the rebuild path.
255+ BOOL reuseHeaderBarButtonItems = subviewLeftItems.count == 0 && subviewRightItems.count == 0 &&
298+ // button. When both the JS configs and React-backed item identities are
299+ // unchanged, keep the already-applied item groups. Item groups are only
300+ // available from iOS 16, so older platforms keep the legacy rebuild path.
301+ BOOL canReuseHeaderBarButtonItems = NO;
302+#if !TARGET_OS_TV
303+ if (@available(iOS 16.0, *)) {
304+ canReuseHeaderBarButtonItems = YES;
305+ }
306+#endif
307+ BOOL reuseHeaderBarButtonItems = canReuseHeaderBarButtonItems &&
256308+ [objc_getAssociatedObject(navitem, &RNSAppliedHeaderBarButtonConfigsKey) isEqual:headerItemsKey];
257309+ if (!reuseHeaderBarButtonItems) {
258310+ NSArray<UIBarButtonItem *> *leftBarButtonItems = [config barButtonItemsFromConfigs:config.headerLeftBarButtonItems
259+ withCurrentItems:navitem.leftBarButtonItems
311+ withCurrentItems:subviewLeftItems
260312+ navigationItem:navitem];
261313+ NSArray<UIBarButtonItem *> *rightBarButtonItems = [config barButtonItemsFromConfigs:config.headerRightBarButtonItems
262+ withCurrentItems:navitem.rightBarButtonItems
314+ withCurrentItems:subviewRightItems
263315+ navigationItem:navitem];
264316+ NSArray<UIBarButtonItem *> *centerBarButtonItems = [config barButtonItemsFromConfigs:config.headerCenterBarButtonItems
265317+ withCurrentItems:@[]
......@@ -271,8 +323,6 @@ index 5970e3e3a624b9498b8dedfc16831df03a274d0c..5ebff085788d813f1139eb6f9129fb21
271323+ if (@available(iOS 26.0, *)) {
272324+ navitem.centerItemGroups = [config barButtonItemGroupsFromItems:centerBarButtonItems];
273325+ }
274+ navitem.leftBarButtonItems = nil;
275+ navitem.rightBarButtonItems = nil;
276326+ } else {
277327+ navitem.leftBarButtonItems = leftBarButtonItems;
278328+ navitem.rightBarButtonItems = rightBarButtonItems;
......@@ -281,13 +331,10 @@ index 5970e3e3a624b9498b8dedfc16831df03a274d0c..5ebff085788d813f1139eb6f9129fb21
281331+ navitem.leftBarButtonItems = leftBarButtonItems;
282332+ navitem.rightBarButtonItems = rightBarButtonItems;
283333+#endif
284+ // Only dict-driven items can be reused: with subview-backed items in the
285+ // mix the applied state depends on view identity, so clear the key to
286+ // force a rebuild on the next pass.
287334+ objc_setAssociatedObject(
288335+ navitem,
289336+ &RNSAppliedHeaderBarButtonConfigsKey,
290+ subviewLeftItems.count == 0 && subviewRightItems.count == 0 ? headerItemsKey : nil,
337+ headerItemsKey,
291338+ OBJC_ASSOCIATION_RETAIN_NONATOMIC);
292339+ }
293340+ NSDictionary<NSString *, id> *mailSearchToolbarConfig = nil;
......@@ -689,7 +736,7 @@ index 5970e3e3a624b9498b8dedfc16831df03a274d0c..5ebff085788d813f1139eb6f9129fb21
689736
690737 // Setting navigation bar visibility is split to mitigate iOS 26 bug with bar button items
691738 // (setting nav bar visibility should be done after `navitem.*BarButtonItems`).
692@@ -773,6 +1259,7 @@ - (void)applySemanticContentAttributeIfNeededToNavCtrl:(UINavigationController *
739@@ -773,6 +1262,7 @@ - (void)applySemanticContentAttributeIfNeededToNavCtrl:(UINavigationController *
693740
694741 - (NSArray<UIBarButtonItem *> *)barButtonItemsFromConfigs:(NSArray<NSDictionary<NSString *, id> *> *)dicts
695742 withCurrentItems:(NSArray<UIBarButtonItem *> *)currentItems
......@@ -697,7 +744,7 @@ index 5970e3e3a624b9498b8dedfc16831df03a274d0c..5ebff085788d813f1139eb6f9129fb21
697744 {
698745 if (dicts.count == 0) {
699746 return currentItems;
700@@ -781,7 +1268,197 @@ - (void)applySemanticContentAttributeIfNeededToNavCtrl:(UINavigationController *
747@@ -781,7 +1271,197 @@ - (void)applySemanticContentAttributeIfNeededToNavCtrl:(UINavigationController *
701748 [items addObjectsFromArray:currentItems];
702749 for (NSUInteger i = 0; i < dicts.count; i++) {
703750 NSDictionary *dict = dicts[i];
......@@ -896,7 +943,7 @@ index 5970e3e3a624b9498b8dedfc16831df03a274d0c..5ebff085788d813f1139eb6f9129fb21
896943 RNSBarButtonItem *item = [[RNSBarButtonItem alloc] initWithConfig:dict
897944 action:^(NSString *buttonId) {
898945 auto eventEmitter = std::static_pointer_cast<const facebook::react::RNSScreenStackHeaderConfigEventEmitter>(
899@@ -803,19 +1480,23 @@ - (void)applySemanticContentAttributeIfNeededToNavCtrl:(UINavigationController *
946@@ -803,19 +1483,23 @@ - (void)applySemanticContentAttributeIfNeededToNavCtrl:(UINavigationController *
900947 }
901948 imageLoader:_imageLoader];
902949 NSNumber *index = dict[@"index"];
......@@ -926,7 +973,7 @@ index 5970e3e3a624b9498b8dedfc16831df03a274d0c..5ebff085788d813f1139eb6f9129fb21
926973 [items insertObject:item atIndex:index.integerValue];
927974 } else {
928975 [items addObject:item];
929@@ -825,6 +1506,47 @@ - (void)applySemanticContentAttributeIfNeededToNavCtrl:(UINavigationController *
976@@ -825,6 +1509,47 @@ - (void)applySemanticContentAttributeIfNeededToNavCtrl:(UINavigationController *
930977 return items;
931978 }
932979
......@@ -974,7 +1021,7 @@ index 5970e3e3a624b9498b8dedfc16831df03a274d0c..5ebff085788d813f1139eb6f9129fb21
9741021 RNS_IGNORE_SUPER_CALL_BEGIN
9751022 - (void)insertReactSubview:(RNSScreenStackHeaderSubview *)subview atIndex:(NSInteger)atIndex
9761023 {
977@@ -1013,6 +1735,8 @@ - (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props::
1024@@ -1013,6 +1738,8 @@ - (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props::
9781025 }
9791026
9801027 _title = RCTNSStringFromStringNilIfEmpty(newScreenProps.title);
......@@ -983,7 +1030,7 @@ index 5970e3e3a624b9498b8dedfc16831df03a274d0c..5ebff085788d813f1139eb6f9129fb21
9831030 if (newScreenProps.titleFontFamily != oldScreenProps.titleFontFamily) {
9841031 _titleFontFamily = RCTNSStringFromStringNilIfEmpty(newScreenProps.titleFontFamily);
9851032 }
986@@ -1038,6 +1762,7 @@ - (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props::
1033@@ -1038,6 +1765,7 @@ - (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props::
9871034 _disableBackButtonMenu = newScreenProps.disableBackButtonMenu;
9881035 _backButtonDisplayMode =
9891036 [RNSConvert UINavigationItemBackButtonDisplayModeFromCppEquivalent:newScreenProps.backButtonDisplayMode];
......@@ -991,7 +1038,7 @@ index 5970e3e3a624b9498b8dedfc16831df03a274d0c..5ebff085788d813f1139eb6f9129fb21
9911038
9921039 if (newScreenProps.userInterfaceStyle != oldScreenProps.userInterfaceStyle) {
9931040 _userInterfaceStyle = [RNSConvert UIUserInterfaceStyleFromCppEquivalent:newScreenProps.userInterfaceStyle];
994@@ -1084,6 +1809,30 @@ - (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props::
1041@@ -1084,6 +1812,30 @@ - (void)updateProps:(react::Props::Shared const &)props oldProps:(react::Props::
9951042 _headerRightBarButtonItems = array;
9961043 }
9971044
pnpm-lock.yaml+7-7
......@@ -94,7 +94,7 @@ patchedDependencies:
9494 react-native-gesture-handler@2.31.2: 808eb26f9e57cf4945efd3985af4d9c764da6f91f4c9764433cc868602bbf4d3
9595 react-native-keyboard-controller@1.21.13: 20be72c84d74253acdcfefbc6defe36dc396944f1a44cab2bdd0e3cd572ae008
9696 react-native-nitro-modules@0.35.9: 825622aae63a8fb5b904f3c77908a0e216261d727ea171709f2c0b6088422675
97 react-native-screens@4.25.2: 59bfd7b84af01708b6e581c4ccdd5ecf05f8b205383802d66b64ed7ea7bb2199
97 react-native-screens@4.25.2: b3d86ac8bf77b40f4112672f92225853bce6faca485a4aeb609a07a70162a5cc
9898
9999importers:
100100
......@@ -413,7 +413,7 @@ importers:
413413 version: 5.7.0(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
414414 react-native-screens:
415415 specifier: 4.25.2
416 version: 4.25.2(patch_hash=59bfd7b84af01708b6e581c4ccdd5ecf05f8b205383802d66b64ed7ea7bb2199)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
416 version: 4.25.2(patch_hash=b3d86ac8bf77b40f4112672f92225853bce6faca485a4aeb609a07a70162a5cc)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
417417 react-native-shiki-engine:
418418 specifier: ^0.3.12
419419 version: 0.3.12(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
......@@ -14273,7 +14273,7 @@ snapshots:
1427314273 react: 19.2.3
1427414274 react-native: 0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6)
1427514275 react-native-safe-area-context: 5.7.0(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
14276 react-native-screens: 4.25.2(patch_hash=59bfd7b84af01708b6e581c4ccdd5ecf05f8b205383802d66b64ed7ea7bb2199)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
14276 react-native-screens: 4.25.2(patch_hash=b3d86ac8bf77b40f4112672f92225853bce6faca485a4aeb609a07a70162a5cc)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
1427714277 sf-symbols-typescript: 2.2.0
1427814278 warn-once: 0.1.1
1427914279 transitivePeerDependencies:
......@@ -17090,7 +17090,7 @@ snapshots:
1709017090 react-native: 0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6)
1709117091 react-native-drawer-layout: 4.2.4(de9b2f2dc96a3557fdc0df187a8417ee)
1709217092 react-native-safe-area-context: 5.7.0(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6)
17093 react-native-screens: 4.25.2(patch_hash=59bfd7b84af01708b6e581c4ccdd5ecf05f8b205383802d66b64ed7ea7bb2199)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6)
17093 react-native-screens: 4.25.2(patch_hash=b3d86ac8bf77b40f4112672f92225853bce6faca485a4aeb609a07a70162a5cc)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6)
1709417094 server-only: 0.0.1
1709517095 sf-symbols-typescript: 2.2.0
1709617096 shallowequal: 1.1.0
......@@ -17141,7 +17141,7 @@ snapshots:
1714117141 react-native: 0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6)
1714217142 react-native-drawer-layout: 4.2.4(05364bd849de538917a7364cc7dee3f5)
1714317143 react-native-safe-area-context: 5.7.0(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
17144 react-native-screens: 4.25.2(patch_hash=59bfd7b84af01708b6e581c4ccdd5ecf05f8b205383802d66b64ed7ea7bb2199)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
17144 react-native-screens: 4.25.2(patch_hash=b3d86ac8bf77b40f4112672f92225853bce6faca485a4aeb609a07a70162a5cc)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3)
1714517145 server-only: 0.0.1
1714617146 sf-symbols-typescript: 2.2.0
1714717147 shallowequal: 1.1.0
......@@ -19956,14 +19956,14 @@ snapshots:
1995619956 react-native: 0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6)
1995719957 optional: true
1995819958
19959 react-native-screens@4.25.2(patch_hash=59bfd7b84af01708b6e581c4ccdd5ecf05f8b205383802d66b64ed7ea7bb2199)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3):
19959 react-native-screens@4.25.2(patch_hash=b3d86ac8bf77b40f4112672f92225853bce6faca485a4aeb609a07a70162a5cc)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6))(react@19.2.3):
1996019960 dependencies:
1996119961 react: 19.2.3
1996219962 react-freeze: 1.0.4(react@19.2.3)
1996319963 react-native: 0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.3)(utf-8-validate@6.0.6)
1996419964 warn-once: 0.1.1
1996519965
19966 react-native-screens@4.25.2(patch_hash=59bfd7b84af01708b6e581c4ccdd5ecf05f8b205383802d66b64ed7ea7bb2199)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6):
19966 react-native-screens@4.25.2(patch_hash=b3d86ac8bf77b40f4112672f92225853bce6faca485a4aeb609a07a70162a5cc)(react-native@0.85.3(@babel/core@7.29.7)(@react-native/metro-config@0.85.3(@babel/core@7.29.7)(bufferutil@4.1.0)(utf-8-validate@6.0.6))(@types/react@19.2.16)(bufferutil@4.1.0)(react@19.2.6)(utf-8-validate@6.0.6))(react@19.2.6):
1996719967 dependencies:
1996819968 react: 19.2.6
1996919969 react-freeze: 1.0.4(react@19.2.6)