react-native-navigation 7.43.0 → 7.45.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 (73) hide show
  1. package/lib/Mock/Components/ComponentScreen.tsx +29 -15
  2. package/lib/Mock/Components/LayoutComponent.tsx +2 -2
  3. package/lib/Mock/index.js +2 -2
  4. package/lib/android/app/build.gradle +1 -0
  5. package/lib/android/app/src/main/java/com/reactnativenavigation/FeatureToggles.kt +62 -0
  6. package/lib/android/app/src/main/java/com/reactnativenavigation/NavigationActivity.java +2 -2
  7. package/lib/android/app/src/main/java/com/reactnativenavigation/NavigationApplication.java +20 -4
  8. package/lib/android/app/src/main/java/com/reactnativenavigation/options/ValueAnimationOptions.kt +3 -3
  9. package/lib/android/app/src/main/java/com/reactnativenavigation/react/ReactView.java +3 -3
  10. package/lib/android/app/src/main/java/com/reactnativenavigation/react/modal/ModalHostLayout.kt +1 -1
  11. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ColorUtils.java +11 -0
  12. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ReactTypefaceUtils.java +3 -2
  13. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ReactViewGroup.kt +4 -2
  14. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/StubAnimationListener.kt +19 -0
  15. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/SystemUiUtils.kt +17 -16
  16. package/lib/android/app/src/main/java/com/reactnativenavigation/utils/ViewUtils.java +6 -4
  17. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabPresenter.java +0 -1
  18. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsAnimator.kt +2 -2
  19. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java +20 -13
  20. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/child/ChildController.java +7 -14
  21. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentPresenter.java +18 -0
  22. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/component/ComponentViewController.java +24 -12
  23. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java +52 -24
  24. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackPresenter.java +20 -10
  25. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/{TopBarAnimator.kt → TopBarAppearanceAnimator.kt} +4 -2
  26. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/TopBarCollapseBehavior.kt +1 -1
  27. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/TopBarController.kt +154 -26
  28. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/statusbar/StatusBarPresenter.kt +212 -0
  29. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/LayoutDirectionApplier.kt +8 -4
  30. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/Presenter.java +12 -107
  31. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/RootPresenter.java +1 -1
  32. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/StatusBarColorAnimator.kt +28 -0
  33. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewController.java +34 -2
  34. package/lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/viewcontroller/ViewControllerVisibilityInfo.kt +5 -0
  35. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/{BaseViewAnimator.kt → BaseViewAppearanceAnimator.kt} +4 -4
  36. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ColorAnimator.kt +22 -0
  37. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/DefaultViewAnimatorCreator.kt +8 -8
  38. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ViewAnimatorCreator.kt +2 -2
  39. package/lib/android/app/src/main/java/com/reactnativenavigation/views/animations/ViewBkgColorProperty.kt +17 -0
  40. package/lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/BackgroundColorAnimator.kt +6 -4
  41. package/lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/BackgroundColorEvaluator.kt +4 -2
  42. package/lib/android/app/src/reactNative71/java/com/reactnativenavigation/react/modal/ModalContentLayout.kt +6 -6
  43. package/lib/dist/Mock/Application.d.ts +4 -6
  44. package/lib/dist/Mock/Components/BottomTabs.d.ts +9 -13
  45. package/lib/dist/Mock/Components/ComponentScreen.d.ts +5 -7
  46. package/lib/dist/Mock/Components/ComponentScreen.js +10 -3
  47. package/lib/dist/Mock/Components/LayoutComponent.d.ts +9 -13
  48. package/lib/dist/Mock/Components/Modals.d.ts +9 -13
  49. package/lib/dist/Mock/Components/NavigationButton.d.ts +11 -15
  50. package/lib/dist/Mock/Components/Overlays.d.ts +9 -13
  51. package/lib/dist/Mock/Components/Stack.d.ts +9 -13
  52. package/lib/dist/Mock/Components/TopBar.d.ts +7 -9
  53. package/lib/dist/Mock/connect.js +2 -1
  54. package/lib/dist/Mock/index.js +2 -2
  55. package/lib/dist/src/adapters/NativeEventsReceiver.js +1 -1
  56. package/lib/dist/src/adapters/TouchablePreview.d.ts +2 -2
  57. package/lib/dist/src/commands/LayoutType.js +1 -1
  58. package/lib/dist/src/commands/OptionsProcessor.js +8 -1
  59. package/lib/dist/src/components/Modal.d.ts +1 -1
  60. package/lib/dist/src/interfaces/CommandName.js +1 -1
  61. package/lib/dist/src/interfaces/Options.d.ts +33 -3
  62. package/lib/dist/src/interfaces/Options.js +2 -2
  63. package/lib/dist/src/types.d.ts +1 -0
  64. package/lib/ios/BottomTabsBasePresenter.m +3 -2
  65. package/lib/ios/RNNAppDelegate.mm +1 -2
  66. package/lib/ios/RNNConvert.h +2 -0
  67. package/lib/ios/RNNConvert.m +4 -0
  68. package/lib/ios/RNNStackPresenter.m +3 -2
  69. package/lib/src/adapters/NativeEventsReceiver.ts +3 -3
  70. package/lib/src/adapters/TouchablePreview.tsx +3 -3
  71. package/lib/src/commands/OptionsProcessor.ts +13 -2
  72. package/lib/src/interfaces/Options.ts +38 -3
  73. package/package.json +37 -31
@@ -1,26 +1,26 @@
1
1
  package com.reactnativenavigation.viewcontrollers.component;
2
2
 
3
+ import static com.reactnativenavigation.utils.ObjectUtils.perform;
4
+
5
+ import android.animation.Animator;
3
6
  import android.app.Activity;
4
7
  import android.content.res.Configuration;
5
8
  import android.view.View;
6
9
 
7
- import com.reactnativenavigation.utils.LogKt;
8
- import com.reactnativenavigation.viewcontrollers.viewcontroller.ScrollEventListener;
9
- import com.reactnativenavigation.options.Options;
10
- import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
11
- import com.reactnativenavigation.utils.SystemUiUtils;
12
- import com.reactnativenavigation.viewcontrollers.viewcontroller.ReactViewCreator;
13
- import com.reactnativenavigation.viewcontrollers.child.ChildController;
14
- import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry;
15
- import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
16
- import com.reactnativenavigation.views.component.ComponentLayout;
17
-
18
10
  import androidx.annotation.NonNull;
11
+ import androidx.annotation.Nullable;
19
12
  import androidx.core.graphics.Insets;
20
13
  import androidx.core.view.ViewCompat;
21
14
  import androidx.core.view.WindowInsetsCompat;
22
15
 
23
- import static com.reactnativenavigation.utils.ObjectUtils.perform;
16
+ import com.reactnativenavigation.options.Options;
17
+ import com.reactnativenavigation.utils.SystemUiUtils;
18
+ import com.reactnativenavigation.viewcontrollers.child.ChildController;
19
+ import com.reactnativenavigation.viewcontrollers.child.ChildControllersRegistry;
20
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
21
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.ReactViewCreator;
22
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.ScrollEventListener;
23
+ import com.reactnativenavigation.views.component.ComponentLayout;
24
24
 
25
25
  public class ComponentViewController extends ChildController<ComponentLayout> {
26
26
  private final String componentName;
@@ -64,6 +64,18 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
64
64
  presenter.setDefaultOptions(defaultOptions);
65
65
  }
66
66
 
67
+ @Nullable
68
+ @Override
69
+ public Animator getPushAnimations(Options appearingOptions) {
70
+ return this.presenter.getStatusBarPushAnimation(appearingOptions);
71
+ }
72
+
73
+ @Nullable
74
+ @Override
75
+ public Animator getPopAnimations(Options appearingOptions, Options disappearingOptions) {
76
+ return this.presenter.getStatusBarPopAnimation(appearingOptions, disappearingOptions);
77
+ }
78
+
67
79
  @Override
68
80
  public ScrollEventListener getScrollEventListener() {
69
81
  return perform(view, null, ComponentLayout::getScrollEventListener);
@@ -1,10 +1,23 @@
1
1
  package com.reactnativenavigation.viewcontrollers.stack;
2
2
 
3
+ import static com.reactnativenavigation.react.Constants.HARDWARE_BACK_BUTTON_ID;
4
+ import static com.reactnativenavigation.utils.CollectionUtils.requireLast;
5
+ import static com.reactnativenavigation.utils.CoordinatorLayoutUtils.matchParentWithBehaviour;
6
+ import static com.reactnativenavigation.utils.CoordinatorLayoutUtils.updateBottomMargin;
7
+ import static com.reactnativenavigation.utils.ObjectUtils.perform;
8
+
3
9
  import android.app.Activity;
4
10
  import android.content.res.Configuration;
5
11
  import android.view.View;
6
12
  import android.view.ViewGroup;
7
13
 
14
+ import androidx.annotation.NonNull;
15
+ import androidx.annotation.RestrictTo;
16
+ import androidx.annotation.Size;
17
+ import androidx.annotation.VisibleForTesting;
18
+ import androidx.coordinatorlayout.widget.CoordinatorLayout;
19
+ import androidx.viewpager.widget.ViewPager;
20
+
8
21
  import com.facebook.react.ReactRootView;
9
22
  import com.reactnativenavigation.options.ButtonOptions;
10
23
  import com.reactnativenavigation.options.Options;
@@ -18,7 +31,9 @@ import com.reactnativenavigation.viewcontrollers.parent.ParentController;
18
31
  import com.reactnativenavigation.viewcontrollers.stack.topbar.TopBarController;
19
32
  import com.reactnativenavigation.viewcontrollers.stack.topbar.button.BackButtonHelper;
20
33
  import com.reactnativenavigation.viewcontrollers.viewcontroller.Presenter;
34
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.TopBarVisibilityInfo;
21
35
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
36
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewControllerVisibilityInfo;
22
37
  import com.reactnativenavigation.views.component.Component;
23
38
  import com.reactnativenavigation.views.stack.StackBehaviour;
24
39
  import com.reactnativenavigation.views.stack.StackLayout;
@@ -31,19 +46,6 @@ import java.util.Collection;
31
46
  import java.util.Iterator;
32
47
  import java.util.List;
33
48
 
34
- import androidx.annotation.NonNull;
35
- import androidx.annotation.RestrictTo;
36
- import androidx.annotation.Size;
37
- import androidx.annotation.VisibleForTesting;
38
- import androidx.coordinatorlayout.widget.CoordinatorLayout;
39
- import androidx.viewpager.widget.ViewPager;
40
-
41
- import static com.reactnativenavigation.react.Constants.HARDWARE_BACK_BUTTON_ID;
42
- import static com.reactnativenavigation.utils.CollectionUtils.*;
43
- import static com.reactnativenavigation.utils.CoordinatorLayoutUtils.matchParentWithBehaviour;
44
- import static com.reactnativenavigation.utils.CoordinatorLayoutUtils.updateBottomMargin;
45
- import static com.reactnativenavigation.utils.ObjectUtils.perform;
46
-
47
49
  public class StackController extends ParentController<StackLayout> {
48
50
 
49
51
  private IdStack<ViewController<?>> stack = new IdStack<>();
@@ -95,6 +97,19 @@ public class StackController extends ParentController<StackLayout> {
95
97
  return stack.peek();
96
98
  }
97
99
 
100
+ @Override
101
+ public void onSelected(ViewController<?> previousVC) {
102
+ presenter.bindNewViewController(previousVC, this);
103
+ super.onSelected(previousVC);
104
+ }
105
+
106
+ @NonNull
107
+ @Override
108
+ public ViewControllerVisibilityInfo getVisibilityInfo() {
109
+ TopBarVisibilityInfo topBarInfo = topBarController.getVisibilityInfo();
110
+ return new ViewControllerVisibilityInfo(topBarInfo);
111
+ }
112
+
98
113
  @Override
99
114
  public void onAttachToParent() {
100
115
  if (!isEmpty() && !getCurrentChild().isDestroyed() && !isViewShown()) {
@@ -159,16 +174,19 @@ public class StackController extends ParentController<StackLayout> {
159
174
  listener.onError("A stack can't contain two children with the same id: " + child.getId());
160
175
  return;
161
176
  }
162
- final ViewController<?> toRemove = stack.peek();
163
- if (size() > 0) backButtonHelper.addToPushedChild(child);
164
- child.setParentController(this);
165
- stack.push(child.getId(), child);
166
- if (!isViewCreated()) return;
177
+
178
+ final ViewController<?> toRemove = pushChildToStack(child);
179
+
180
+ if (!isViewCreated()) {
181
+ return;
182
+ }
183
+
167
184
  Options resolvedOptions = resolveCurrentOptions(presenter.getDefaultOptions());
168
- addChildToStack(child, resolvedOptions);
185
+ updateChildLayout(child, resolvedOptions);
186
+
169
187
  if (toRemove != null) {
170
- StackAnimationOptions animation = resolvedOptions.animations.push;
171
- if (animation.enabled.isTrueOrUndefined()) {
188
+ StackAnimationOptions animOptions = resolvedOptions.animations.push;
189
+ if (animOptions.enabled.isTrueOrUndefined()) {
172
190
  animator.push(
173
191
  child,
174
192
  toRemove,
@@ -195,7 +213,17 @@ public class StackController extends ParentController<StackLayout> {
195
213
  listener.onSuccess(toAdd.getId());
196
214
  }
197
215
 
198
- private void addChildToStack(ViewController<?> child, Options resolvedOptions) {
216
+ private ViewController<?> pushChildToStack(ViewController<?> child) {
217
+ final ViewController<?> toRemove = stack.peek();
218
+
219
+ if (size() > 0) backButtonHelper.addToPushedChild(child);
220
+
221
+ child.setParentController(this);
222
+ stack.push(child.getId(), child);
223
+ return toRemove;
224
+ }
225
+
226
+ private void updateChildLayout(ViewController<?> child, Options resolvedOptions) {
199
227
  child.setWaitForRender(resolvedOptions.animations.push.waitForRender);
200
228
  if (size() == 1) presenter.applyInitialChildLayoutOptions(resolvedOptions);
201
229
  getView().addView(child.getView(), getView().getChildCount() - 1, matchParentWithBehaviour(new StackBehaviour(this)));
@@ -222,7 +250,7 @@ public class StackController extends ParentController<StackLayout> {
222
250
  child.setParentController(this);
223
251
  stack.push(child.getId(), child);
224
252
  Options resolvedOptions = resolveCurrentOptions(presenter.getDefaultOptions());
225
- addChildToStack(child, resolvedOptions);
253
+ updateChildLayout(child, resolvedOptions);
226
254
 
227
255
  CommandListener listenerAdapter = new CommandListenerAdapter() {
228
256
  @Override
@@ -316,7 +344,7 @@ public class StackController extends ParentController<StackLayout> {
316
344
  appearing,
317
345
  disappearing,
318
346
  disappearingOptions,
319
- presenter.getAdditionalPopAnimations(appearingOptions, disappearingOptions),
347
+ presenter.getAdditionalPopAnimations(appearingOptions, disappearingOptions, appearing),
320
348
  () -> finishPopping(appearing, disappearing, listener)
321
349
  );
322
350
  } else {
@@ -37,6 +37,7 @@ import com.reactnativenavigation.viewcontrollers.stack.topbar.button.ButtonContr
37
37
  import com.reactnativenavigation.viewcontrollers.stack.topbar.button.ButtonPresenter;
38
38
  import com.reactnativenavigation.viewcontrollers.stack.topbar.button.IconResolver;
39
39
  import com.reactnativenavigation.viewcontrollers.stack.topbar.title.TitleBarReactViewController;
40
+ import com.reactnativenavigation.viewcontrollers.statusbar.StatusBarPresenter;
40
41
  import com.reactnativenavigation.viewcontrollers.viewcontroller.IReactView;
41
42
  import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController;
42
43
  import com.reactnativenavigation.views.stack.topbar.TopBar;
@@ -191,6 +192,12 @@ public class StackPresenter {
191
192
  componentLeftButtons.remove(child.getView());
192
193
  }
193
194
 
195
+ public void bindNewViewController(ViewController<?> previousVC, ViewController<?> newVC) {
196
+ Options options = newVC.resolveCurrentOptions(defaultOptions);
197
+ topBarController.bindNewViewController(previousVC, newVC);
198
+ StatusBarPresenter.instance.bindViewController(options.statusBar);
199
+ }
200
+
194
201
  private void destroyButtons(@Nullable Map<String, ButtonController> buttons) {
195
202
  if (buttons != null)
196
203
  forEach(buttons.values(), ViewController::destroy);
@@ -233,7 +240,7 @@ public class StackPresenter {
233
240
 
234
241
  topBar.setBorderHeight(topBarOptions.borderHeight.get(0d));
235
242
  topBar.setBorderColor(topBarOptions.borderColor.get(DEFAULT_BORDER_COLOR));
236
- topBar.setBackgroundColor(topBarOptions.background.color.get(Color.WHITE));
243
+ topBarController.setBackgroundColor(topBarOptions, Color.WHITE);
237
244
 
238
245
  if (topBarOptions.background.component.hasValue()) {
239
246
  View createdComponent = findBackgroundComponent(topBarOptions.background.component);
@@ -417,18 +424,23 @@ public class StackPresenter {
417
424
  }
418
425
  }
419
426
 
420
- public List<Animator> getAdditionalPushAnimations(StackController stack, ViewController<?> appearing,
427
+ public List<Animator> getAdditionalPushAnimations(
428
+ StackController stack,
429
+ ViewController<?> appearingCtrl,
421
430
  Options appearingOptions) {
422
431
  return CollectionUtils.asList(
423
- topBarController.getPushAnimation(appearingOptions,
424
- getTopBarTranslationAnimationDelta(stack, appearing)),
425
- perform(bottomTabsController, null, btc -> btc.getPushAnimation(appearingOptions)));
432
+ topBarController.getPushAnimation(appearingOptions, getTopBarTranslationAnimationDelta(stack, appearingCtrl)),
433
+ perform(appearingCtrl, null, vc -> vc.getPushAnimations(appearingOptions)),
434
+ perform(bottomTabsController, null, btc -> btc.getPushAnimation(appearingOptions)
435
+ ));
426
436
  }
427
437
 
428
- public List<Animator> getAdditionalPopAnimations(Options appearingOptions, Options disappearingOptions) {
438
+ public List<Animator> getAdditionalPopAnimations(Options appearingOptions, Options disappearingOptions, ViewController<?> appearingCtrl) {
429
439
  return CollectionUtils.asList(
430
440
  topBarController.getPopAnimation(appearingOptions, disappearingOptions),
431
- perform(bottomTabsController, null, btc -> btc.getPopAnimation(appearingOptions, disappearingOptions)));
441
+ perform(appearingCtrl, null, vc -> vc.getPopAnimations(appearingOptions, disappearingOptions)),
442
+ perform(bottomTabsController, null, btc -> btc.getPopAnimation(appearingOptions, disappearingOptions)
443
+ ));
432
444
  }
433
445
 
434
446
  public List<Animator> getAdditionalSetRootAnimations(StackController stack, ViewController<?> appearing,
@@ -618,9 +630,7 @@ public class StackPresenter {
618
630
  if (resolveOptions.subtitle.font.hasValue()) {
619
631
  topBar.setSubtitleTypeface(typefaceLoader, resolveOptions.subtitle.font);
620
632
  }
621
-
622
- if (topBarOptions.background.color.hasValue())
623
- topBar.setBackgroundColor(topBarOptions.background.color.get());
633
+ topBarController.setBackgroundColor(topBarOptions);
624
634
 
625
635
  if (topBarOptions.background.component.hasValue()) {
626
636
  if (backgroundControllers.containsKey(component)) {
@@ -1,9 +1,11 @@
1
1
  package com.reactnativenavigation.viewcontrollers.stack.topbar
2
2
 
3
- import com.reactnativenavigation.views.animations.BaseViewAnimator
3
+ import com.reactnativenavigation.views.animations.BaseViewAppearanceAnimator
4
4
  import com.reactnativenavigation.views.stack.topbar.TopBar
5
5
 
6
- class TopBarAnimator @JvmOverloads constructor(view: TopBar? = null) : BaseViewAnimator<TopBar>(HideDirection.Up, view) {
6
+ class TopBarAppearanceAnimator @JvmOverloads constructor(view: TopBar? = null)
7
+ : BaseViewAppearanceAnimator<TopBar>(HideDirection.Up, view) {
8
+
7
9
  @Suppress("UNUSED_PARAMETER")
8
10
  fun hideOnScroll(translationStart: Float, translationEndDy: Float) {
9
11
  // NOOP for now - this entire mechanism needs to be reimplemented as it relies on bridge events which are obsolete in TurboModules config
@@ -7,7 +7,7 @@ import com.reactnativenavigation.views.stack.topbar.TopBar
7
7
 
8
8
  class TopBarCollapseBehavior(private val topBar: TopBar) : ScrollEventListener.OnScrollListener, ScrollEventListener.OnDragListener {
9
9
  private var scrollEventListener: ScrollEventListener? = null
10
- private val animator: TopBarAnimator = TopBarAnimator(topBar)
10
+ private val animator: TopBarAppearanceAnimator = TopBarAppearanceAnimator(topBar)
11
11
 
12
12
  fun enableCollapse(scrollEventListener: ScrollEventListener?) {
13
13
  this.scrollEventListener = scrollEventListener
@@ -1,28 +1,44 @@
1
1
  package com.reactnativenavigation.viewcontrollers.stack.topbar
2
2
 
3
3
  import android.animation.Animator
4
+ import android.animation.AnimatorSet
4
5
  import android.content.Context
6
+ import android.graphics.drawable.ColorDrawable
7
+ import android.os.Build
5
8
  import android.view.MenuItem
6
9
  import android.view.View
10
+ import androidx.core.animation.addListener
11
+ import androidx.core.animation.doOnEnd
7
12
  import androidx.viewpager.widget.ViewPager
13
+ import com.reactnativenavigation.RNNFeatureToggles
14
+ import com.reactnativenavigation.RNNToggles
8
15
  import com.reactnativenavigation.options.Alignment
9
16
  import com.reactnativenavigation.options.AnimationOptions
10
17
  import com.reactnativenavigation.options.Options
18
+ import com.reactnativenavigation.options.TopBarOptions
19
+ import com.reactnativenavigation.options.animations.ViewAnimationOptions
11
20
  import com.reactnativenavigation.utils.CollectionUtils.forEachIndexed
12
21
  import com.reactnativenavigation.utils.ViewUtils
13
22
  import com.reactnativenavigation.utils.resetViewProperties
14
23
  import com.reactnativenavigation.viewcontrollers.stack.topbar.button.ButtonController
15
24
  import com.reactnativenavigation.viewcontrollers.stack.topbar.title.TitleBarReactViewController
25
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.TopBarVisibilityInfo
26
+ import com.reactnativenavigation.viewcontrollers.viewcontroller.ViewController
27
+ import com.reactnativenavigation.views.animations.ColorAnimator
16
28
  import com.reactnativenavigation.views.stack.StackLayout
17
29
  import com.reactnativenavigation.views.stack.topbar.TopBar
18
30
  import com.reactnativenavigation.views.stack.topbar.titlebar.ButtonBar
19
31
 
20
32
 
21
- open class TopBarController(private val animator: TopBarAnimator = TopBarAnimator()) {
33
+ open class TopBarController(
34
+ private val appearAnimator: TopBarAppearanceAnimator = TopBarAppearanceAnimator(),
35
+ private val colorAnimator: ColorAnimator = ColorAnimator(),
36
+ ) {
22
37
  lateinit var view: TopBar
23
38
  private lateinit var leftButtonBar: ButtonBar
24
39
  private lateinit var rightButtonBar: ButtonBar
25
40
 
41
+ private var hasPendingColorAnim = false
26
42
 
27
43
  val height: Int
28
44
  get() = view.height
@@ -31,70 +47,142 @@ open class TopBarController(private val animator: TopBarAnimator = TopBarAnimato
31
47
  val leftButtonCount: Int
32
48
  get() = leftButtonBar.buttonCount
33
49
 
34
- fun getRightButton(index: Int): MenuItem = rightButtonBar.getButton(index)
50
+ val visibilityInfo: TopBarVisibilityInfo
51
+ get() = TopBarVisibilityInfo(view.isShown, getBackgroundColor())
35
52
 
36
53
  fun createView(context: Context, parent: StackLayout): TopBar {
37
54
  if (!::view.isInitialized) {
38
55
  view = createTopBar(context, parent)
39
56
  leftButtonBar = view.leftButtonBar
40
57
  rightButtonBar = view.rightButtonBar
41
- animator.bindView(view)
58
+ appearAnimator.bindView(view)
42
59
  }
43
60
  return view
44
61
  }
45
62
 
46
- protected open fun createTopBar(context: Context, stackLayout: StackLayout): TopBar {
47
- return TopBar(context)
48
- }
49
-
50
63
  fun initTopTabs(viewPager: ViewPager?) = view.initTopTabs(viewPager)
51
64
 
52
65
  fun clearTopTabs() = view.clearTopTabs()
53
66
 
67
+ fun setBackgroundColor(topBarOptions: TopBarOptions, defaultColor: Int) {
68
+ val color = topBarOptions.background.color
69
+
70
+ if (!hasPendingColorAnim) {
71
+ view.setBackgroundColor(color.get(defaultColor)!!)
72
+ }
73
+ }
74
+
75
+ fun setBackgroundColor(topBarOptions: TopBarOptions) {
76
+ val color = topBarOptions.background.color
77
+
78
+ if (color.hasValue() && !hasPendingColorAnim) {
79
+ view.setBackgroundColor(color.get())
80
+ }
81
+ }
82
+
83
+ fun getBackgroundColor(): Int? {
84
+ return if (view.background is ColorDrawable) {
85
+ (view.background as ColorDrawable).color
86
+ } else {
87
+ null
88
+ }
89
+ }
90
+
91
+ fun getRightButton(index: Int): MenuItem = rightButtonBar.getButton(index)
92
+
54
93
  fun getPushAnimation(appearingOptions: Options, additionalDy: Float = 0f): Animator? {
55
- if (appearingOptions.topBar.animate.isFalse) return null
56
- return animator.getPushAnimation(
57
- appearingOptions.animations.push.topBar,
58
- appearingOptions.topBar.visible,
59
- additionalDy
60
- )
94
+ val topBarOptions = appearingOptions.topBar
95
+ val topBarAnimOptions = appearingOptions.animations.push.topBar
96
+
97
+ hasPendingColorAnim = false
98
+
99
+ mutableListOf(
100
+ getAppearancePushAnimation(topBarOptions, topBarAnimOptions, additionalDy),
101
+ getBkgColorAnimation(topBarOptions)?.apply {
102
+ hasPendingColorAnim = true
103
+
104
+ addListener(onEnd = {
105
+ hasPendingColorAnim = false
106
+ })
107
+ },
108
+ ).filterNotNull().let {
109
+ return if (it.isNotEmpty()) {
110
+ AnimatorSet().apply { playTogether(it) }
111
+ } else {
112
+ null
113
+ }
114
+ }
61
115
  }
62
116
 
63
117
  fun getPopAnimation(appearingOptions: Options, disappearingOptions: Options): Animator? {
64
- if (appearingOptions.topBar.animate.isFalse) return null
65
- return animator.getPopAnimation(
66
- disappearingOptions.animations.pop.topBar,
67
- appearingOptions.topBar.visible
68
- )
118
+ val topBarOptions = appearingOptions.topBar
119
+ val topBarAnimOptions = disappearingOptions.animations.pop.topBar
120
+
121
+ hasPendingColorAnim = false
122
+
123
+ mutableListOf(
124
+ getAppearancePopAnimation(topBarOptions, topBarAnimOptions),
125
+ getBkgColorAnimation(topBarOptions)?.apply {
126
+ hasPendingColorAnim = true
127
+
128
+ addListener(onEnd = {
129
+ hasPendingColorAnim = false
130
+ })
131
+ },
132
+ ).filterNotNull().let {
133
+ return if (it.isNotEmpty()) {
134
+ AnimatorSet().apply { playTogether(it) }
135
+ } else {
136
+ null
137
+ }
138
+ }
69
139
  }
70
140
 
71
141
  fun getSetStackRootAnimation(appearingOptions: Options, additionalDy: Float = 0f): Animator? {
72
142
  if (appearingOptions.topBar.animate.isFalse) return null
73
- return animator.getSetStackRootAnimation(
143
+ return appearAnimator.getSetStackRootAnimation(
74
144
  appearingOptions.animations.setStackRoot.topBar,
75
145
  appearingOptions.topBar.visible,
76
146
  additionalDy
77
147
  )
78
148
  }
79
149
 
150
+ fun bindNewViewController(previousVC: ViewController<*>?, newVC: ViewController<*>?) {
151
+ if (!RNNFeatureToggles.isEnabled(RNNToggles.TOP_BAR_COLOR_ANIMATION__TABS)) {
152
+ return
153
+ }
154
+
155
+ previousVC?.visibilityInfo?.topBarVisibilityInfo?.solidColor?.let { fromColor ->
156
+ newVC?.visibilityInfo?.topBarVisibilityInfo?.solidColor?.let { toColor ->
157
+ colorAnimator.getAnimation(view, fromColor, toColor).apply {
158
+ doOnEnd {
159
+ hasPendingColorAnim = false
160
+ }
161
+ hasPendingColorAnim = true
162
+ start()
163
+ }
164
+ }
165
+ }
166
+ }
167
+
80
168
  fun show() {
81
- if (ViewUtils.isVisible(view) || animator.isAnimatingShow()) return
169
+ if (ViewUtils.isVisible(view) || appearAnimator.isAnimatingShow()) return
82
170
  view.resetViewProperties()
83
171
  view.visibility = View.VISIBLE
84
172
  }
85
173
 
86
174
  fun showAnimate(options: AnimationOptions, additionalDy: Float) {
87
- if (ViewUtils.isVisible(view) || animator.isAnimatingShow()) return
88
- animator.show(options, additionalDy)
175
+ if (ViewUtils.isVisible(view) || appearAnimator.isAnimatingShow()) return
176
+ appearAnimator.show(options, additionalDy)
89
177
  }
90
178
 
91
179
  fun hide() {
92
- if (!animator.isAnimatingHide()) view.visibility = View.GONE
180
+ if (!appearAnimator.isAnimatingHide()) view.visibility = View.GONE
93
181
  }
94
182
 
95
183
  fun hideAnimate(options: AnimationOptions, additionalDy: Float) {
96
- if (!ViewUtils.isVisible(view) || animator.isAnimatingHide()) return
97
- animator.hide(options, additionalDy)
184
+ if (!ViewUtils.isVisible(view) || appearAnimator.isAnimatingHide()) return
185
+ appearAnimator.hide(options, additionalDy)
98
186
  }
99
187
 
100
188
  fun setTitleComponent(component: TitleBarReactViewController) {
@@ -126,4 +214,44 @@ open class TopBarController(private val animator: TopBarAnimator = TopBarAnimato
126
214
  toRemove.forEach { view.removeLeftButton(it) }
127
215
  forEachIndexed(toAdd) { b: ButtonController, i: Int -> b.addToMenu(leftButtonBar, i * 10) }
128
216
  }
129
- }
217
+
218
+ protected open fun createTopBar(context: Context, stackLayout: StackLayout): TopBar {
219
+ return TopBar(context)
220
+ }
221
+
222
+ private fun getBkgColorAnimation(topBarOptions: TopBarOptions): Animator? {
223
+ val targetColor = topBarOptions.background.color
224
+
225
+ if (targetColor.hasValue()
226
+ && view.background is ColorDrawable
227
+ && RNNFeatureToggles.isEnabled(RNNToggles.TOP_BAR_COLOR_ANIMATION__PUSH)) {
228
+ return colorAnimator.getAnimation(
229
+ view,
230
+ (view.background as ColorDrawable).color,
231
+ targetColor.get()
232
+ )
233
+ }
234
+ return null
235
+ }
236
+
237
+ private fun getAppearancePushAnimation(topBarOptions: TopBarOptions, topBarAnimOptions: ViewAnimationOptions, additionalDy: Float) =
238
+ if (!topBarOptions.animate.isFalse) {
239
+ appearAnimator.getPushAnimation(
240
+ topBarAnimOptions,
241
+ topBarOptions.visible,
242
+ additionalDy,
243
+ )
244
+ } else {
245
+ null
246
+ }
247
+
248
+ private fun getAppearancePopAnimation(topBarOptions: TopBarOptions, topBarAnimOptions: ViewAnimationOptions) =
249
+ if (!topBarOptions.animate.isFalse) {
250
+ appearAnimator.getPopAnimation(
251
+ topBarAnimOptions,
252
+ topBarOptions.visible,
253
+ )
254
+ } else {
255
+ null
256
+ }
257
+ }