react-native-navigation 7.23.1 → 7.24.0

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 (263) hide show
  1. package/.buildkite/pipeline.yml +51 -11
  2. package/.nvmrc +1 -0
  3. package/Mock.d.ts +1 -0
  4. package/Mock.js +4 -0
  5. package/Mock.ts +1 -1
  6. package/README.md +0 -1
  7. package/jest.config.js +40 -0
  8. package/lib/{src/Mock → Mock}/Application.tsx +0 -0
  9. package/lib/{src/Mock → Mock}/ComponentProps.tsx +0 -0
  10. package/lib/{src/Mock → Mock}/Components/BottomTabs.tsx +0 -0
  11. package/lib/{src/Mock → Mock}/Components/ComponentScreen.tsx +13 -2
  12. package/lib/{src/Mock → Mock}/Components/LayoutComponent.tsx +0 -0
  13. package/lib/{src/Mock → Mock}/Components/Modals.tsx +0 -0
  14. package/lib/{src/Mock → Mock}/Components/NavigationButton.tsx +1 -1
  15. package/lib/{src/Mock → Mock}/Components/Overlays.tsx +0 -0
  16. package/lib/{src/Mock → Mock}/Components/Stack.tsx +0 -0
  17. package/lib/{src/Mock → Mock}/Components/TopBar.tsx +2 -2
  18. package/lib/{src/Mock → Mock}/Layouts/BottomTabsNode.ts +1 -1
  19. package/lib/{src/Mock → Mock}/Layouts/ComponentNode.ts +1 -1
  20. package/lib/{src/Mock → Mock}/Layouts/LayoutNodeFactory.ts +0 -0
  21. package/lib/{src/Mock → Mock}/Layouts/Node.ts +1 -1
  22. package/lib/{src/Mock → Mock}/Layouts/ParentNode.ts +2 -2
  23. package/lib/{src/Mock → Mock}/Layouts/StackNode.ts +0 -0
  24. package/lib/{src/Mock → Mock}/Stores/EventsStore.ts +10 -2
  25. package/lib/{src/Mock → Mock}/Stores/LayoutStore.ts +3 -2
  26. package/lib/{src/Mock → Mock}/connect.ts +0 -0
  27. package/lib/Mock/constants.d.ts +2 -0
  28. package/lib/Mock/constants.js +5 -0
  29. package/lib/{src/Mock → Mock}/constants.ts +0 -0
  30. package/lib/Mock/index.d.ts +3 -0
  31. package/lib/Mock/index.js +14 -0
  32. package/lib/{src/Mock → Mock}/index.ts +0 -0
  33. package/lib/{src/Mock → Mock}/mocks/AppRegistryService.ts +0 -0
  34. package/lib/{src/Mock → Mock}/mocks/NativeCommandsSender.tsx +1 -1
  35. package/lib/{src/Mock → Mock}/mocks/NativeEventsReceiver.ts +7 -4
  36. package/lib/android/app/build.gradle +23 -21
  37. package/lib/android/app/src/main/java/com/reactnativenavigation/options/FontOptions.kt +2 -2
  38. package/lib/android/app/src/main/java/com/reactnativenavigation/options/HardwareBackButtonOptions.kt +35 -2
  39. package/lib/android/app/src/main/java/com/reactnativenavigation/options/LayoutFactory.java +32 -17
  40. package/lib/android/app/src/main/java/com/reactnativenavigation/options/Options.java +1 -1
  41. package/lib/android/app/src/main/java/com/reactnativenavigation/options/parsers/TypefaceLoader.kt +16 -10
  42. package/lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java +5 -2
  43. package/lib/android/app/src/main/java/com/reactnativenavigation/react/modal/ModalFrameLayout.kt +3 -3
  44. package/lib/android/app/src/main/java/com/reactnativenavigation/react/modal/ModalViewManager.kt +11 -8
  45. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/SystemUiUtils.kt +168 -0
  46. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabPresenter.java +5 -2
  47. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java +42 -2
  48. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/child/ChildController.java +12 -16
  49. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewController.java +19 -11
  50. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentViewController.java +2 -2
  51. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/modal/ModalPresenter.java +6 -4
  52. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/overlay/OverlayManager.kt +8 -3
  53. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java +15 -7
  54. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenter.java +127 -138
  55. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/TopBarController.kt +183 -22
  56. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/button/ButtonController.kt +25 -4
  57. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/button/ButtonPresenter.kt +9 -1
  58. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/button/ButtonSpan.kt +1 -1
  59. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/Presenter.java +52 -71
  60. package/lib/android/app/src/main/java/com/reactnativenavigation/views/component/ComponentLayout.java +2 -0
  61. package/lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/ReactImageMatrixAnimator.kt +2 -3
  62. package/lib/android/app/src/main/java/com/reactnativenavigation/views/stack/topbar/TopBar.java +1 -2
  63. package/lib/android/app/src/main/java/com/reactnativenavigation/views/stack/topbar/titlebar/ButtonBar.kt +7 -12
  64. package/lib/android/app/src/main/java/com/reactnativenavigation/views/stack/topbar/titlebar/TitleAndButtonsContainer.kt +0 -2
  65. package/lib/android/app/src/main/java/com/reactnativenavigation/views/stack/topbar/titlebar/TitleSubTitleLayout.kt +0 -7
  66. package/lib/android/app/src/reactNative51/java/com/reactnativenavigation/react/NavigationReactNativeHost.java +2 -1
  67. package/lib/android/app/src/test/java/com/reactnativenavigation/BaseTest.java +7 -6
  68. package/lib/android/app/src/test/java/com/reactnativenavigation/TestActivity.java +5 -0
  69. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/ImageLoaderMock.kt +5 -4
  70. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/Mocks.kt +3 -2
  71. package/lib/android/app/src/test/java/com/reactnativenavigation/mocks/TypefaceLoaderMock.kt +5 -1
  72. package/lib/android/app/src/test/java/com/reactnativenavigation/options/TransitionAnimationOptionsTest.kt +2 -3
  73. package/lib/android/app/src/test/java/com/reactnativenavigation/presentation/PresenterTest.java +25 -10
  74. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/LayoutFactoryTest.java +25 -2
  75. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/MotionEventTest.kt +1 -1
  76. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/{TitleAndButtonsMeasurer.kt → TitleAndButtonsMeasurerTest.kt} +2 -2
  77. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/UiThreadTest.java +2 -2
  78. package/lib/android/app/src/test/java/com/reactnativenavigation/utils/UiUtilsTest.java +1 -1
  79. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsControllerTest.kt +572 -0
  80. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsPresenterTest.kt +1 -1
  81. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/child/ChildControllerTest.java +2 -1
  82. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewControllerTest.java +5 -5
  83. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/fakes/FakeParentController.kt +1 -1
  84. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/modal/ModalAnimatorTest.kt +1 -1
  85. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/modal/ModalPresenterTest.java +7 -3
  86. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/modal/ModalStackTest.java +17 -4
  87. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/navigator/NavigatorTest.java +2 -2
  88. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/navigator/RootPresenterTest.kt +5 -5
  89. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/overlay/OverlayManagerTest.java +1 -0
  90. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/parent/ParentControllerTest.java +4 -0
  91. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/sidemenu/SideMenuControllerTest.java +6 -2
  92. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackAnimatorTest.kt +1 -1
  93. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.kt +13 -8
  94. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenterTest.kt +58 -51
  95. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/TopBarControllerTest.kt +219 -41
  96. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewControllerTest.java +4 -1
  97. package/lib/android/app/src/test/java/com/reactnativenavigation/views/TitleAndButtonsContainerTest.kt +2 -2
  98. package/lib/android/app/src/test/java/com/reactnativenavigation/views/animations/BaseViewAnimatorTest.kt +4 -4
  99. package/lib/android/app/src/test/java/com/reactnativenavigation/views/bottomtabs/BottomTabsContainerTest.kt +1 -1
  100. package/lib/android/app/src/test/java/com/reactnativenavigation/views/bottomtabs/BottomTabsTest.kt +4 -4
  101. package/lib/dist/Mock/Application.js +2 -2
  102. package/lib/dist/Mock/Components/BottomTabs.js +2 -2
  103. package/lib/dist/Mock/Components/ComponentScreen.js +15 -5
  104. package/lib/dist/Mock/Components/LayoutComponent.js +3 -2
  105. package/lib/dist/Mock/Components/Modals.js +2 -2
  106. package/lib/dist/Mock/Components/NavigationButton.d.ts +1 -1
  107. package/lib/dist/Mock/Components/NavigationButton.js +8 -10
  108. package/lib/dist/Mock/Components/Overlays.js +2 -2
  109. package/lib/dist/Mock/Components/Stack.js +2 -2
  110. package/lib/dist/Mock/Components/TopBar.d.ts +2 -2
  111. package/lib/dist/Mock/Components/TopBar.js +7 -6
  112. package/lib/dist/Mock/Layouts/BottomTabsNode.d.ts +1 -1
  113. package/lib/dist/Mock/Layouts/BottomTabsNode.js +3 -3
  114. package/lib/dist/Mock/Layouts/ComponentNode.d.ts +1 -1
  115. package/lib/dist/Mock/Layouts/ComponentNode.js +4 -4
  116. package/lib/dist/Mock/Layouts/LayoutNodeFactory.js +3 -3
  117. package/lib/dist/Mock/Layouts/Node.d.ts +1 -1
  118. package/lib/dist/Mock/Layouts/Node.js +5 -0
  119. package/lib/dist/Mock/Layouts/ParentNode.d.ts +2 -2
  120. package/lib/dist/Mock/Layouts/ParentNode.js +4 -3
  121. package/lib/dist/Mock/Layouts/StackNode.js +1 -1
  122. package/lib/dist/Mock/Stores/EventsStore.d.ts +5 -2
  123. package/lib/dist/Mock/Stores/EventsStore.js +7 -0
  124. package/lib/dist/Mock/Stores/LayoutStore.js +6 -3
  125. package/lib/dist/Mock/connect.js +1 -1
  126. package/lib/dist/Mock/index.js +1 -1
  127. package/lib/dist/Mock/mocks/NativeCommandsSender.d.ts +1 -1
  128. package/lib/dist/Mock/mocks/NativeCommandsSender.js +2 -2
  129. package/lib/dist/Mock/mocks/NativeEventsReceiver.d.ts +3 -3
  130. package/lib/dist/Mock/mocks/NativeEventsReceiver.js +6 -3
  131. package/lib/dist/{Navigation.d.ts → src/Navigation.d.ts} +0 -0
  132. package/lib/dist/{Navigation.js → src/Navigation.js} +19 -3
  133. package/lib/dist/{NavigationDelegate.d.ts → src/NavigationDelegate.d.ts} +0 -0
  134. package/lib/dist/{NavigationDelegate.js → src/NavigationDelegate.js} +1 -0
  135. package/lib/dist/{adapters → src/adapters}/AppRegistryService.d.ts +0 -0
  136. package/lib/dist/{adapters → src/adapters}/AppRegistryService.js +0 -0
  137. package/lib/dist/{adapters → src/adapters}/AssetResolver.d.ts +0 -0
  138. package/lib/dist/{adapters → src/adapters}/AssetResolver.js +0 -0
  139. package/lib/dist/src/adapters/ColorService.d.ts +3 -0
  140. package/lib/dist/{adapters → src/adapters}/ColorService.js +1 -1
  141. package/lib/dist/{adapters → src/adapters}/Constants.d.ts +0 -0
  142. package/lib/dist/{adapters → src/adapters}/Constants.js +10 -6
  143. package/lib/dist/{adapters → src/adapters}/NativeCommandsSender.d.ts +0 -0
  144. package/lib/dist/{adapters → src/adapters}/NativeCommandsSender.js +1 -0
  145. package/lib/dist/{adapters → src/adapters}/NativeEventsReceiver.d.ts +0 -0
  146. package/lib/dist/{adapters → src/adapters}/NativeEventsReceiver.js +1 -0
  147. package/lib/dist/{adapters → src/adapters}/NativeEventsReceiver.mock.d.ts +0 -0
  148. package/lib/dist/{adapters → src/adapters}/NativeEventsReceiver.mock.js +0 -0
  149. package/lib/dist/{adapters → src/adapters}/TouchablePreview.d.ts +0 -0
  150. package/lib/dist/src/adapters/TouchablePreview.js +89 -0
  151. package/lib/dist/{adapters → src/adapters}/UniqueIdProvider.d.ts +0 -0
  152. package/lib/dist/{adapters → src/adapters}/UniqueIdProvider.js +2 -2
  153. package/lib/dist/{commands → src/commands}/Commands.d.ts +0 -0
  154. package/lib/dist/{commands → src/commands}/Commands.js +24 -10
  155. package/lib/dist/{commands → src/commands}/Deprecations.d.ts +0 -0
  156. package/lib/dist/src/commands/Deprecations.js +80 -0
  157. package/lib/dist/{commands → src/commands}/LayoutTreeCrawler.d.ts +0 -0
  158. package/lib/dist/{commands → src/commands}/LayoutTreeCrawler.js +4 -2
  159. package/lib/dist/{commands → src/commands}/LayoutTreeParser.d.ts +0 -0
  160. package/lib/dist/{commands → src/commands}/LayoutTreeParser.js +1 -0
  161. package/lib/dist/{commands → src/commands}/LayoutType.d.ts +0 -0
  162. package/lib/dist/{commands → src/commands}/LayoutType.js +0 -0
  163. package/lib/dist/{commands → src/commands}/OptionsCrawler.d.ts +0 -0
  164. package/lib/dist/{commands → src/commands}/OptionsCrawler.js +6 -4
  165. package/lib/dist/{commands → src/commands}/OptionsProcessor.d.ts +1 -1
  166. package/lib/dist/{commands → src/commands}/OptionsProcessor.js +50 -42
  167. package/lib/dist/{components → src/components}/ComponentRegistry.d.ts +0 -0
  168. package/lib/dist/{components → src/components}/ComponentRegistry.js +4 -0
  169. package/lib/dist/{components → src/components}/ComponentWrapper.d.ts +0 -0
  170. package/lib/dist/{components → src/components}/ComponentWrapper.js +17 -17
  171. package/lib/dist/{components → src/components}/Modal.d.ts +0 -0
  172. package/lib/dist/{components → src/components}/Modal.js +8 -8
  173. package/lib/dist/{components → src/components}/Store.d.ts +2 -0
  174. package/lib/dist/{components → src/components}/Store.js +13 -6
  175. package/lib/dist/{events → src/events}/CommandsObserver.d.ts +0 -0
  176. package/lib/dist/{events → src/events}/CommandsObserver.js +2 -1
  177. package/lib/dist/{events → src/events}/ComponentEventsObserver.d.ts +4 -2
  178. package/lib/dist/{events → src/events}/ComponentEventsObserver.js +16 -14
  179. package/lib/dist/{events → src/events}/EventsRegistry.d.ts +2 -2
  180. package/lib/dist/{events → src/events}/EventsRegistry.js +3 -0
  181. package/lib/dist/{index.d.ts → src/index.d.ts} +0 -0
  182. package/lib/dist/src/index.js +22 -0
  183. package/lib/dist/{interfaces → src/interfaces}/CommandName.d.ts +0 -0
  184. package/lib/dist/{interfaces → src/interfaces}/CommandName.js +0 -0
  185. package/lib/dist/{interfaces → src/interfaces}/ComponentEvents.d.ts +0 -0
  186. package/lib/dist/{interfaces → src/interfaces}/ComponentEvents.js +0 -0
  187. package/lib/dist/{interfaces → src/interfaces}/EventSubscription.d.ts +0 -0
  188. package/lib/dist/{interfaces → src/interfaces}/EventSubscription.js +0 -0
  189. package/lib/dist/{interfaces → src/interfaces}/Events.d.ts +0 -0
  190. package/lib/dist/{interfaces → src/interfaces}/Events.js +0 -0
  191. package/lib/dist/{interfaces → src/interfaces}/Layout.d.ts +0 -0
  192. package/lib/dist/{interfaces → src/interfaces}/Layout.js +0 -0
  193. package/lib/dist/{interfaces → src/interfaces}/NavigationComponent.d.ts +0 -0
  194. package/lib/dist/{interfaces → src/interfaces}/NavigationComponent.js +8 -1
  195. package/lib/dist/{interfaces → src/interfaces}/NavigationComponentListener.d.ts +0 -0
  196. package/lib/dist/{interfaces → src/interfaces}/NavigationComponentListener.js +0 -0
  197. package/lib/dist/{interfaces → src/interfaces}/NavigationComponentProps.d.ts +0 -0
  198. package/lib/dist/{interfaces → src/interfaces}/NavigationComponentProps.js +0 -0
  199. package/lib/dist/{interfaces → src/interfaces}/NavigationFunctionComponent.d.ts +0 -0
  200. package/lib/dist/{interfaces → src/interfaces}/NavigationFunctionComponent.js +0 -0
  201. package/lib/dist/{interfaces → src/interfaces}/Options.d.ts +9 -0
  202. package/lib/dist/{interfaces → src/interfaces}/Options.js +0 -0
  203. package/lib/dist/{interfaces → src/interfaces}/ProcessorSubscription.d.ts +0 -0
  204. package/lib/dist/{interfaces → src/interfaces}/ProcessorSubscription.js +0 -0
  205. package/lib/dist/{interfaces → src/interfaces}/Processors.d.ts +0 -0
  206. package/lib/dist/{interfaces → src/interfaces}/Processors.js +0 -0
  207. package/lib/dist/{processors → src/processors}/LayoutProcessor.d.ts +0 -0
  208. package/lib/dist/{processors → src/processors}/LayoutProcessor.js +1 -0
  209. package/lib/dist/{processors → src/processors}/LayoutProcessorsStore.d.ts +0 -0
  210. package/lib/dist/{processors → src/processors}/LayoutProcessorsStore.js +1 -3
  211. package/lib/dist/{processors → src/processors}/OptionProcessorsStore.d.ts +0 -0
  212. package/lib/dist/{processors → src/processors}/OptionProcessorsStore.js +1 -3
  213. package/lib/dist/{types.d.ts → src/types.d.ts} +0 -0
  214. package/lib/dist/{types.js → src/types.js} +0 -0
  215. package/lib/ios/AnimationObserver.h +17 -0
  216. package/lib/ios/AnimationObserver.m +41 -0
  217. package/lib/ios/BottomTabPresenter.h +0 -3
  218. package/lib/ios/BottomTabPresenter.m +0 -8
  219. package/lib/ios/RNNAssert.h +2 -2
  220. package/lib/ios/RNNBasePresenter.h +0 -4
  221. package/lib/ios/RNNBasePresenter.m +0 -12
  222. package/lib/ios/RNNBottomTabOptions.m +2 -1
  223. package/lib/ios/RNNBottomTabsController.m +8 -8
  224. package/lib/ios/RNNBridgeManager.mm +0 -1
  225. package/lib/ios/RNNButtonBuilder.m +2 -0
  226. package/lib/ios/RNNButtonOptions.h +1 -0
  227. package/lib/ios/RNNButtonOptions.m +4 -0
  228. package/lib/ios/RNNCommandsHandler.m +15 -8
  229. package/lib/ios/RNNComponentPresenter.m +0 -4
  230. package/lib/ios/RNNComponentViewController.m +2 -4
  231. package/lib/ios/RNNDotIndicatorPresenter.m +2 -1
  232. package/lib/ios/RNNExternalViewController.m +2 -4
  233. package/lib/ios/RNNModalManager.h +2 -1
  234. package/lib/ios/RNNModalManager.m +12 -21
  235. package/lib/ios/RNNSegmentedControl.h +1 -1
  236. package/lib/ios/RNNSideMenuChildVC.m +0 -4
  237. package/lib/ios/RNNSideMenuController.m +0 -4
  238. package/lib/ios/RNNSplitViewController.m +0 -4
  239. package/lib/ios/RNNStackController.m +0 -4
  240. package/lib/ios/RNNStackPresenter.m +3 -0
  241. package/lib/ios/RNNSwizzles.m +20 -0
  242. package/lib/ios/RNNTabBarItemCreator.m +3 -2
  243. package/lib/ios/RNNUIBarButtonItem.h +2 -0
  244. package/lib/ios/RNNUIBarButtonItem.m +17 -0
  245. package/lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj +8 -0
  246. package/lib/ios/TopBarPresenter.m +8 -4
  247. package/lib/ios/UIViewController+RNNOptions.m +1 -1
  248. package/lib/src/commands/Commands.ts +6 -1
  249. package/lib/src/commands/LayoutTreeCrawler.ts +2 -2
  250. package/lib/src/commands/OptionsCrawler.ts +2 -1
  251. package/lib/src/commands/OptionsProcessor.ts +15 -13
  252. package/lib/src/components/Store.ts +9 -0
  253. package/lib/src/events/ComponentEventsObserver.ts +5 -1
  254. package/lib/src/events/EventsRegistry.ts +2 -1
  255. package/lib/src/interfaces/Options.ts +10 -0
  256. package/package.json +19 -60
  257. package/tsconfig.mocks.json +7 -0
  258. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/StatusBarUtils.java +0 -41
  259. package/lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsControllerTest.java +0 -511
  260. package/lib/dist/adapters/ColorService.d.ts +0 -3
  261. package/lib/dist/adapters/TouchablePreview.js +0 -91
  262. package/lib/dist/commands/Deprecations.js +0 -82
  263. package/lib/dist/index.js +0 -22
@@ -1,9 +1,11 @@
1
1
  package com.reactnativenavigation.options;
2
2
 
3
3
  import android.app.Activity;
4
+ import android.content.Context;
4
5
 
5
6
  import com.facebook.react.ReactInstanceManager;
6
7
  import com.facebook.react.bridge.ReactContext;
8
+ import com.reactnativenavigation.NavigationApplication;
7
9
  import com.reactnativenavigation.options.parsers.TypefaceLoader;
8
10
  import com.reactnativenavigation.react.events.EventEmitter;
9
11
  import com.reactnativenavigation.utils.Assertions;
@@ -45,6 +47,8 @@ import androidx.annotation.RestrictTo;
45
47
  import static com.reactnativenavigation.options.Options.parse;
46
48
  import static com.reactnativenavigation.utils.CollectionUtils.*;
47
49
 
50
+ import org.json.JSONObject;
51
+
48
52
  public class LayoutFactory {
49
53
  private Activity activity;
50
54
  private ChildControllersRegistry childRegistry;
@@ -75,15 +79,15 @@ public class LayoutFactory {
75
79
  final ReactContext context = reactInstanceManager.getCurrentReactContext();
76
80
  switch (node.type) {
77
81
  case Component:
78
- return createComponent(context, node);
82
+ return createComponent(node);
79
83
  case ExternalComponent:
80
84
  return createExternalComponent(context, node);
81
85
  case Stack:
82
- return createStack(context, node);
86
+ return createStack(node);
83
87
  case BottomTabs:
84
- return createBottomTabs(context, node);
88
+ return createBottomTabs(node);
85
89
  case SideMenuRoot:
86
- return createSideMenuRoot(context, node);
90
+ return createSideMenuRoot(node);
87
91
  case SideMenuCenter:
88
92
  return createSideMenuContent(node);
89
93
  case SideMenuLeft:
@@ -91,17 +95,17 @@ public class LayoutFactory {
91
95
  case SideMenuRight:
92
96
  return createSideMenuRight(node);
93
97
  case TopTabs:
94
- return createTopTabs(context, node);
98
+ return createTopTabs(node);
95
99
  default:
96
100
  throw new IllegalArgumentException("Invalid node type: " + node.type);
97
101
  }
98
102
  }
99
103
 
100
- private ViewController<?> createSideMenuRoot(ReactContext context, LayoutNode node) {
104
+ private ViewController<?> createSideMenuRoot(LayoutNode node) {
101
105
  SideMenuController sideMenuController = new SideMenuController(activity,
102
106
  childRegistry,
103
107
  node.id,
104
- parse(context, typefaceManager, node.getOptions()),
108
+ parseOptions( node.getOptions()),
105
109
  new SideMenuPresenter(),
106
110
  new Presenter(activity, defaultOptions)
107
111
  );
@@ -153,7 +157,7 @@ public class LayoutFactory {
153
157
  return create(node.children.get(0));
154
158
  }
155
159
 
156
- private ViewController<?> createComponent(ReactContext context, LayoutNode node) {
160
+ private ViewController<?> createComponent(LayoutNode node) {
157
161
  String id = node.id;
158
162
  String name = node.data.optString("name");
159
163
  return new ComponentViewController(activity,
@@ -161,7 +165,7 @@ public class LayoutFactory {
161
165
  id,
162
166
  name,
163
167
  new ComponentViewCreator(reactInstanceManager),
164
- parse(context, typefaceManager, node.getOptions()),
168
+ parseOptions(node.getOptions()),
165
169
  new Presenter(activity, defaultOptions),
166
170
  new ComponentPresenter(defaultOptions)
167
171
  );
@@ -178,17 +182,17 @@ public class LayoutFactory {
178
182
  reactInstanceManager,
179
183
  new EventEmitter(context),
180
184
  new ExternalComponentPresenter(),
181
- parse(context, typefaceManager, node.getOptions())
185
+ parseOptions(node.getOptions())
182
186
  );
183
187
  }
184
188
 
185
- private ViewController<?> createStack(ReactContext context, LayoutNode node) {
189
+ private ViewController<?> createStack(LayoutNode node) {
186
190
  return new StackControllerBuilder(activity, eventEmitter)
187
191
  .setChildren(createChildren(node.children))
188
192
  .setChildRegistry(childRegistry)
189
193
  .setTopBarController(new TopBarController())
190
194
  .setId(node.id)
191
- .setInitialOptions(parse(context, typefaceManager, node.getOptions()))
195
+ .setInitialOptions(parseOptions(node.getOptions()))
192
196
  .setStackPresenter(new StackPresenter(activity,
193
197
  new TitleBarReactViewCreator(reactInstanceManager),
194
198
  new TopBarBackgroundViewCreator(reactInstanceManager),
@@ -210,7 +214,7 @@ public class LayoutFactory {
210
214
  return result;
211
215
  }
212
216
 
213
- private ViewController<?> createBottomTabs(ReactContext context, LayoutNode node) {
217
+ private ViewController<?> createBottomTabs(LayoutNode node) {
214
218
  List<ViewController<?>> tabs = map(node.children, this::create);
215
219
  BottomTabsPresenter bottomTabsPresenter = new BottomTabsPresenter(tabs, defaultOptions, new BottomTabsAnimator());
216
220
  return new BottomTabsController(activity,
@@ -219,24 +223,35 @@ public class LayoutFactory {
219
223
  eventEmitter,
220
224
  new ImageLoader(),
221
225
  node.id,
222
- parse(context, typefaceManager, node.getOptions()),
226
+ parseOptions( node.getOptions()),
223
227
  new Presenter(activity, defaultOptions),
224
228
  new BottomTabsAttacher(tabs, bottomTabsPresenter, defaultOptions),
225
229
  bottomTabsPresenter,
226
230
  new BottomTabPresenter(activity, tabs, new ImageLoader(), new TypefaceLoader(activity), defaultOptions));
227
231
  }
228
232
 
229
- private ViewController<?> createTopTabs(ReactContext context, LayoutNode node) {
233
+ private ViewController<?> createTopTabs(LayoutNode node) {
230
234
  final List<ViewController<?>> tabs = new ArrayList<>();
231
235
  for (int i = 0; i < node.children.size(); i++) {
232
236
  ViewController<?> tabController = create(node.children.get(i));
233
- Options options = parse(context, typefaceManager, node.children.get(i).getOptions());
237
+ Options options = parseOptions(node.children.get(i).getOptions());
234
238
  options.setTopTabIndex(i);
235
239
  tabs.add(tabController);
236
240
  }
237
- return new TopTabsController(activity, childRegistry, node.id, tabs, new TopTabsLayoutCreator(activity, tabs), parse(context, typefaceManager, node.getOptions()), new Presenter(activity, defaultOptions));
241
+ return new TopTabsController(activity, childRegistry, node.id, tabs, new TopTabsLayoutCreator(activity, tabs)
242
+ , parseOptions(node.getOptions()), new Presenter(activity, defaultOptions));
238
243
  }
239
244
 
245
+ private Options parseOptions(JSONObject jsonOptions) {
246
+ Context context = reactInstanceManager.getCurrentReactContext();
247
+ if (context == null) {
248
+ context = activity == null ? NavigationApplication.instance : activity;
249
+ }
250
+ if (typefaceManager == null) {
251
+ typefaceManager = new TypefaceLoader(context);
252
+ }
253
+ return parse(context, typefaceManager, jsonOptions);
254
+ }
240
255
  @NonNull
241
256
  @RestrictTo(RestrictTo.Scope.TESTS)
242
257
  public Options getDefaultOptions() {
@@ -15,7 +15,7 @@ public class Options {
15
15
  public static final Options EMPTY = new Options();
16
16
 
17
17
  @NonNull
18
- public static Options parse(Context context, TypefaceLoader typefaceManager, JSONObject json) {
18
+ public static Options parse(@NonNull Context context, TypefaceLoader typefaceManager, JSONObject json) {
19
19
  Options result = new Options();
20
20
  if (json == null) return result;
21
21
 
@@ -2,21 +2,27 @@ package com.reactnativenavigation.options.parsers
2
2
 
3
3
  import android.content.Context
4
4
  import android.graphics.Typeface
5
+ import com.aurelhubert.ahbottomnavigation.AHTextView
5
6
  import com.reactnativenavigation.utils.ReactTypefaceUtils
6
7
 
7
8
  open class TypefaceLoader(private val context: Context) {
8
- @JvmOverloads open fun getTypeFace(
9
- fontFamilyName: String?,
10
- fontStyle: String?,
11
- fontWeight: String?,
12
- defaultTypeFace: Typeface? = null
9
+ open val defaultTypeFace: Typeface by lazy {
10
+ AHTextView(context).typeface ?: Typeface.DEFAULT
11
+ }
12
+
13
+ @JvmOverloads
14
+ open fun getTypeFace(
15
+ fontFamilyName: String?,
16
+ fontStyle: String?,
17
+ fontWeight: String?,
18
+ defaultTypeFace: Typeface? = null
13
19
  ): Typeface? {
14
20
  return ReactTypefaceUtils.applyStyles(
15
- defaultTypeFace,
16
- ReactTypefaceUtils.parseFontStyle(fontStyle),
17
- ReactTypefaceUtils.parseFontWeight(fontWeight),
18
- fontFamilyName,
19
- context.assets
21
+ defaultTypeFace,
22
+ ReactTypefaceUtils.parseFontStyle(fontStyle),
23
+ ReactTypefaceUtils.parseFontWeight(fontWeight),
24
+ fontFamilyName,
25
+ context.assets
20
26
  )
21
27
  }
22
28
  }
@@ -23,7 +23,7 @@ import com.reactnativenavigation.options.parsers.TypefaceLoader;
23
23
  import com.reactnativenavigation.react.events.EventEmitter;
24
24
  import com.reactnativenavigation.utils.LaunchArgsParser;
25
25
  import com.reactnativenavigation.utils.Now;
26
- import com.reactnativenavigation.utils.StatusBarUtils;
26
+ import com.reactnativenavigation.utils.SystemUiUtils;
27
27
  import com.reactnativenavigation.utils.UiThread;
28
28
  import com.reactnativenavigation.utils.UiUtils;
29
29
  import com.reactnativenavigation.viewcontrollers.navigator.Navigator;
@@ -34,6 +34,8 @@ import java.util.Objects;
34
34
 
35
35
  import static com.reactnativenavigation.utils.UiUtils.pxToDp;
36
36
 
37
+ import android.app.Activity;
38
+
37
39
  public class NavigationModule extends ReactContextBaseJavaModule {
38
40
  private static final String NAME = "RNNBridgeModule";
39
41
 
@@ -88,10 +90,11 @@ public class NavigationModule extends ReactContextBaseJavaModule {
88
90
 
89
91
  private WritableMap createNavigationConstantsMap() {
90
92
  ReactApplicationContext ctx = getReactApplicationContext();
93
+ final Activity currentActivity = ctx.getCurrentActivity();
91
94
  WritableMap constants = Arguments.createMap();
92
95
  constants.putString(Constants.BACK_BUTTON_JS_KEY, Constants.BACK_BUTTON_ID);
93
96
  constants.putDouble(Constants.BOTTOM_TABS_HEIGHT_KEY, pxToDp(ctx, UiUtils.getBottomTabsHeight(ctx)));
94
- constants.putDouble(Constants.STATUS_BAR_HEIGHT_KEY, pxToDp(ctx, StatusBarUtils.getStatusBarHeight(ctx)));
97
+ constants.putDouble(Constants.STATUS_BAR_HEIGHT_KEY, pxToDp(ctx, SystemUiUtils.getStatusBarHeight(currentActivity)));
95
98
  constants.putDouble(Constants.TOP_BAR_HEIGHT_KEY, pxToDp(ctx, UiUtils.getTopBarHeight(ctx)));
96
99
  return constants;
97
100
  }
@@ -2,7 +2,7 @@ package com.reactnativenavigation.react.modal
2
2
 
3
3
  import android.widget.FrameLayout
4
4
  import com.facebook.react.bridge.ReactContext
5
- import com.reactnativenavigation.utils.StatusBarUtils
5
+ import com.reactnativenavigation.utils.SystemUiUtils
6
6
 
7
7
  class ModalFrameLayout(context: ReactContext) : FrameLayout(context) {
8
8
  val modalContentLayout = ModalContentLayout(context)
@@ -11,9 +11,9 @@ class ModalFrameLayout(context: ReactContext) : FrameLayout(context) {
11
11
  addView(modalContentLayout, MarginLayoutParams(MarginLayoutParams.WRAP_CONTENT, MarginLayoutParams.WRAP_CONTENT)
12
12
  .apply {
13
13
  val translucent = context.currentActivity?.window?.let {
14
- StatusBarUtils.isTranslucent(context.currentActivity?.window)
14
+ SystemUiUtils.isTranslucent(it)
15
15
  } ?: false
16
- topMargin = if (translucent) 0 else StatusBarUtils.getStatusBarHeight(context)
16
+ topMargin = if (translucent) 0 else SystemUiUtils.getStatusBarHeight(context.currentActivity)
17
17
  })
18
18
  }
19
19
  }
@@ -1,5 +1,6 @@
1
1
  package com.reactnativenavigation.react.modal
2
2
 
3
+ import android.app.Activity
3
4
  import android.content.Context
4
5
  import android.graphics.Point
5
6
  import android.view.WindowManager
@@ -21,7 +22,7 @@ import com.reactnativenavigation.options.parseTransitionAnimationOptions
21
22
  import com.reactnativenavigation.options.parsers.JSONParser
22
23
  import com.reactnativenavigation.react.CommandListener
23
24
  import com.reactnativenavigation.react.CommandListenerAdapter
24
- import com.reactnativenavigation.utils.StatusBarUtils
25
+ import com.reactnativenavigation.utils.SystemUiUtils
25
26
  import com.reactnativenavigation.viewcontrollers.navigator.Navigator
26
27
 
27
28
  private const val MODAL_MANAGER_NAME = "RNNModalViewManager"
@@ -107,18 +108,18 @@ class ModalViewManager(val reactContext: ReactContext) : ViewGroupManager<ModalH
107
108
  }
108
109
  }
109
110
 
110
- private fun getModalHostSize(context: Context): Point {
111
+ private fun getModalHostSize(activity: Activity): Point {
111
112
  val MIN_POINT = Point()
112
113
  val MAX_POINT = Point()
113
114
  val SIZE_POINT = Point()
114
- val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
115
+ val wm = activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager
115
116
  val display = Assertions.assertNotNull(wm).defaultDisplay
116
117
  // getCurrentSizeRange will return the min and max width and height that the window can be
117
118
  display.getCurrentSizeRange(MIN_POINT, MAX_POINT)
118
119
  // getSize will return the dimensions of the screen in its current orientation
119
120
  display.getSize(SIZE_POINT)
120
121
  val attrs = intArrayOf(android.R.attr.windowFullscreen)
121
- val theme = context.theme
122
+ val theme = activity.theme
122
123
  val ta = theme.obtainStyledAttributes(attrs)
123
124
  val windowFullscreen = ta.getBoolean(0, false)
124
125
 
@@ -126,7 +127,7 @@ private fun getModalHostSize(context: Context): Point {
126
127
  // because Display.getCurrentSizeRange doesn't include it.
127
128
  var statusBarHeight = 0
128
129
  if (windowFullscreen) {
129
- statusBarHeight = StatusBarUtils.getStatusBarHeight(context)
130
+ statusBarHeight = SystemUiUtils.getStatusBarHeight(activity)
130
131
  }
131
132
  return if (SIZE_POINT.x < SIZE_POINT.y) {
132
133
  // If we are vertical the width value comes from min width and height comes from max height
@@ -140,8 +141,10 @@ private fun getModalHostSize(context: Context): Point {
140
141
  private class ModalHostShadowNode : LayoutShadowNode() {
141
142
  override fun addChildAt(child: ReactShadowNodeImpl, i: Int) {
142
143
  super.addChildAt(child, i)
143
- val modalSize = getModalHostSize(themedContext)
144
- child.setStyleWidth(modalSize.x.toFloat())
145
- child.setStyleHeight(modalSize.y.toFloat())
144
+ themedContext?.currentActivity?.let {
145
+ val modalSize = getModalHostSize(it)
146
+ child.setStyleWidth(modalSize.x.toFloat())
147
+ child.setStyleHeight(modalSize.y.toFloat())
148
+ }
146
149
  }
147
150
  }
@@ -0,0 +1,168 @@
1
+ package com.reactnativenavigation.utils
2
+
3
+ import android.app.Activity
4
+ import android.graphics.Color
5
+ import android.graphics.Rect
6
+ import android.os.Build
7
+ import android.view.View
8
+ import android.view.Window
9
+ import androidx.annotation.ColorInt
10
+ import androidx.core.view.WindowCompat
11
+ import androidx.core.view.WindowInsetsCompat
12
+ import androidx.core.view.WindowInsetsControllerCompat
13
+ import kotlin.math.abs
14
+ import kotlin.math.ceil
15
+
16
+
17
+ object SystemUiUtils {
18
+ private const val STATUS_BAR_HEIGHT_M = 24
19
+ private const val STATUS_BAR_HEIGHT_L = 25
20
+ private const val STATUS_BAR_HEIGHT_TRANSLUCENCY = 0.65f
21
+ private var statusBarHeight = -1
22
+ var navigationBarDefaultColor = -1
23
+ private set
24
+
25
+
26
+ @JvmStatic
27
+ fun getStatusBarHeight(activity: Activity?): Int {
28
+ val res = if (statusBarHeight > 0) {
29
+ statusBarHeight
30
+ } else {
31
+ statusBarHeight = activity?.let {
32
+ val rectangle = Rect()
33
+ val window: Window = activity.window
34
+ window.decorView.getWindowVisibleDisplayFrame(rectangle)
35
+ val statusBarHeight: Int = rectangle.top
36
+ val contentView = window.findViewById<View>(Window.ID_ANDROID_CONTENT)
37
+ contentView?.let {
38
+ val contentViewTop = contentView.top
39
+ abs(contentViewTop - statusBarHeight)
40
+ }
41
+ } ?: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) STATUS_BAR_HEIGHT_M else STATUS_BAR_HEIGHT_L
42
+ statusBarHeight
43
+ }
44
+ return res
45
+ }
46
+
47
+ @JvmStatic
48
+ fun saveStatusBarHeight(height: Int) {
49
+ statusBarHeight = height
50
+ }
51
+
52
+
53
+ @JvmStatic
54
+ fun getStatusBarHeightDp(activity: Activity?): Int {
55
+ return UiUtils.pxToDp(activity, getStatusBarHeight(activity).toFloat())
56
+ .toInt()
57
+ }
58
+
59
+ @JvmStatic
60
+ fun hideNavigationBar(window: Window?, view: View) {
61
+ window?.let {
62
+ WindowCompat.setDecorFitsSystemWindows(window, false)
63
+ WindowInsetsControllerCompat(window, view).let { controller ->
64
+ controller.hide(WindowInsetsCompat.Type.navigationBars())
65
+ controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
66
+ }
67
+ }
68
+ }
69
+
70
+ @JvmStatic
71
+ fun showNavigationBar(window: Window?, view: View) {
72
+ window?.let {
73
+ WindowCompat.setDecorFitsSystemWindows(window, true)
74
+ WindowInsetsControllerCompat(window, view).show(WindowInsetsCompat.Type.navigationBars())
75
+ }
76
+ }
77
+
78
+ @JvmStatic
79
+ fun setStatusBarColorScheme(window: Window?, view: View, isDark: Boolean) {
80
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return
81
+
82
+ window?.let {
83
+ WindowInsetsControllerCompat(window, view).isAppearanceLightStatusBars = isDark
84
+ // Workaround: on devices with api 30 status bar icons flickers or get hidden when removing view
85
+ //turns out it is a bug on such devices, fixed by using system flags until it is fixed.
86
+ var flags = view.systemUiVisibility
87
+ flags = if (isDark) {
88
+ flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
89
+ } else {
90
+ flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
91
+ }
92
+
93
+ view.systemUiVisibility = flags
94
+ }
95
+ }
96
+
97
+ @JvmStatic
98
+ fun setStatusBarTranslucent(window: Window?) {
99
+ window?.let {
100
+ setStatusBarColor(window, window.statusBarColor, true)
101
+ }
102
+ }
103
+
104
+ @JvmStatic
105
+ fun isTranslucent(window: Window?): Boolean {
106
+ return window?.let {
107
+ Color.alpha(it.statusBarColor) < 255
108
+ } ?: false
109
+ }
110
+
111
+ @JvmStatic
112
+ fun clearStatusBarTranslucency(window: Window?) {
113
+ window?.let {
114
+ setStatusBarColor(it, it.statusBarColor, false)
115
+ }
116
+ }
117
+
118
+ @JvmStatic
119
+ fun setStatusBarColor(
120
+ window: Window?,
121
+ @ColorInt color: Int,
122
+ translucent: Boolean
123
+ ) {
124
+ val opaqueColor = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
125
+ Color.BLACK
126
+ }else{
127
+ val alpha = if (translucent) STATUS_BAR_HEIGHT_TRANSLUCENCY else 1f
128
+ val red: Int = Color.red(color)
129
+ val green: Int = Color.green(color)
130
+ val blue: Int = Color.blue(color)
131
+ Color.argb(ceil(alpha * 255).toInt(), red, green, blue)
132
+ }
133
+ window?.statusBarColor = opaqueColor
134
+ }
135
+
136
+ @JvmStatic
137
+ fun hideStatusBar(window: Window?, view: View) {
138
+ window?.let {
139
+ WindowCompat.setDecorFitsSystemWindows(window, false)
140
+ WindowInsetsControllerCompat(window, view).let { controller ->
141
+ controller.hide(WindowInsetsCompat.Type.statusBars())
142
+ controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
143
+ }
144
+ }
145
+ }
146
+
147
+ @JvmStatic
148
+ fun showStatusBar(window: Window?, view: View) {
149
+ window?.let {
150
+ WindowCompat.setDecorFitsSystemWindows(window, true)
151
+ WindowInsetsControllerCompat(window, view).show(WindowInsetsCompat.Type.statusBars())
152
+ }
153
+ }
154
+
155
+ @JvmStatic
156
+ fun setNavigationBarBackgroundColor(window: Window?, color: Int, lightColor: Boolean) {
157
+ window?.let {
158
+ if (navigationBarDefaultColor == -1) {
159
+ navigationBarDefaultColor = window.navigationBarColor
160
+ }
161
+ WindowInsetsControllerCompat(window, window.decorView).let { controller ->
162
+ controller.isAppearanceLightNavigationBars = lightColor
163
+ }
164
+ window.navigationBarColor = color
165
+ }
166
+ }
167
+
168
+ }
@@ -9,6 +9,7 @@ import android.graphics.drawable.Drawable;
9
9
 
10
10
  import androidx.annotation.NonNull;
11
11
 
12
+ import com.aurelhubert.ahbottomnavigation.AHTextView;
12
13
  import com.aurelhubert.ahbottomnavigation.notification.AHNotification;
13
14
  import com.reactnativenavigation.options.BottomTabOptions;
14
15
  import com.reactnativenavigation.options.DotIndicatorOptions;
@@ -27,6 +28,7 @@ public class BottomTabPresenter {
27
28
  private final Context context;
28
29
  private final ImageLoader imageLoader;
29
30
  private final TypefaceLoader typefaceLoader;
31
+ private final Typeface defaultTypeface;
30
32
  private Options defaultOptions;
31
33
  private final BottomTabFinder bottomTabFinder;
32
34
  private final LateInit<BottomTabs> bottomTabs = new LateInit<>();
@@ -39,6 +41,7 @@ public class BottomTabPresenter {
39
41
  this.bottomTabFinder = new BottomTabFinder(tabs);
40
42
  this.imageLoader = imageLoader;
41
43
  this.typefaceLoader = typefaceLoader;
44
+ this.defaultTypeface = typefaceLoader.getDefaultTypeFace();
42
45
  this.defaultOptions = defaultOptions;
43
46
  defaultDotIndicatorSize = dpToPx(context, 6);
44
47
  }
@@ -57,7 +60,7 @@ public class BottomTabPresenter {
57
60
  BottomTabOptions tab = tabs.get(i).resolveCurrentOptions(defaultOptions).bottomTabOptions;
58
61
  bottomTabs.setIconWidth(i, tab.iconWidth.get(null));
59
62
  bottomTabs.setIconHeight(i, tab.iconHeight.get(null));
60
- bottomTabs.setTitleTypeface(i, tab.font.getTypeface(typefaceLoader, Typeface.DEFAULT));
63
+ bottomTabs.setTitleTypeface(i, tab.font.getTypeface(typefaceLoader, defaultTypeface));
61
64
  if (tab.selectedIconColor.canApplyValue()) bottomTabs.setIconActiveColor(i, tab.selectedIconColor.get(null));
62
65
  if (tab.iconColor.canApplyValue()) bottomTabs.setIconInactiveColor(i, tab.iconColor.get(null));
63
66
  bottomTabs.setTitleActiveColor(i, tab.selectedTextColor.get(null));
@@ -86,7 +89,7 @@ public class BottomTabPresenter {
86
89
  BottomTabOptions tab = options.bottomTabOptions;
87
90
  if (tab.iconWidth.hasValue()) bottomTabs.setIconWidth(index, tab.iconWidth.get(null));
88
91
  if (tab.iconHeight.hasValue()) bottomTabs.setIconHeight(index, tab.iconHeight.get(null));
89
- if (tab.font.hasValue()) bottomTabs.setTitleTypeface(index, tab.font.getTypeface(typefaceLoader, Typeface.DEFAULT));
92
+ if (tab.font.hasValue()) bottomTabs.setTitleTypeface(index, tab.font.getTypeface(typefaceLoader, defaultTypeface));
90
93
  if (canMergeColor(tab.selectedIconColor)) bottomTabs.setIconActiveColor(index, tab.selectedIconColor.get());
91
94
  if (canMergeColor(tab.iconColor)) bottomTabs.setIconInactiveColor(index, tab.iconColor.get());
92
95
  if (tab.selectedTextColor.hasValue()) bottomTabs.setTitleActiveColor(index, tab.selectedTextColor.get());
@@ -13,6 +13,7 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
13
13
  import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
14
14
  import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
15
15
  import com.reactnativenavigation.options.BottomTabOptions;
16
+ import com.reactnativenavigation.options.HwBackBottomTabsBehaviour;
16
17
  import com.reactnativenavigation.options.Options;
17
18
  import com.reactnativenavigation.react.CommandListener;
18
19
  import com.reactnativenavigation.react.CommandListenerAdapter;
@@ -29,6 +30,8 @@ import com.reactnativenavigation.views.bottomtabs.BottomTabsContainer;
29
30
  import com.reactnativenavigation.views.bottomtabs.BottomTabsLayout;
30
31
 
31
32
  import java.util.Collection;
33
+ import java.util.Deque;
34
+ import java.util.LinkedList;
32
35
  import java.util.List;
33
36
 
34
37
  import static com.reactnativenavigation.utils.CollectionUtils.forEach;
@@ -39,6 +42,7 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
39
42
 
40
43
  private BottomTabsContainer bottomTabsContainer;
41
44
  private BottomTabs bottomTabs;
45
+ private final Deque<Integer> selectionStack;
42
46
  private final List<ViewController<?>> tabs;
43
47
  private final EventEmitter eventEmitter;
44
48
  private final ImageLoader imageLoader;
@@ -66,6 +70,7 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
66
70
  this.presenter = bottomTabsPresenter;
67
71
  this.tabPresenter = bottomTabPresenter;
68
72
  forEach(tabs, tab -> tab.setParentController(this));
73
+ selectionStack = new LinkedList<>();
69
74
  }
70
75
 
71
76
  @Override
@@ -156,7 +161,27 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
156
161
 
157
162
  @Override
158
163
  public boolean handleBack(CommandListener listener) {
159
- return !tabs.isEmpty() && tabs.get(bottomTabs.getCurrentItem()).handleBack(listener);
164
+ final boolean childBack = !tabs.isEmpty() && tabs.get(bottomTabs.getCurrentItem()).handleBack(listener);
165
+ final Options options = resolveCurrentOptions();
166
+ if (!childBack) {
167
+ if (options.hardwareBack.getBottomTabOnPress() instanceof HwBackBottomTabsBehaviour.PrevSelection) {
168
+ if (!selectionStack.isEmpty()) {
169
+ final int prevSelectedTabIndex = selectionStack.poll();
170
+ selectTab(prevSelectedTabIndex, false);
171
+ return true;
172
+ }
173
+ } else if (options.hardwareBack.getBottomTabOnPress() instanceof HwBackBottomTabsBehaviour.JumpToFirst) {
174
+ if (getSelectedIndex() != 0) {
175
+ selectTab(0, false);
176
+ return true;
177
+ } else {
178
+ return false;
179
+ }
180
+ } else {
181
+ return false;
182
+ }
183
+ }
184
+ return childBack;
160
185
  }
161
186
 
162
187
  @Override
@@ -203,7 +228,7 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
203
228
  });
204
229
  }
205
230
 
206
- int getSelectedIndex() {
231
+ public int getSelectedIndex() {
207
232
  return bottomTabs.getCurrentItem();
208
233
  }
209
234
 
@@ -239,6 +264,12 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
239
264
 
240
265
  @Override
241
266
  public void selectTab(final int newIndex) {
267
+ final boolean enableSelectionHistory = resolveCurrentOptions().hardwareBack.getBottomTabOnPress() instanceof HwBackBottomTabsBehaviour.PrevSelection;
268
+ selectTab(newIndex, enableSelectionHistory);
269
+ }
270
+
271
+ private void selectTab(int newIndex, boolean enableSelectionHistory) {
272
+ saveTabSelection(newIndex, enableSelectionHistory);
242
273
  tabsAttacher.onTabSelected(tabs.get(newIndex));
243
274
  getCurrentView().setVisibility(View.INVISIBLE);
244
275
  bottomTabs.setCurrentItem(newIndex, false);
@@ -246,6 +277,15 @@ public class BottomTabsController extends ParentController<BottomTabsLayout> imp
246
277
  getCurrentChild().onViewDidAppear();
247
278
  }
248
279
 
280
+ private void saveTabSelection(int newIndex, boolean enableSelectionHistory) {
281
+ if (enableSelectionHistory) {
282
+ if (selectionStack.isEmpty()
283
+ || selectionStack.peek() != newIndex
284
+ || bottomTabs.getCurrentItem() != newIndex)
285
+ selectionStack.offerFirst(bottomTabs.getCurrentItem());
286
+ }
287
+ }
288
+
249
289
  @NonNull
250
290
  private ViewGroup getCurrentView() {
251
291
  return tabs.get(bottomTabs.getCurrentItem()).getView();