react-native-screens 5.0.0-alpha.2 → 5.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/Package.swift +87 -0
  2. package/README.md +0 -7
  3. package/android/src/main/cpp/NativeProxy.cpp +30 -6
  4. package/android/src/main/cpp/NativeProxy.h +7 -1
  5. package/android/src/main/java/com/swmansion/rnscreens/common/container/Container.kt +8 -0
  6. package/android/src/main/java/com/swmansion/rnscreens/common/container/ContainerItem.kt +13 -1
  7. package/android/src/main/java/com/swmansion/rnscreens/common/text/ReactTextAppearance.kt +62 -0
  8. package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearance.kt +20 -0
  9. package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearanceDefaults.kt +65 -0
  10. package/android/src/main/java/com/swmansion/rnscreens/helpers/PropIconResolver.kt +17 -23
  11. package/android/src/main/java/com/swmansion/rnscreens/legacy/Screen.kt +3 -1
  12. package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenStack.kt +2 -0
  13. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetBehaviorController.kt +49 -18
  14. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetDimensionsCoordinator.kt +65 -40
  15. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetKeyboardCoordinator.kt +101 -0
  16. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetNativeDismissCoordinator.kt +0 -6
  17. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetAvailableHeightProvider.kt +44 -0
  18. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetDialog.kt +35 -3
  19. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetDialogManager.kt +33 -106
  20. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/interfaces/FormSheetDialogEventEmitter.kt +2 -0
  21. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/model/FormSheetDetents.kt +61 -15
  22. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetAnimatorFactory.kt +8 -9
  23. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetDimmingManager.kt +115 -0
  24. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetDismissalOrigin.kt +22 -0
  25. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentation.kt +173 -0
  26. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentationManager.kt +141 -49
  27. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentationState.kt +1 -1
  28. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetStackRegistry.kt +28 -0
  29. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/event/FormSheetDismissEvent.kt +29 -0
  30. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/host/FormSheetHostEventEmitter.kt +7 -0
  31. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/host/FormSheetHostViewManager.kt +2 -0
  32. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderApplicator.kt +369 -58
  33. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderBackPressHandler.kt +11 -0
  34. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderCoordinatorLayout.kt +143 -98
  35. package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderAppBarLayout.kt +155 -23
  36. package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderContentScrimDrawable.kt +36 -0
  37. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderCollapsedTitleGravityMode.kt +6 -0
  38. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfig.kt +170 -167
  39. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigViewManager.kt +385 -12
  40. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationObserver.kt +0 -4
  41. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationProviding.kt +32 -3
  42. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderDelegate.kt +0 -7
  43. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderInvalidationFlags.kt +7 -2
  44. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuApplicator.kt +27 -280
  45. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuController.kt +448 -0
  46. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuDelegate.kt +10 -0
  47. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuMapper.kt +28 -20
  48. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuConfig.kt +3 -55
  49. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuGroupMetadata.kt +1 -10
  50. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuItemConfig.kt +1 -3
  51. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuModel.kt +180 -0
  52. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementOptions.kt +57 -6
  53. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementRawUpdate.kt +3 -1
  54. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementUpdate.kt +1 -0
  55. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuIconResolver.kt +4 -3
  56. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuUpdateQueue.kt +23 -9
  57. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackContainer.kt +103 -3
  58. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHost.kt +13 -0
  59. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHostViewManager.kt +14 -0
  60. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreen.kt +4 -0
  61. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragment.kt +20 -1
  62. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragmentDelegate.kt +12 -0
  63. package/android/src/main/java/com/swmansion/rnscreens/tabs/appearance/TabsAppearanceCoordinator.kt +2 -4
  64. package/android/src/main/java/com/swmansion/rnscreens/tabs/container/MenuHelpers.kt +5 -23
  65. package/android/src/main/java/com/swmansion/rnscreens/tabs/container/TabsContainer.kt +46 -25
  66. package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHost.kt +10 -0
  67. package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHostA11yCoordinator.kt +23 -2
  68. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreen.kt +17 -0
  69. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreenFragment.kt +3 -0
  70. package/android/src/main/java/com/swmansion/rnscreens/utils/DimensionUtils.kt +7 -0
  71. package/android/src/main/java/com/swmansion/rnscreens/utils/StyleUtils.kt +22 -0
  72. package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_available_space.xml +8 -0
  73. package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_entire_space.xml +8 -0
  74. package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_available_space.xml +8 -0
  75. package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_entire_space.xml +8 -0
  76. package/cpp/legacy/RNSScreenRemovalListener.cpp +31 -1
  77. package/cpp/legacy/RNSScreenRemovalListener.h +18 -3
  78. package/ios/RNSEnums.h +2 -0
  79. package/ios/conversion/RNSConversions.h +7 -108
  80. package/ios/legacy/RNSFullWindowOverlay.mm +1 -1
  81. package/ios/legacy/RNSModalScreen.mm +1 -1
  82. package/ios/legacy/RNSScreen.mm +8 -19
  83. package/ios/legacy/RNSScreenStackHeaderConfig.mm +3 -1
  84. package/ios/legacy/RNSScreenStackHeaderSubview.mm +1 -1
  85. package/ios/legacy/RNSScreenWindowTraits.mm +5 -13
  86. package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.h +1 -3
  87. package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.mm +11 -22
  88. package/ios/modals/form-sheet/RNSFormSheetContentController.h +1 -1
  89. package/ios/modals/form-sheet/RNSFormSheetContentController.mm +7 -18
  90. package/ios/modals/form-sheet/RNSFormSheetHostComponentView.mm +4 -4
  91. package/ios/modals/form-sheet/RNSFormSheetHostShadowStateProxy.mm +2 -2
  92. package/ios/modals/form-sheet/RNSFormSheetUpdateFlags.h +3 -0
  93. package/ios/safe-area/RNSSafeAreaViewComponentView.mm +2 -2
  94. package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.mm +2 -3
  95. package/ios/split/RNSSplitAppearanceApplicator.h +4 -4
  96. package/ios/split/RNSSplitAppearanceApplicator.mm +53 -56
  97. package/ios/split/RNSSplitHostComponentEventEmitter.h +1 -0
  98. package/ios/split/RNSSplitHostComponentEventEmitter.mm +1 -1
  99. package/ios/split/RNSSplitHostComponentView.h +5 -15
  100. package/ios/split/RNSSplitHostComponentView.mm +55 -6
  101. package/ios/split/RNSSplitHostController.h +25 -6
  102. package/ios/split/RNSSplitHostController.mm +24 -92
  103. package/ios/split/RNSSplitHostProviders.h +67 -0
  104. package/ios/split/RNSSplitScreenComponentView.h +0 -39
  105. package/ios/split/RNSSplitScreenComponentView.mm +27 -10
  106. package/ios/split/RNSSplitScreenController.h +26 -3
  107. package/ios/split/RNSSplitScreenController.mm +13 -30
  108. package/ios/split/RNSSplitScreenShadowStateProxy.h +1 -40
  109. package/ios/split/RNSSplitScreenShadowStateProxy.mm +1 -26
  110. package/ios/split/conversion/RNSConversions-SplitView.h +56 -0
  111. package/ios/{conversion → split/conversion}/RNSConversions-SplitView.mm +4 -1
  112. package/ios/stack/conversion/RNSConversions-Stack.h +32 -0
  113. package/ios/stack/conversion/RNSConversions-Stack.mm +55 -0
  114. package/ios/stack/header/RNSStackHeaderAppearanceMapper.h +26 -0
  115. package/ios/stack/header/RNSStackHeaderAppearanceMapper.mm +88 -0
  116. package/ios/stack/header/RNSStackHeaderConfigComponentView.h +10 -1
  117. package/ios/stack/header/RNSStackHeaderConfigComponentView.mm +67 -35
  118. package/ios/stack/header/RNSStackHeaderConfigDataProviding.h +6 -0
  119. package/ios/stack/header/RNSStackHeaderConfigShadowStateProxy.mm +1 -1
  120. package/ios/stack/header/RNSStackHeaderIconResolver.mm +7 -0
  121. package/ios/stack/header/RNSStackHeaderItemComponentView.h +3 -1
  122. package/ios/stack/header/RNSStackHeaderItemComponentView.mm +15 -2
  123. package/ios/stack/header/RNSStackHeaderItemDataProviding.h +2 -0
  124. package/ios/stack/header/RNSStackHeaderItemShadowStateProxy.mm +1 -1
  125. package/ios/stack/header/RNSStackHeaderItemSpacerComponentView.mm +2 -1
  126. package/ios/stack/header/RNSStackHeaderMenuMapper.mm +4 -0
  127. package/ios/stack/host/RNSStackNavigationBar.h +25 -0
  128. package/ios/stack/host/RNSStackNavigationBar.mm +80 -0
  129. package/ios/stack/host/RNSStackNavigationBarCoordinator.h +8 -0
  130. package/ios/stack/host/RNSStackNavigationBarCoordinator.mm +11 -0
  131. package/ios/stack/host/RNSStackNavigationController.mm +13 -5
  132. package/ios/stack/host/RNSStackOperation.h +0 -2
  133. package/ios/stack/screen/RNSStackScreenComponentView.mm +9 -2
  134. package/ios/stack/screen/RNSStackScreenController.mm +12 -0
  135. package/ios/stack/screen/RNSStackScreenHeaderCoordinator.h +8 -0
  136. package/ios/stack/screen/RNSStackScreenHeaderCoordinator.mm +98 -16
  137. package/ios/tabs/RNSTabBarAppearanceCoordinator.mm +40 -9
  138. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.h +1 -1
  139. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.mm +1 -1
  140. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryContentComponentView.mm +1 -1
  141. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryEventEmitter.mm +1 -1
  142. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryShadowStateProxy.mm +1 -1
  143. package/ios/tabs/conversion/RNSConversions-Tabs.h +78 -0
  144. package/ios/{conversion → tabs/conversion}/RNSConversions-Tabs.mm +8 -71
  145. package/ios/tabs/extensions/RNSTabsHostComponentView+RNSImageLoader.h +1 -1
  146. package/ios/tabs/host/RNSTabsHostComponentView.h +2 -0
  147. package/ios/tabs/host/RNSTabsHostComponentView.mm +10 -3
  148. package/ios/tabs/host/RNSTabsHostEventEmitter.mm +1 -1
  149. package/ios/tabs/screen/RNSTabsScreenComponentView.mm +20 -5
  150. package/ios/utils/RNSDefines.h +3 -0
  151. package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js +34 -19
  152. package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js.map +1 -1
  153. package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js +33 -1
  154. package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
  155. package/lib/commonjs/components/stack/host/StackHost.js +9 -6
  156. package/lib/commonjs/components/stack/host/StackHost.js.map +1 -1
  157. package/lib/commonjs/components/stack/index.js.map +1 -1
  158. package/lib/commonjs/components/tabs/host/TabsHost.ios.js +1 -0
  159. package/lib/commonjs/components/tabs/host/TabsHost.ios.js.map +1 -1
  160. package/lib/commonjs/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
  161. package/lib/commonjs/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
  162. package/lib/commonjs/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
  163. package/lib/commonjs/fabric/stack/StackHostNativeComponent.js.map +1 -1
  164. package/lib/commonjs/fabric/tabs/TabsHostIOSNativeComponent.js.map +1 -1
  165. package/lib/module/components/stack/header/StackHeaderConfig.android.js +35 -20
  166. package/lib/module/components/stack/header/StackHeaderConfig.android.js.map +1 -1
  167. package/lib/module/components/stack/header/StackHeaderConfig.ios.js +34 -2
  168. package/lib/module/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
  169. package/lib/module/components/stack/host/StackHost.js +9 -6
  170. package/lib/module/components/stack/host/StackHost.js.map +1 -1
  171. package/lib/module/components/stack/index.js.map +1 -1
  172. package/lib/module/components/tabs/host/TabsHost.ios.js +1 -0
  173. package/lib/module/components/tabs/host/TabsHost.ios.js.map +1 -1
  174. package/lib/module/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
  175. package/lib/module/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
  176. package/lib/module/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
  177. package/lib/module/fabric/stack/StackHostNativeComponent.js.map +1 -1
  178. package/lib/module/fabric/tabs/TabsHostIOSNativeComponent.js.map +1 -1
  179. package/lib/typescript/components/modals/form-sheet/FormSheet.types.d.ts +1 -1
  180. package/lib/typescript/components/stack/header/StackHeaderConfig.android.d.ts.map +1 -1
  181. package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts +616 -21
  182. package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts.map +1 -1
  183. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.d.ts.map +1 -1
  184. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts +226 -2
  185. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts.map +1 -1
  186. package/lib/typescript/components/stack/header/StackHeaderConfig.types.d.ts +2 -2
  187. package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts +2 -0
  188. package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts.map +1 -1
  189. package/lib/typescript/components/stack/host/StackHost.d.ts +1 -1
  190. package/lib/typescript/components/stack/host/StackHost.d.ts.map +1 -1
  191. package/lib/typescript/components/stack/host/StackHost.types.d.ts +24 -0
  192. package/lib/typescript/components/stack/host/StackHost.types.d.ts.map +1 -1
  193. package/lib/typescript/components/stack/index.d.ts +2 -2
  194. package/lib/typescript/components/stack/index.d.ts.map +1 -1
  195. package/lib/typescript/components/tabs/host/TabsHost.ios.d.ts.map +1 -1
  196. package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts +16 -0
  197. package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts.map +1 -1
  198. package/lib/typescript/components/tabs/host/TabsHost.types.d.ts +3 -0
  199. package/lib/typescript/components/tabs/host/TabsHost.types.d.ts.map +1 -1
  200. package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts +52 -0
  201. package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts.map +1 -1
  202. package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts +25 -1
  203. package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts.map +1 -1
  204. package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts +2 -0
  205. package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts.map +1 -1
  206. package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts +3 -1
  207. package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts.map +1 -1
  208. package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts +1 -0
  209. package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts.map +1 -1
  210. package/package.json +8 -7
  211. package/react-native.config.js +3 -0
  212. package/src/components/modals/form-sheet/FormSheet.types.ts +1 -1
  213. package/src/components/stack/header/StackHeaderConfig.android.tsx +48 -23
  214. package/src/components/stack/header/StackHeaderConfig.android.types.ts +637 -21
  215. package/src/components/stack/header/StackHeaderConfig.ios.tsx +45 -1
  216. package/src/components/stack/header/StackHeaderConfig.ios.types.ts +238 -2
  217. package/src/components/stack/header/StackHeaderConfig.types.ts +2 -2
  218. package/src/components/stack/header/ios/StackHeaderItem.ios.types.ts +2 -0
  219. package/src/components/stack/host/StackHost.tsx +4 -2
  220. package/src/components/stack/host/StackHost.types.ts +26 -0
  221. package/src/components/stack/index.ts +6 -1
  222. package/src/components/tabs/host/TabsHost.ios.tsx +1 -0
  223. package/src/components/tabs/host/TabsHost.ios.types.ts +16 -0
  224. package/src/components/tabs/host/TabsHost.types.ts +3 -0
  225. package/src/fabric/stack/StackHeaderConfigAndroidNativeComponent.ts +78 -0
  226. package/src/fabric/stack/StackHeaderConfigIOSNativeComponent.ts +32 -0
  227. package/src/fabric/stack/StackHeaderItemIOSNativeComponent.ts +2 -0
  228. package/src/fabric/stack/StackHostNativeComponent.ts +11 -2
  229. package/src/fabric/tabs/TabsHostIOSNativeComponent.ts +1 -0
  230. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingView.kt +0 -83
  231. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewManager.kt +0 -89
  232. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewPointerEvents.kt +0 -18
  233. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuSelectionController.kt +0 -83
  234. package/ios/conversion/RNSConversions-Stack.h +0 -32
  235. package/ios/conversion/RNSConversions-Stack.mm +0 -41
  236. package/ios/conversion/always_false.h +0 -31
  237. /package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.h +0 -0
@@ -3,6 +3,7 @@ package com.swmansion.rnscreens.stack.header.config
3
3
  import android.annotation.SuppressLint
4
4
  import android.graphics.drawable.Drawable
5
5
  import android.util.LayoutDirection
6
+ import android.view.Gravity
6
7
  import com.facebook.react.bridge.UIManager
7
8
  import com.facebook.react.bridge.UIManagerListener
8
9
  import com.facebook.react.common.annotations.UnstableReactNativeAPI
@@ -10,6 +11,7 @@ import com.facebook.react.uimanager.ThemedReactContext
10
11
  import com.facebook.react.uimanager.UIManagerHelper
11
12
  import com.facebook.react.views.view.ReactViewGroup
12
13
  import com.swmansion.rnscreens.common.ShadowStateProxy
14
+ import com.swmansion.rnscreens.common.text.ReactTextAppearance
13
15
  import com.swmansion.rnscreens.helpers.IconResolution
14
16
  import com.swmansion.rnscreens.helpers.PropIconResolver
15
17
  import com.swmansion.rnscreens.helpers.getFabricUIManagerNotNull
@@ -17,12 +19,11 @@ import com.swmansion.rnscreens.helpers.resolveImage
17
19
  import com.swmansion.rnscreens.stack.header.subview.OnStackHeaderSubviewChangeListener
18
20
  import com.swmansion.rnscreens.stack.header.subview.StackHeaderSubview
19
21
  import com.swmansion.rnscreens.stack.header.subview.StackHeaderSubviewType
22
+ import com.swmansion.rnscreens.stack.header.toolbar.StackHeaderToolbarMenuController
23
+ import com.swmansion.rnscreens.stack.header.toolbar.StackHeaderToolbarMenuDelegate
20
24
  import com.swmansion.rnscreens.stack.header.toolbar.model.StackHeaderToolbarMenuConfig
21
- import com.swmansion.rnscreens.stack.header.toolbar.model.StackHeaderToolbarMenuItemIconSource
22
- import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarFieldUpdate
23
25
  import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarMenuElementRawUpdate
24
26
  import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarMenuIconResolver
25
- import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarMenuUpdateQueue
26
27
  import java.lang.ref.WeakReference
27
28
  import kotlin.properties.Delegates
28
29
 
@@ -33,6 +34,7 @@ internal class StackHeaderConfig(
33
34
  ) : ReactViewGroup(reactContext),
34
35
  StackHeaderConfigurationProviding,
35
36
  StackHeaderDelegate,
37
+ StackHeaderToolbarMenuDelegate,
36
38
  OnStackHeaderSubviewChangeListener,
37
39
  UIManagerListener {
38
40
  init {
@@ -71,92 +73,121 @@ internal class StackHeaderConfig(
71
73
 
72
74
  // region Properties
73
75
 
74
- override var type: StackHeaderType by Delegates.observable(StackHeaderType.SMALL) { _, old, new ->
75
- if (old != new) invalidate(StackHeaderInvalidationFlags.STRUCTURE)
76
- }
76
+ override var type: StackHeaderType by invalidatingProperty(StackHeaderType.SMALL, StackHeaderInvalidationFlags.STRUCTURE)
77
77
  internal set
78
78
 
79
- override var title: String by Delegates.observable("") { _, old, new ->
80
- if (old != new) invalidate(StackHeaderInvalidationFlags.TITLE)
81
- }
79
+ override var title: String by invalidatingProperty("", StackHeaderInvalidationFlags.TITLE)
82
80
  internal set
83
81
 
84
- override var hidden: Boolean by Delegates.observable(false) { _, old, new ->
85
- if (old != new) invalidate(StackHeaderInvalidationFlags.STRUCTURE)
86
- }
82
+ override var subtitle: String by invalidatingProperty("", StackHeaderInvalidationFlags.TITLE)
87
83
  internal set
88
84
 
89
- override var transparent: Boolean by Delegates.observable(false) { _, old, new ->
90
- if (old != new) invalidate(StackHeaderInvalidationFlags.STRUCTURE)
91
- }
85
+ // Requires header rebuild due to bug in Material implementation
86
+ override var maxLines: Int by invalidatingProperty(1, StackHeaderInvalidationFlags.STRUCTURE)
92
87
  internal set
93
88
 
94
- override var backButtonHidden: Boolean by Delegates.observable(false) { _, old, new ->
95
- if (old != new) invalidate(StackHeaderInvalidationFlags.BACK_BUTTON)
96
- }
89
+ override var hidden: Boolean by invalidatingProperty(false, StackHeaderInvalidationFlags.STRUCTURE)
97
90
  internal set
98
91
 
99
- override var backButtonTintColorNormal: Int? by Delegates.observable(null) { _, old, new ->
100
- if (old != new) invalidate(StackHeaderInvalidationFlags.BACK_BUTTON)
101
- }
92
+ override var transparent: Boolean by invalidatingProperty(false, StackHeaderInvalidationFlags.STRUCTURE)
102
93
  internal set
103
94
 
104
- override var backButtonTintColorPressed: Int? by Delegates.observable(null) { _, old, new ->
105
- if (old != new) invalidate(StackHeaderInvalidationFlags.BACK_BUTTON)
106
- }
95
+ override var backButtonHidden: Boolean by invalidatingProperty(false, StackHeaderInvalidationFlags.BACK_BUTTON)
107
96
  internal set
108
97
 
109
- override var backButtonTintColorFocused: Int? by Delegates.observable(null) { _, old, new ->
110
- if (old != new) invalidate(StackHeaderInvalidationFlags.BACK_BUTTON)
111
- }
98
+ override var backButtonTintColorNormal: Int? by invalidatingProperty(null, StackHeaderInvalidationFlags.BACK_BUTTON)
112
99
  internal set
113
100
 
114
- override var backButtonIcon: Drawable? by Delegates.observable(null) { _, old, new ->
115
- if (old !== new) invalidate(StackHeaderInvalidationFlags.BACK_BUTTON)
116
- }
101
+ override var backButtonTintColorPressed: Int? by invalidatingProperty(null, StackHeaderInvalidationFlags.BACK_BUTTON)
117
102
  internal set
118
103
 
119
- override var scrollFlagScroll: Boolean by Delegates.observable(false) { _, old, new ->
120
- if (old != new) invalidate(StackHeaderInvalidationFlags.SCROLL_FLAGS)
121
- }
104
+ override var backButtonTintColorFocused: Int? by invalidatingProperty(null, StackHeaderInvalidationFlags.BACK_BUTTON)
122
105
  internal set
123
106
 
124
- override var scrollFlagEnterAlways: Boolean by Delegates.observable(false) { _, old, new ->
125
- if (old != new) invalidate(StackHeaderInvalidationFlags.SCROLL_FLAGS)
126
- }
107
+ override var backButtonIcon: Drawable? by invalidatingProperty(null, StackHeaderInvalidationFlags.BACK_BUTTON)
127
108
  internal set
128
109
 
129
- override var scrollFlagEnterAlwaysCollapsed: Boolean by Delegates.observable(false) { _, old, new ->
130
- if (old != new) invalidate(StackHeaderInvalidationFlags.SCROLL_FLAGS)
131
- }
110
+ override var overflowIconTintColorNormal: Int? by invalidatingProperty(null, StackHeaderInvalidationFlags.OVERFLOW_ICON)
132
111
  internal set
133
112
 
134
- override var scrollFlagExitUntilCollapsed: Boolean by Delegates.observable(false) { _, old, new ->
135
- if (old != new) invalidate(StackHeaderInvalidationFlags.SCROLL_FLAGS)
136
- }
113
+ override var overflowIconTintColorPressed: Int? by invalidatingProperty(null, StackHeaderInvalidationFlags.OVERFLOW_ICON)
137
114
  internal set
138
115
 
139
- override var scrollFlagSnap: Boolean by Delegates.observable(false) { _, old, new ->
140
- if (old != new) invalidate(StackHeaderInvalidationFlags.SCROLL_FLAGS)
141
- }
116
+ override var overflowIconTintColorFocused: Int? by invalidatingProperty(null, StackHeaderInvalidationFlags.OVERFLOW_ICON)
142
117
  internal set
143
118
 
144
- override var liftOnScroll: Boolean by Delegates.observable(true) { _, old, new ->
145
- if (old != new) invalidate(StackHeaderInvalidationFlags.LIFT_ON_SCROLL)
146
- }
119
+ override var overflowIcon: Drawable? by invalidatingProperty(null, StackHeaderInvalidationFlags.OVERFLOW_ICON)
147
120
  internal set
148
121
 
149
- override var toolbarMenu: StackHeaderToolbarMenuConfig
150
- by Delegates.observable(StackHeaderToolbarMenuConfig(emptyList(), emptyList())) { _, old, new ->
151
- if (old != new) invalidate(StackHeaderInvalidationFlags.TOOLBAR_MENU)
152
- }
122
+ override var scrollFlagScroll: Boolean by invalidatingProperty(false, StackHeaderInvalidationFlags.SCROLL_FLAGS)
153
123
  internal set
154
124
 
155
- override var toolbarMenuGroupDividerEnabled: Boolean by Delegates.observable(false) { _, old, new ->
156
- if (old != new) invalidate(StackHeaderInvalidationFlags.TOOLBAR_MENU)
157
- }
125
+ override var scrollFlagEnterAlways: Boolean by invalidatingProperty(false, StackHeaderInvalidationFlags.SCROLL_FLAGS)
126
+ internal set
127
+
128
+ override var scrollFlagEnterAlwaysCollapsed: Boolean by invalidatingProperty(false, StackHeaderInvalidationFlags.SCROLL_FLAGS)
129
+ internal set
130
+
131
+ override var scrollFlagExitUntilCollapsed: Boolean by invalidatingProperty(false, StackHeaderInvalidationFlags.SCROLL_FLAGS)
132
+ internal set
133
+
134
+ override var scrollFlagSnap: Boolean by invalidatingProperty(false, StackHeaderInvalidationFlags.SCROLL_FLAGS)
135
+ internal set
136
+
137
+ override var liftOnScroll: Boolean by invalidatingProperty(true, StackHeaderInvalidationFlags.LIFT_ON_SCROLL)
138
+ internal set
139
+
140
+ override var backgroundColor: Int? by invalidatingProperty(null, StackHeaderInvalidationFlags.BACKGROUND_COLORS)
141
+ internal set
142
+
143
+ override var scrolledBackgroundColor: Int? by invalidatingProperty(null, StackHeaderInvalidationFlags.BACKGROUND_COLORS)
144
+ internal set
145
+
146
+ override var statusBarScrimColor: Int? by invalidatingProperty(null, StackHeaderInvalidationFlags.BACKGROUND_COLORS)
147
+ internal set
148
+
149
+ override var titleCentered: Boolean by invalidatingProperty(false, StackHeaderInvalidationFlags.TITLE_POSITIONING)
150
+ internal set
151
+
152
+ override var subtitleCentered: Boolean by invalidatingProperty(false, StackHeaderInvalidationFlags.TITLE_POSITIONING)
153
+ internal set
154
+
155
+ override var expandedTitleHorizontalGravity: Int by invalidatingProperty(Gravity.START, StackHeaderInvalidationFlags.TITLE_POSITIONING)
156
+ internal set
157
+
158
+ override var expandedTitleVerticalGravity: Int by invalidatingProperty(Gravity.BOTTOM, StackHeaderInvalidationFlags.TITLE_POSITIONING)
159
+ internal set
160
+
161
+ override var collapsedTitleHorizontalGravity: Int by invalidatingProperty(Gravity.START, StackHeaderInvalidationFlags.TITLE_POSITIONING)
162
+ internal set
163
+
164
+ override var collapsedTitleVerticalGravity: Int by invalidatingProperty(
165
+ Gravity.CENTER_VERTICAL,
166
+ StackHeaderInvalidationFlags.TITLE_POSITIONING,
167
+ )
168
+ internal set
169
+
170
+ override var collapsedTitleGravityMode: StackHeaderCollapsedTitleGravityMode
171
+ by invalidatingProperty(StackHeaderCollapsedTitleGravityMode.AVAILABLE_SPACE, StackHeaderInvalidationFlags.STRUCTURE)
158
172
  internal set
159
173
 
174
+ override var contentInsetStart: Float?
175
+ by invalidatingProperty(null, StackHeaderInvalidationFlags.CONTENT_INSETS)
176
+ internal set
177
+
178
+ override var contentInsetEnd: Float?
179
+ by invalidatingProperty(null, StackHeaderInvalidationFlags.CONTENT_INSETS)
180
+ internal set
181
+
182
+ override val titleAppearance = ReactTextAppearance(reactContext.assets, ::invalidateTextAppearance)
183
+ override val subtitleAppearance = ReactTextAppearance(reactContext.assets, ::invalidateTextAppearance)
184
+ override val expandedTitleAppearance = ReactTextAppearance(reactContext.assets, ::invalidateTextAppearance)
185
+ override val collapsedTitleAppearance = ReactTextAppearance(reactContext.assets, ::invalidateTextAppearance)
186
+ override val expandedSubtitleAppearance = ReactTextAppearance(reactContext.assets, ::invalidateTextAppearance)
187
+ override val collapsedSubtitleAppearance = ReactTextAppearance(reactContext.assets, ::invalidateTextAppearance)
188
+
189
+ private fun invalidateTextAppearance() = invalidate(StackHeaderInvalidationFlags.TITLE_APPEARANCE)
190
+
160
191
  override val isRTL: Boolean
161
192
  get() = layoutDirection == LayoutDirection.RTL
162
193
 
@@ -186,11 +217,10 @@ internal class StackHeaderConfig(
186
217
  // Resolution happens in resolveBackButtonIconIfNeeded(), called from onAfterUpdateTransaction.
187
218
  internal var backButtonDrawableIconResourceName: String? = null
188
219
  internal var backButtonImageIconUri: String? = null
189
- private val backButtonIconResolver = PropIconResolver()
220
+ private val backButtonIconResolver = createPropIconResolver(reactContext)
190
221
 
191
222
  internal fun resolveBackButtonIconIfNeeded() {
192
223
  backButtonIconResolver.resolve(
193
- reactContext,
194
224
  backButtonDrawableIconResourceName,
195
225
  backButtonImageIconUri,
196
226
  ) { result ->
@@ -208,82 +238,82 @@ internal class StackHeaderConfig(
208
238
 
209
239
  // endregion
210
240
 
211
- // region Toolbar menu item icon resolution
241
+ // region Overflow menu icon resolution
212
242
 
213
- internal var toolbarMenuItemIconSourceMap = mapOf<String, StackHeaderToolbarMenuItemIconSource>()
243
+ // Staging fields for overflow menu icon resolution — mirrors the back button icon.
244
+ // Resolution happens in resolveOverflowIconIfNeeded(), called from onAfterUpdateTransaction.
245
+ internal var overflowIconDrawableIconResourceName: String? = null
246
+ internal var overflowIconImageIconUri: String? = null
247
+ private val overflowIconResolver = createPropIconResolver(reactContext)
214
248
 
215
- private var toolbarMenuItemIconResolvers = mapOf<String, PropIconResolver>()
249
+ internal fun resolveOverflowIconIfNeeded() {
250
+ overflowIconResolver.resolve(
251
+ overflowIconDrawableIconResourceName,
252
+ overflowIconImageIconUri,
253
+ ) { result ->
254
+ when (result) {
255
+ IconResolution.Unchanged -> Unit
256
+ is IconResolution.Resolved -> {
257
+ overflowIcon = result.drawable
258
+ if (!isInsideMountTransaction) {
259
+ flushUpdates()
260
+ }
261
+ }
262
+ }
263
+ }
264
+ }
216
265
 
217
- // Last resolved icon per menu item id, from the `toolbarMenu` prop path only
218
- // (resolveToolbarMenuItemIconsIfNeeded). Command (`updateToolbarMenuElements`) icons are applied
219
- // directly to the live toolbar and are intentionally NOT stored here.
220
- private var toolbarMenuItemIcons = mapOf<String, Drawable?>()
266
+ // endregion
221
267
 
222
- internal fun resolveToolbarMenuItemIconsIfNeeded() {
223
- val nextResolvers = mutableMapOf<String, PropIconResolver>()
268
+ // region Toolbar menu
224
269
 
225
- toolbarMenuItemIconSourceMap.forEach { (id, source) ->
226
- val resolver = toolbarMenuItemIconResolvers[id] ?: PropIconResolver()
227
- nextResolvers[id] = resolver
270
+ override val toolbarMenuController =
271
+ StackHeaderToolbarMenuController(createMenuIconResolver(reactContext))
272
+ .also { it.delegate = WeakReference(this) }
228
273
 
229
- resolver.resolve(
230
- context = reactContext,
231
- drawableIconResourceName = source.drawableIconResourceName,
232
- imageIconUri = source.imageIconUri,
233
- ) { result ->
234
- val icon =
235
- when (result) {
236
- IconResolution.Unchanged -> toolbarMenuItemIcons[id]
237
- is IconResolution.Resolved -> {
238
- toolbarMenuItemIcons = toolbarMenuItemIcons + (id to result.drawable)
239
- result.drawable
240
- }
241
- }
274
+ internal fun setToolbarMenuFromProps(menu: StackHeaderToolbarMenuConfig) {
275
+ if (toolbarMenuController.setMenu(menu)) {
276
+ invalidate(StackHeaderInvalidationFlags.TOOLBAR_MENU)
277
+ }
278
+ }
242
279
 
243
- applyToolbarMenuItemIcon(id, icon)
244
- }
280
+ internal fun setToolbarMenuGroupDividerEnabledFromProps(enabled: Boolean) {
281
+ if (toolbarMenuController.setGroupDividerEnabled(enabled)) {
282
+ invalidate(StackHeaderInvalidationFlags.TOOLBAR_MENU)
245
283
  }
284
+ }
246
285
 
247
- toolbarMenuItemIconResolvers = nextResolvers
248
- toolbarMenuItemIcons = toolbarMenuItemIcons.filterKeys { it in toolbarMenuItemIconSourceMap }
286
+ internal fun dispatchMenuElementUpdates(updates: List<StackHeaderToolbarMenuElementRawUpdate>) {
287
+ toolbarMenuController.enqueueElementUpdates(updates)
249
288
  }
250
289
 
251
- private fun applyToolbarMenuItemIcon(
252
- id: String,
253
- icon: Drawable?,
290
+ // StackHeaderToolbarMenuDelegate -> JS events
291
+
292
+ override fun onMenuItemClicked(id: String) {
293
+ eventEmitter.emitOnToolbarMenuItemPress(id)
294
+ }
295
+
296
+ override fun onGroupSelectionChanged(
297
+ groupId: String,
298
+ selectedIds: List<String>,
254
299
  ) {
255
- val currentMenu = toolbarMenu
256
- val updated = currentMenu.updateItemIcon(id, icon)
257
- if (updated !== currentMenu) {
258
- toolbarMenu = updated
259
- if (!isInsideMountTransaction) {
260
- flushUpdates()
261
- }
262
- }
300
+ eventEmitter.emitOnToolbarMenuGroupSelectionChange(groupId, selectedIds)
263
301
  }
264
302
 
265
303
  // endregion
266
304
 
267
305
  // region Subviews
268
306
 
269
- override var backgroundSubview: StackHeaderSubview? by Delegates.observable(null) { _, old, new ->
270
- if (old !== new) invalidate(StackHeaderInvalidationFlags.SUBVIEWS)
271
- }
307
+ override var backgroundSubview: StackHeaderSubview? by invalidatingProperty(null, StackHeaderInvalidationFlags.SUBVIEWS)
272
308
  private set
273
309
 
274
- override var leadingSubview: StackHeaderSubview? by Delegates.observable(null) { _, old, new ->
275
- if (old !== new) invalidate(StackHeaderInvalidationFlags.SUBVIEWS)
276
- }
310
+ override var leadingSubview: StackHeaderSubview? by invalidatingProperty(null, StackHeaderInvalidationFlags.SUBVIEWS)
277
311
  private set
278
312
 
279
- override var centerSubview: StackHeaderSubview? by Delegates.observable(null) { _, old, new ->
280
- if (old !== new) invalidate(StackHeaderInvalidationFlags.SUBVIEWS)
281
- }
313
+ override var centerSubview: StackHeaderSubview? by invalidatingProperty(null, StackHeaderInvalidationFlags.SUBVIEWS)
282
314
  private set
283
315
 
284
- override var trailingSubview: StackHeaderSubview? by Delegates.observable(null) { _, old, new ->
285
- if (old !== new) invalidate(StackHeaderInvalidationFlags.SUBVIEWS)
286
- }
316
+ override var trailingSubview: StackHeaderSubview? by invalidatingProperty(null, StackHeaderInvalidationFlags.SUBVIEWS)
287
317
  private set
288
318
 
289
319
  override fun onStackHeaderSubviewChanged() {
@@ -349,17 +379,6 @@ internal class StackHeaderConfig(
349
379
  )
350
380
  }
351
381
 
352
- override fun onMenuItemClicked(id: String) {
353
- eventEmitter.emitOnToolbarMenuItemPress(id)
354
- }
355
-
356
- override fun onGroupSelectionChanged(
357
- groupId: String,
358
- selectedIds: List<String>,
359
- ) {
360
- eventEmitter.emitOnToolbarMenuGroupSelectionChange(groupId, selectedIds)
361
- }
362
-
363
382
  override fun onSubviewOriginChanged(
364
383
  type: StackHeaderSubviewType,
365
384
  x: Int,
@@ -388,52 +407,6 @@ internal class StackHeaderConfig(
388
407
 
389
408
  // endregion
390
409
 
391
- // region Imperative menu item commands
392
-
393
- /**
394
- * Resolves a single command's icon. Unlike the `toolbarMenu` prop path,
395
- * this does NOT go through the stateful per-id [PropIconResolver] (whose
396
- * drop-stale async guard could leave the queue waiting forever - the queue
397
- * requires that [StackHeaderToolbarMenuIconResolver.resolve] always calls
398
- * [onResolved] even if the image loading results in failure; see
399
- * [StackHeaderToolbarMenuIconResolver] and
400
- * [StackHeaderToolbarMenuUpdateQueue] for more details) and does NOT touch
401
- * the prop icon cache: it resolves the source with an always-completing
402
- * [resolveImage] and forwards the result to the queue, which applies it to
403
- * the live toolbar. Ordering across commands is guaranteed by the queue, so
404
- * no drop-stale is needed here; a failed or empty source resolves to `null`
405
- * -> Reset (the icon is cleared) rather than stalling the queue.
406
- */
407
- private val commandIconResolver =
408
- StackHeaderToolbarMenuIconResolver { iconSource, onResolved ->
409
- resolveImage(
410
- reactContext,
411
- iconSource.drawableIconResourceName,
412
- iconSource.imageIconUri,
413
- ) { drawable ->
414
- onResolved(StackHeaderToolbarFieldUpdate.from(drawable))
415
- }
416
- }
417
-
418
- // Serializes `updateToolbarMenuElements` batches and waits for every icon in a batch to
419
- // resolve before applying it, so each batch is applied atomically and in order.
420
- private val menuUpdateQueue =
421
- StackHeaderToolbarMenuUpdateQueue(
422
- iconResolver = commandIconResolver,
423
- delegate = { updates -> configObserver?.onMenuElementsUpdated(updates) },
424
- )
425
-
426
- /**
427
- * Enqueues a batch of toolbar menu element view commands. The batch is processed only
428
- * after any earlier batch has been fully applied, and is applied atomically once all of
429
- * its icons (if any) have resolved — see [StackHeaderToolbarMenuUpdateQueue].
430
- */
431
- internal fun dispatchMenuElementUpdates(updates: List<StackHeaderToolbarMenuElementRawUpdate>) {
432
- menuUpdateQueue.enqueue(updates)
433
- }
434
-
435
- // endregion
436
-
437
410
  // region UIManagerListener
438
411
 
439
412
  private var isInsideMountTransaction = false
@@ -461,10 +434,40 @@ internal class StackHeaderConfig(
461
434
  UIManagerHelper
462
435
  .getFabricUIManagerNotNull(reactContext)
463
436
  .removeUIManagerEventListener(this)
464
- menuUpdateQueue.tearDown()
437
+ toolbarMenuController.tearDown()
465
438
  invalidationFlags = StackHeaderInvalidationFlags.NONE
466
439
  configObserver = null
467
440
  }
468
441
 
469
442
  // endregion
443
+
444
+ // region Helpers
445
+
446
+ private fun <T> invalidatingProperty(
447
+ initialValue: T,
448
+ flag: StackHeaderInvalidationFlags,
449
+ ) = Delegates.observable(initialValue) { _, old, new ->
450
+ if (old != new) invalidate(flag)
451
+ }
452
+
453
+ // endregion
454
+
455
+ // Built outside the instance scope on purpose: a lambda capturing this view
456
+ // would be retained by every icon load still in flight.
457
+ private companion object {
458
+ fun createPropIconResolver(context: ThemedReactContext) =
459
+ PropIconResolver { name, uri, onComplete ->
460
+ resolveImage(context, name, uri, onComplete)
461
+ }
462
+
463
+ fun createMenuIconResolver(context: ThemedReactContext) =
464
+ StackHeaderToolbarMenuIconResolver { iconSource, onResolved ->
465
+ resolveImage(
466
+ context,
467
+ iconSource.drawableIconResourceName,
468
+ iconSource.imageIconUri,
469
+ onResolved,
470
+ )
471
+ }
472
+ }
470
473
  }