Browse Source

Hide back button in mergeOptions (#5826)

This commit fixes hiding the back button with `backButton.visible: false` in mergeOptions. It didn't work on Android.
Guy Carmeli 5 years ago
parent
commit
3f17dc4a82
No account linked to committer's email address

+ 5
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/BackButton.java View File

65
         visible = new Bool(true);
65
         visible = new Bool(true);
66
         hasValue = true;
66
         hasValue = true;
67
     }
67
     }
68
+
69
+    public void setHidden() {
70
+        visible = new Bool(false);
71
+        hasValue = true;
72
+    }
68
 }
73
 }

+ 2
- 1
lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java View File

20
 import com.reactnativenavigation.viewcontrollers.ViewController;
20
 import com.reactnativenavigation.viewcontrollers.ViewController;
21
 import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsAttacher;
21
 import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsAttacher;
22
 import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsController;
22
 import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsController;
23
+import com.reactnativenavigation.viewcontrollers.button.NavigationIconResolver;
23
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentCreator;
24
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentCreator;
24
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentViewController;
25
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentViewController;
25
 import com.reactnativenavigation.viewcontrollers.sidemenu.SideMenuController;
26
 import com.reactnativenavigation.viewcontrollers.sidemenu.SideMenuController;
186
                         new TitleBarReactViewCreator(reactInstanceManager),
187
                         new TitleBarReactViewCreator(reactInstanceManager),
187
                         new TopBarBackgroundViewCreator(reactInstanceManager),
188
                         new TopBarBackgroundViewCreator(reactInstanceManager),
188
                         new TitleBarButtonCreator(reactInstanceManager),
189
                         new TitleBarButtonCreator(reactInstanceManager),
189
-                        new ImageLoader(),
190
+                        new NavigationIconResolver(activity, new ImageLoader()),
190
                         new RenderChecker(),
191
                         new RenderChecker(),
191
                         defaultOptions
192
                         defaultOptions
192
                 ))
193
                 ))

+ 11
- 7
lib/android/app/src/main/java/com/reactnativenavigation/presentation/StackPresenter.java View File

21
 import com.reactnativenavigation.parse.params.Colour;
21
 import com.reactnativenavigation.parse.params.Colour;
22
 import com.reactnativenavigation.utils.ButtonPresenter;
22
 import com.reactnativenavigation.utils.ButtonPresenter;
23
 import com.reactnativenavigation.utils.CollectionUtils;
23
 import com.reactnativenavigation.utils.CollectionUtils;
24
-import com.reactnativenavigation.utils.ImageLoader;
25
 import com.reactnativenavigation.utils.ObjectUtils;
24
 import com.reactnativenavigation.utils.ObjectUtils;
26
 import com.reactnativenavigation.utils.StatusBarUtils;
25
 import com.reactnativenavigation.utils.StatusBarUtils;
27
 import com.reactnativenavigation.utils.UiUtils;
26
 import com.reactnativenavigation.utils.UiUtils;
65
     private TopBarController topBarController;
64
     private TopBarController topBarController;
66
     private final TitleBarReactViewCreator titleViewCreator;
65
     private final TitleBarReactViewCreator titleViewCreator;
67
     private TitleBarButtonController.OnClickListener onClickListener;
66
     private TitleBarButtonController.OnClickListener onClickListener;
68
-    private final ImageLoader imageLoader;
69
     private final RenderChecker renderChecker;
67
     private final RenderChecker renderChecker;
70
     private final TopBarBackgroundViewCreator topBarBackgroundViewCreator;
68
     private final TopBarBackgroundViewCreator topBarBackgroundViewCreator;
71
     private final ReactViewCreator buttonCreator;
69
     private final ReactViewCreator buttonCreator;
76
     private Map<View, TopBarBackgroundViewController> backgroundControllers = new HashMap();
74
     private Map<View, TopBarBackgroundViewController> backgroundControllers = new HashMap();
77
     private Map<View, Map<String, TitleBarButtonController>> componentRightButtons = new HashMap();
75
     private Map<View, Map<String, TitleBarButtonController>> componentRightButtons = new HashMap();
78
     private Map<View, Map<String, TitleBarButtonController>> componentLeftButtons = new HashMap();
76
     private Map<View, Map<String, TitleBarButtonController>> componentLeftButtons = new HashMap();
77
+    private NavigationIconResolver iconResolver;
79
 
78
 
80
     public StackPresenter(Activity activity,
79
     public StackPresenter(Activity activity,
81
                           TitleBarReactViewCreator titleViewCreator,
80
                           TitleBarReactViewCreator titleViewCreator,
82
                           TopBarBackgroundViewCreator topBarBackgroundViewCreator,
81
                           TopBarBackgroundViewCreator topBarBackgroundViewCreator,
83
                           ReactViewCreator buttonCreator,
82
                           ReactViewCreator buttonCreator,
84
-                          ImageLoader imageLoader,
83
+                          NavigationIconResolver iconResolver,
85
                           RenderChecker renderChecker,
84
                           RenderChecker renderChecker,
86
                           Options defaultOptions) {
85
                           Options defaultOptions) {
87
         this.activity = activity;
86
         this.activity = activity;
88
         this.titleViewCreator = titleViewCreator;
87
         this.titleViewCreator = titleViewCreator;
89
         this.topBarBackgroundViewCreator = topBarBackgroundViewCreator;
88
         this.topBarBackgroundViewCreator = topBarBackgroundViewCreator;
90
         this.buttonCreator = buttonCreator;
89
         this.buttonCreator = buttonCreator;
91
-        this.imageLoader = imageLoader;
90
+        this.iconResolver = iconResolver;
92
         this.renderChecker = renderChecker;
91
         this.renderChecker = renderChecker;
93
         this.defaultOptions = defaultOptions;
92
         this.defaultOptions = defaultOptions;
94
         defaultTitleFontSize = UiUtils.dpToSp(activity, 18);
93
         defaultTitleFontSize = UiUtils.dpToSp(activity, 18);
311
 
310
 
312
     private TitleBarButtonController createButtonController(Button button) {
311
     private TitleBarButtonController createButtonController(Button button) {
313
         TitleBarButtonController controller = new TitleBarButtonController(activity,
312
         TitleBarButtonController controller = new TitleBarButtonController(activity,
314
-                new NavigationIconResolver(activity, imageLoader),
315
-                imageLoader,
313
+                iconResolver,
316
                 new ButtonPresenter(topBar.getTitleBar(), button),
314
                 new ButtonPresenter(topBar.getTitleBar(), button),
317
                 button,
315
                 button,
318
                 buttonCreator,
316
                 buttonCreator,
379
             }
377
             }
380
         }
378
         }
381
         if (buttons.left != null) topBar.setLeftButtons(leftButtonControllers);
379
         if (buttons.left != null) topBar.setLeftButtons(leftButtonControllers);
382
-        if (buttons.back.hasValue()) topBar.setBackButton(createButtonController(buttons.back));
380
+        if (buttons.back.hasValue()) {
381
+            if (buttons.back.visible.isFalse()) {
382
+                topBar.clearLeftButtons();
383
+            } else {
384
+                topBar.setBackButton(createButtonController(buttons.back));
385
+            }
386
+        }
383
 
387
 
384
         if (options.rightButtonColor.hasValue()) topBar.setOverflowButtonColor(options.rightButtonColor.get());
388
         if (options.rightButtonColor.hasValue()) topBar.setOverflowButtonColor(options.rightButtonColor.get());
385
     }
389
     }

+ 9
- 0
lib/android/app/src/main/java/com/reactnativenavigation/utils/ImageLoader.java View File

1
 package com.reactnativenavigation.utils;
1
 package com.reactnativenavigation.utils;
2
 
2
 
3
+import android.app.Activity;
3
 import android.content.Context;
4
 import android.content.Context;
4
 import android.graphics.Bitmap;
5
 import android.graphics.Bitmap;
5
 import android.graphics.BitmapFactory;
6
 import android.graphics.BitmapFactory;
7
 import android.graphics.drawable.Drawable;
8
 import android.graphics.drawable.Drawable;
8
 import android.net.Uri;
9
 import android.net.Uri;
9
 import android.os.StrictMode;
10
 import android.os.StrictMode;
11
+import android.view.View;
10
 
12
 
11
 import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
13
 import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
12
 import com.reactnativenavigation.NavigationApplication;
14
 import com.reactnativenavigation.NavigationApplication;
15
+import com.reactnativenavigation.R;
13
 
16
 
14
 import java.io.FileNotFoundException;
17
 import java.io.FileNotFoundException;
15
 import java.io.IOException;
18
 import java.io.IOException;
20
 
23
 
21
 import androidx.annotation.NonNull;
24
 import androidx.annotation.NonNull;
22
 import androidx.annotation.Nullable;
25
 import androidx.annotation.Nullable;
26
+import androidx.core.content.ContextCompat;
23
 
27
 
24
 public class ImageLoader {
28
 public class ImageLoader {
25
 
29
 
33
 
37
 
34
     private static final String FILE_SCHEME = "file";
38
     private static final String FILE_SCHEME = "file";
35
 
39
 
40
+    public Drawable getBackButtonIcon(Activity context) {
41
+        boolean isRTL = context.getWindow().getDecorView().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
42
+        return ContextCompat.getDrawable(context, isRTL ? R.drawable.ic_arrow_back_black_rtl_24dp : R.drawable.ic_arrow_back_black_24dp);
43
+    }
44
+
36
     @Nullable
45
     @Nullable
37
     public Drawable loadIcon(Context context, @Nullable String uri) {
46
     public Drawable loadIcon(Context context, @Nullable String uri) {
38
         if (uri == null) return null;
47
         if (uri == null) return null;

+ 3
- 9
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/TitleBarButtonController.java View File

22
 import com.reactnativenavigation.viewcontrollers.button.NavigationIconResolver;
22
 import com.reactnativenavigation.viewcontrollers.button.NavigationIconResolver;
23
 import com.reactnativenavigation.views.titlebar.TitleBarReactButtonView;
23
 import com.reactnativenavigation.views.titlebar.TitleBarReactButtonView;
24
 
24
 
25
-import java.util.Collections;
26
 import java.util.List;
25
 import java.util.List;
27
 
26
 
28
 import androidx.annotation.NonNull;
27
 import androidx.annotation.NonNull;
36
     }
35
     }
37
 
36
 
38
     private final NavigationIconResolver navigationIconResolver;
37
     private final NavigationIconResolver navigationIconResolver;
39
-    private final ImageLoader imageLoader;
40
     private ButtonPresenter optionsPresenter;
38
     private ButtonPresenter optionsPresenter;
41
     private final Button button;
39
     private final Button button;
42
     private final ReactViewCreator viewCreator;
40
     private final ReactViewCreator viewCreator;
54
 
52
 
55
     public TitleBarButtonController(Activity activity,
53
     public TitleBarButtonController(Activity activity,
56
                                     NavigationIconResolver navigationIconResolver,
54
                                     NavigationIconResolver navigationIconResolver,
57
-                                    ImageLoader imageLoader,
58
                                     ButtonPresenter optionsPresenter,
55
                                     ButtonPresenter optionsPresenter,
59
                                     Button button,
56
                                     Button button,
60
                                     ReactViewCreator viewCreator,
57
                                     ReactViewCreator viewCreator,
61
                                     OnClickListener onClickListener) {
58
                                     OnClickListener onClickListener) {
62
         super(activity, button.id, new YellowBoxDelegate(), new Options());
59
         super(activity, button.id, new YellowBoxDelegate(), new Options());
63
         this.navigationIconResolver = navigationIconResolver;
60
         this.navigationIconResolver = navigationIconResolver;
64
-        this.imageLoader = imageLoader;
65
         this.optionsPresenter = optionsPresenter;
61
         this.optionsPresenter = optionsPresenter;
66
         this.button = button;
62
         this.button = button;
67
         this.viewCreator = viewCreator;
63
         this.viewCreator = viewCreator;
104
     }
100
     }
105
 
101
 
106
     public void applyNavigationIcon(Toolbar toolbar) {
102
     public void applyNavigationIcon(Toolbar toolbar) {
107
-        Integer direction = getActivity().getWindow().getDecorView().getLayoutDirection();
108
-        navigationIconResolver.resolve(button, direction, icon -> {
103
+        navigationIconResolver.resolve(button, icon -> {
109
             setIconColor(icon);
104
             setIconColor(icon);
110
             toolbar.setNavigationOnClickListener(view -> onPressListener.onPress(button.id));
105
             toolbar.setNavigationOnClickListener(view -> onPressListener.onPress(button.id));
111
             toolbar.setNavigationIcon(icon);
106
             toolbar.setNavigationIcon(icon);
134
             if (button.hasIcon()) {
129
             if (button.hasIcon()) {
135
                 loadIcon(new ImageLoadingListenerAdapter() {
130
                 loadIcon(new ImageLoadingListenerAdapter() {
136
                     @Override
131
                     @Override
137
-                    public void onComplete(@NonNull List<Drawable> icons) {
138
-                        Drawable icon = icons.get(0);
132
+                    public void onComplete(@NonNull Drawable icon) {
139
                         TitleBarButtonController.this.icon = icon;
133
                         TitleBarButtonController.this.icon = icon;
140
                         setIconColor(icon);
134
                         setIconColor(icon);
141
                         menuItem.setIcon(icon);
135
                         menuItem.setIcon(icon);
151
     }
145
     }
152
 
146
 
153
     private void loadIcon(ImageLoader.ImagesLoadingListener callback) {
147
     private void loadIcon(ImageLoader.ImagesLoadingListener callback) {
154
-        imageLoader.loadIcons(getActivity(), Collections.singletonList(button.icon.get()), callback);
148
+        navigationIconResolver.resolve(button, callback::onComplete);
155
     }
149
     }
156
 
150
 
157
     private void setIconColor(Drawable icon) {
151
     private void setIconColor(Drawable icon) {

+ 8
- 11
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/button/NavigationIconResolver.java View File

1
 package com.reactnativenavigation.viewcontrollers.button;
1
 package com.reactnativenavigation.viewcontrollers.button;
2
 
2
 
3
-import android.content.Context;
3
+import android.app.Activity;
4
 import android.graphics.drawable.Drawable;
4
 import android.graphics.drawable.Drawable;
5
-import androidx.annotation.NonNull;
6
-import androidx.core.content.ContextCompat;
7
 import android.util.Log;
5
 import android.util.Log;
8
-import android.view.View;
9
 
6
 
10
-import com.reactnativenavigation.R;
11
 import com.reactnativenavigation.parse.params.Button;
7
 import com.reactnativenavigation.parse.params.Button;
12
 import com.reactnativenavigation.react.Constants;
8
 import com.reactnativenavigation.react.Constants;
13
 import com.reactnativenavigation.utils.Functions.Func1;
9
 import com.reactnativenavigation.utils.Functions.Func1;
14
 import com.reactnativenavigation.utils.ImageLoader;
10
 import com.reactnativenavigation.utils.ImageLoader;
15
 import com.reactnativenavigation.utils.ImageLoadingListenerAdapter;
11
 import com.reactnativenavigation.utils.ImageLoadingListenerAdapter;
16
 
12
 
13
+import androidx.annotation.NonNull;
14
+
17
 public class NavigationIconResolver {
15
 public class NavigationIconResolver {
18
 
16
 
19
-    private Context context;
17
+    private Activity context;
20
     private ImageLoader imageLoader;
18
     private ImageLoader imageLoader;
21
 
19
 
22
-    public NavigationIconResolver(Context context, ImageLoader imageLoader) {
20
+    public NavigationIconResolver(Activity context, ImageLoader imageLoader) {
23
         this.context = context;
21
         this.context = context;
24
         this.imageLoader = imageLoader;
22
         this.imageLoader = imageLoader;
25
     }
23
     }
26
 
24
 
27
-    public void resolve(Button button, Integer direction, Func1<Drawable> onSuccess) {
28
-        if (button.icon.hasValue()) {
25
+    public void resolve(Button button, Func1<Drawable> onSuccess) {
26
+        if (button.hasIcon()) {
29
             imageLoader.loadIcon(context, button.icon.get(), new ImageLoadingListenerAdapter() {
27
             imageLoader.loadIcon(context, button.icon.get(), new ImageLoadingListenerAdapter() {
30
                 @Override
28
                 @Override
31
                 public void onComplete(@NonNull Drawable icon) {
29
                 public void onComplete(@NonNull Drawable icon) {
38
                 }
36
                 }
39
             });
37
             });
40
         } else if (Constants.BACK_BUTTON_ID.equals(button.id)) {
38
         } else if (Constants.BACK_BUTTON_ID.equals(button.id)) {
41
-            Boolean isRTL = direction == View.LAYOUT_DIRECTION_RTL;
42
-            onSuccess.run(ContextCompat.getDrawable(context, isRTL ? R.drawable.ic_arrow_back_black_rtl_24dp : R.drawable.ic_arrow_back_black_24dp));
39
+            onSuccess.run(imageLoader.getBackButtonIcon(context));
43
         } else {
40
         } else {
44
             Log.w("RNN", "Left button needs to have an icon");
41
             Log.w("RNN", "Left button needs to have an icon");
45
         }
42
         }

+ 2
- 1
lib/android/app/src/test/java/com/reactnativenavigation/TestUtils.java View File

17
 import com.reactnativenavigation.utils.UiUtils;
17
 import com.reactnativenavigation.utils.UiUtils;
18
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
18
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
19
 import com.reactnativenavigation.viewcontrollers.ViewController;
19
 import com.reactnativenavigation.viewcontrollers.ViewController;
20
+import com.reactnativenavigation.viewcontrollers.button.NavigationIconResolver;
20
 import com.reactnativenavigation.viewcontrollers.stack.StackControllerBuilder;
21
 import com.reactnativenavigation.viewcontrollers.stack.StackControllerBuilder;
21
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
22
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
22
 import com.reactnativenavigation.views.StackLayout;
23
 import com.reactnativenavigation.views.StackLayout;
38
                 .setId("stack")
39
                 .setId("stack")
39
                 .setChildRegistry(new ChildControllersRegistry())
40
                 .setChildRegistry(new ChildControllersRegistry())
40
                 .setTopBarController(topBarController)
41
                 .setTopBarController(topBarController)
41
-                .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), new TopBarButtonCreatorMock(), new ImageLoader(), new RenderChecker(), new Options()))
42
+                .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), new TopBarButtonCreatorMock(), new NavigationIconResolver(activity, new ImageLoader()), new RenderChecker(), new Options()))
42
                 .setInitialOptions(new Options());
43
                 .setInitialOptions(new Options());
43
     }
44
     }
44
 
45
 

+ 30
- 0
lib/android/app/src/test/java/com/reactnativenavigation/mocks/BackDrawable.java View File

1
+package com.reactnativenavigation.mocks;
2
+
3
+import android.graphics.Canvas;
4
+import android.graphics.ColorFilter;
5
+import android.graphics.drawable.Drawable;
6
+
7
+import androidx.annotation.NonNull;
8
+import androidx.annotation.Nullable;
9
+
10
+public class BackDrawable extends Drawable {
11
+    @Override
12
+    public void draw(@NonNull Canvas canvas) {
13
+
14
+    }
15
+
16
+    @Override
17
+    public void setAlpha(int alpha) {
18
+
19
+    }
20
+
21
+    @Override
22
+    public void setColorFilter(@Nullable ColorFilter colorFilter) {
23
+
24
+    }
25
+
26
+    @Override
27
+    public int getOpacity() {
28
+        return 0;
29
+    }
30
+}

+ 7
- 5
lib/android/app/src/test/java/com/reactnativenavigation/mocks/ImageLoaderMock.java View File

3
 import android.graphics.Canvas;
3
 import android.graphics.Canvas;
4
 import android.graphics.ColorFilter;
4
 import android.graphics.ColorFilter;
5
 import android.graphics.drawable.Drawable;
5
 import android.graphics.drawable.Drawable;
6
-import androidx.annotation.NonNull;
7
 
6
 
8
 import com.reactnativenavigation.utils.ImageLoader;
7
 import com.reactnativenavigation.utils.ImageLoader;
9
 
8
 
13
 import java.util.Collections;
12
 import java.util.Collections;
14
 import java.util.List;
13
 import java.util.List;
15
 
14
 
15
+import androidx.annotation.NonNull;
16
+
16
 import static org.mockito.ArgumentMatchers.any;
17
 import static org.mockito.ArgumentMatchers.any;
17
 import static org.mockito.Mockito.doAnswer;
18
 import static org.mockito.Mockito.doAnswer;
18
 
19
 
39
         }
40
         }
40
     };
41
     };
41
 
42
 
43
+    private static Drawable backIcon = new BackDrawable();
44
+
42
     public static ImageLoader mock() {
45
     public static ImageLoader mock() {
43
         ImageLoader imageLoader = Mockito.mock(ImageLoader.class);
46
         ImageLoader imageLoader = Mockito.mock(ImageLoader.class);
44
-        doAnswer(
45
-                invocation -> {
47
+        doAnswer(invocation -> {
46
                     int urlCount = ((Collection) invocation.getArguments()[1]).size();
48
                     int urlCount = ((Collection) invocation.getArguments()[1]).size();
47
                     List<Drawable> drawables = Collections.nCopies(urlCount, mockDrawable);
49
                     List<Drawable> drawables = Collections.nCopies(urlCount, mockDrawable);
48
                     ((ImageLoader.ImagesLoadingListener) invocation.getArguments()[2]).onComplete(drawables);
50
                     ((ImageLoader.ImagesLoadingListener) invocation.getArguments()[2]).onComplete(drawables);
49
                     return null;
51
                     return null;
50
                 }
52
                 }
51
         ).when(imageLoader).loadIcons(any(), any(), any());
53
         ).when(imageLoader).loadIcons(any(), any(), any());
52
-        doAnswer(
53
-                invocation -> {
54
+        doAnswer(invocation -> {
54
                     ((ImageLoader.ImagesLoadingListener) invocation.getArguments()[2]).onComplete(mockDrawable);
55
                     ((ImageLoader.ImagesLoadingListener) invocation.getArguments()[2]).onComplete(mockDrawable);
55
                     return null;
56
                     return null;
56
                 }
57
                 }
57
         ).when(imageLoader).loadIcon(any(), any(), any());
58
         ).when(imageLoader).loadIcon(any(), any(), any());
59
+        doAnswer(invocation -> backIcon).when(imageLoader).getBackButtonIcon(any());
58
         return imageLoader;
60
         return imageLoader;
59
     }
61
     }
60
 }
62
 }

+ 3
- 3
lib/android/app/src/test/java/com/reactnativenavigation/utils/TitleBarHelper.java View File

1
 package com.reactnativenavigation.utils;
1
 package com.reactnativenavigation.utils;
2
 
2
 
3
 import android.app.Activity;
3
 import android.app.Activity;
4
-import androidx.appcompat.view.menu.ActionMenuItemView;
5
-import androidx.appcompat.widget.Toolbar;
6
 
4
 
7
 import com.reactnativenavigation.mocks.ImageLoaderMock;
5
 import com.reactnativenavigation.mocks.ImageLoaderMock;
8
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
6
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
13
 import com.reactnativenavigation.viewcontrollers.button.NavigationIconResolver;
11
 import com.reactnativenavigation.viewcontrollers.button.NavigationIconResolver;
14
 import com.reactnativenavigation.views.titlebar.TitleBar;
12
 import com.reactnativenavigation.views.titlebar.TitleBar;
15
 
13
 
14
+import androidx.appcompat.view.menu.ActionMenuItemView;
15
+import androidx.appcompat.widget.Toolbar;
16
+
16
 public class TitleBarHelper {
17
 public class TitleBarHelper {
17
     public static ActionMenuItemView getRightButton(Toolbar toolbar, int index) {
18
     public static ActionMenuItemView getRightButton(Toolbar toolbar, int index) {
18
         return (ActionMenuItemView) ViewUtils.findChildrenByClassRecursive(toolbar, ActionMenuItemView.class).get(toolbar.getMenu().size() - index - 1);
19
         return (ActionMenuItemView) ViewUtils.findChildrenByClassRecursive(toolbar, ActionMenuItemView.class).get(toolbar.getMenu().size() - index - 1);
45
     public static TitleBarButtonController createButtonController(Activity activity, TitleBar titleBar, Button button) {
46
     public static TitleBarButtonController createButtonController(Activity activity, TitleBar titleBar, Button button) {
46
         return new TitleBarButtonController(activity,
47
         return new TitleBarButtonController(activity,
47
                 new NavigationIconResolver(activity, ImageLoaderMock.mock()),
48
                 new NavigationIconResolver(activity, ImageLoaderMock.mock()),
48
-                ImageLoaderMock.mock(),
49
                 new ButtonPresenter(titleBar, button),
49
                 new ButtonPresenter(titleBar, button),
50
                 button,
50
                 button,
51
                 new TopBarButtonCreatorMock(),
51
                 new TopBarButtonCreatorMock(),

+ 51
- 28
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/StackPresenterTest.java View File

5
 import android.graphics.Typeface;
5
 import android.graphics.Typeface;
6
 import android.view.Gravity;
6
 import android.view.Gravity;
7
 import android.view.View;
7
 import android.view.View;
8
-import android.view.ViewGroup;
9
 
8
 
10
 import com.reactnativenavigation.BaseTest;
9
 import com.reactnativenavigation.BaseTest;
11
 import com.reactnativenavigation.TestUtils;
10
 import com.reactnativenavigation.TestUtils;
11
+import com.reactnativenavigation.mocks.BackDrawable;
12
 import com.reactnativenavigation.mocks.ImageLoaderMock;
12
 import com.reactnativenavigation.mocks.ImageLoaderMock;
13
 import com.reactnativenavigation.mocks.Mocks;
13
 import com.reactnativenavigation.mocks.Mocks;
14
 import com.reactnativenavigation.mocks.SimpleViewController;
14
 import com.reactnativenavigation.mocks.SimpleViewController;
29
 import com.reactnativenavigation.parse.params.Text;
29
 import com.reactnativenavigation.parse.params.Text;
30
 import com.reactnativenavigation.presentation.RenderChecker;
30
 import com.reactnativenavigation.presentation.RenderChecker;
31
 import com.reactnativenavigation.presentation.StackPresenter;
31
 import com.reactnativenavigation.presentation.StackPresenter;
32
+import com.reactnativenavigation.utils.CommandListenerAdapter;
32
 import com.reactnativenavigation.utils.TitleBarHelper;
33
 import com.reactnativenavigation.utils.TitleBarHelper;
34
+import com.reactnativenavigation.utils.UiUtils;
35
+import com.reactnativenavigation.viewcontrollers.button.NavigationIconResolver;
33
 import com.reactnativenavigation.viewcontrollers.stack.StackController;
36
 import com.reactnativenavigation.viewcontrollers.stack.StackController;
34
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
37
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
35
 import com.reactnativenavigation.views.StackLayout;
38
 import com.reactnativenavigation.views.StackLayout;
39
 import org.json.JSONObject;
42
 import org.json.JSONObject;
40
 import org.junit.Test;
43
 import org.junit.Test;
41
 import org.mockito.ArgumentCaptor;
44
 import org.mockito.ArgumentCaptor;
45
+import org.robolectric.annotation.LooperMode;
46
+import org.robolectric.shadows.ShadowLooper;
42
 
47
 
43
 import java.util.ArrayList;
48
 import java.util.ArrayList;
44
 import java.util.Collection;
49
 import java.util.Collection;
47
 
52
 
48
 import androidx.appcompat.widget.ActionMenuView;
53
 import androidx.appcompat.widget.ActionMenuView;
49
 import androidx.appcompat.widget.Toolbar;
54
 import androidx.appcompat.widget.Toolbar;
55
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
50
 
56
 
51
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
57
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
52
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
58
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
62
 import static org.mockito.Mockito.verify;
68
 import static org.mockito.Mockito.verify;
63
 import static org.mockito.Mockito.when;
69
 import static org.mockito.Mockito.when;
64
 
70
 
71
+@LooperMode(LooperMode.Mode.PAUSED)
65
 public class StackPresenterTest extends BaseTest {
72
 public class StackPresenterTest extends BaseTest {
66
 
73
 
67
     private static final Options EMPTY_OPTIONS = new Options();
74
     private static final Options EMPTY_OPTIONS = new Options();
78
     private Button componentBtn1 = TitleBarHelper.reactViewButton("btn1_");
85
     private Button componentBtn1 = TitleBarHelper.reactViewButton("btn1_");
79
     private Button componentBtn2 = TitleBarHelper.reactViewButton("btn2_");
86
     private Button componentBtn2 = TitleBarHelper.reactViewButton("btn2_");
80
     private TopBarController topBarController;
87
     private TopBarController topBarController;
88
+    private ChildControllersRegistry childRegistry;
89
+    private NavigationIconResolver iconResolver;
81
 
90
 
82
     @Override
91
     @Override
83
     public void beforeEach() {
92
     public void beforeEach() {
89
             }
98
             }
90
         };
99
         };
91
         renderChecker = spy(new RenderChecker());
100
         renderChecker = spy(new RenderChecker());
92
-        uut = spy(new StackPresenter(activity, titleViewCreator, new TopBarBackgroundViewCreatorMock(), new TopBarButtonCreatorMock(), ImageLoaderMock.mock(), renderChecker, new Options()));
93
-        topBar = mockTopBar();
94
-        topBarController = spy(new TopBarController() {
95
-            @Override
96
-            protected TopBar createTopBar(Context context, StackLayout stackLayout) {
97
-                return topBar;
98
-            }
99
-        });
101
+        iconResolver = new NavigationIconResolver(activity, ImageLoaderMock.mock());
102
+        uut = spy(new StackPresenter(activity, titleViewCreator, new TopBarBackgroundViewCreatorMock(), new TopBarButtonCreatorMock(), iconResolver, renderChecker, new Options()));
103
+        createTopBarController();
100
 
104
 
101
         parent = TestUtils.newStackController(activity)
105
         parent = TestUtils.newStackController(activity)
102
                 .setTopBarController(topBarController)
106
                 .setTopBarController(topBarController)
103
                 .setStackPresenter(uut)
107
                 .setStackPresenter(uut)
104
                 .build();
108
                 .build();
105
-        parent.ensureViewIsCreated();
106
 
109
 
107
-        ChildControllersRegistry childRegistry = new ChildControllersRegistry();
110
+        childRegistry = new ChildControllersRegistry();
108
         child = spy(new SimpleViewController(activity, childRegistry, "child1", Options.EMPTY));
111
         child = spy(new SimpleViewController(activity, childRegistry, "child1", Options.EMPTY));
109
         otherChild = spy(new SimpleViewController(activity, childRegistry, "child1", Options.EMPTY));
112
         otherChild = spy(new SimpleViewController(activity, childRegistry, "child1", Options.EMPTY));
113
+        activity.setContentView(parent.getView());
110
     }
114
     }
111
 
115
 
112
     @Test
116
     @Test
114
         Options o1 = new Options();
118
         Options o1 = new Options();
115
         o1.topBar.title.component = component(Alignment.Default);
119
         o1.topBar.title.component = component(Alignment.Default);
116
         o1.topBar.background.component = component(Alignment.Default);
120
         o1.topBar.background.component = component(Alignment.Default);
117
-        o1.topBar.buttons.right = new ArrayList(Collections.singletonList(componentBtn1));
121
+        o1.topBar.buttons.right = new ArrayList<>(Collections.singletonList(componentBtn1));
118
         uut.applyChildOptions(o1, parent, child);
122
         uut.applyChildOptions(o1, parent, child);
119
 
123
 
120
         uut.isRendered(child.getView());
124
         uut.isRendered(child.getView());
121
         ArgumentCaptor<Collection<ViewController>> controllers = ArgumentCaptor.forClass(Collection.class);
125
         ArgumentCaptor<Collection<ViewController>> controllers = ArgumentCaptor.forClass(Collection.class);
122
         verify(renderChecker).areRendered(controllers.capture());
126
         verify(renderChecker).areRendered(controllers.capture());
123
-        ArrayList<ViewController> items = new ArrayList(controllers.getValue());
127
+        ArrayList<ViewController> items = new ArrayList<>(controllers.getValue());
124
         assertThat(items.contains(uut.getComponentButtons(child.getView()).get(0))).isTrue();
128
         assertThat(items.contains(uut.getComponentButtons(child.getView()).get(0))).isTrue();
125
         assertThat(items.contains(uut.getTitleComponents().get(child.getView()))).isTrue();
129
         assertThat(items.contains(uut.getTitleComponents().get(child.getView()))).isTrue();
126
         assertThat(items.contains(uut.getBackgroundComponents().get(child.getView()))).isTrue();
130
         assertThat(items.contains(uut.getBackgroundComponents().get(child.getView()))).isTrue();
250
         assertThat(initialButtons.get(1).isDestroyed()).isTrue();
254
         assertThat(initialButtons.get(1).isDestroyed()).isTrue();
251
     }
255
     }
252
 
256
 
257
+    @Test
258
+    public void mergeButtons_backButtonIsRemovedIfVisibleFalse() {
259
+        ViewController pushedChild = spy(new SimpleViewController(activity, childRegistry, "child2", new Options()));
260
+        disablePushAnimation(child, pushedChild);
261
+        parent.push(child, new CommandListenerAdapter());
262
+
263
+        assertThat(topBar.getTitleBar().getNavigationIcon()).isNull();
264
+
265
+        parent.push(pushedChild, new CommandListenerAdapter());
266
+        ShadowLooper.idleMainLooper();
267
+        verify(pushedChild).onViewAppeared();
268
+        assertThat(topBar.getTitleBar().getNavigationIcon()).isInstanceOf(BackDrawable.class);
269
+
270
+        Options backButtonHidden = new Options();
271
+        backButtonHidden.topBar.buttons.back.setHidden();
272
+        uut.mergeChildOptions(backButtonHidden, backButtonHidden, parent, child);
273
+
274
+        ShadowLooper.idleMainLooper();
275
+        assertThat(topBar.getTitleBar().getNavigationIcon()).isNull();
276
+    }
277
+
253
     @Test
278
     @Test
254
     public void mergeTopBarOptions() {
279
     public void mergeTopBarOptions() {
255
         Options options = new Options();
280
         Options options = new Options();
302
         verify(topBar, times(1)).setTopTabsVisible(anyBoolean());
327
         verify(topBar, times(1)).setTopTabsVisible(anyBoolean());
303
     }
328
     }
304
 
329
 
305
-    @Test
306
-    public void mergeTopTabOptions() {
307
-        Options options = new Options();
308
-        uut.mergeChildOptions(options, EMPTY_OPTIONS, parent, child);
309
-
310
-        verify(topBar, times(0)).setTopTabFontFamily(anyInt(), any());
311
-
312
-        options.topTabOptions.tabIndex = 1;
313
-        options.topTabOptions.fontFamily = Typeface.DEFAULT_BOLD;
314
-        uut.mergeChildOptions(options, EMPTY_OPTIONS, parent, child);
315
-
316
-        verify(topBar, times(1)).setTopTabFontFamily(1, Typeface.DEFAULT_BOLD);
317
-    }
318
-
319
     @Test
330
     @Test
320
     public void applyInitialChildLayoutOptions() {
331
     public void applyInitialChildLayoutOptions() {
321
         Options options = new Options();
332
         Options options = new Options();
571
         toolbar.addView(new ActionMenuView(activity));
582
         toolbar.addView(new ActionMenuView(activity));
572
         when(topBar.getTitleBar()).then(invocation -> toolbar);
583
         when(topBar.getTitleBar()).then(invocation -> toolbar);
573
         when(topBar.getContext()).then(invocation -> activity);
584
         when(topBar.getContext()).then(invocation -> activity);
574
-        when(topBar.getLayoutParams()).thenReturn(new ViewGroup.MarginLayoutParams(MATCH_PARENT, WRAP_CONTENT));
585
+        when(topBar.dispatchApplyWindowInsets(any())).then(invocation -> invocation.getArguments()[0]);
586
+        when(topBar.getLayoutParams()).thenReturn(new CoordinatorLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
575
         return topBar;
587
         return topBar;
576
     }
588
     }
577
 
589
 
590
+    private void createTopBarController() {
591
+        topBarController = spy(new TopBarController() {
592
+            @Override
593
+            protected TopBar createTopBar(Context context, StackLayout stackLayout) {
594
+                topBar = spy(super.createTopBar(context, stackLayout));
595
+                topBar.layout(0, 0, 1000, UiUtils.getTopBarHeight(activity));
596
+                return topBar;
597
+            }
598
+        });
599
+    }
600
+
578
     private Component component(Alignment alignment) {
601
     private Component component(Alignment alignment) {
579
         Component component = new Component();
602
         Component component = new Component();
580
         component.name = new Text("myComp");
603
         component.name = new Text("myComp");

+ 2
- 2
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopBarButtonControllerTest.java View File

51
         getTitleBar().layout(0, 0, 1080, 200);
51
         getTitleBar().layout(0, 0, 1080, 200);
52
 
52
 
53
         optionsPresenter = spy(new ButtonPresenter(getTitleBar(), button));
53
         optionsPresenter = spy(new ButtonPresenter(getTitleBar(), button));
54
-        uut = new TitleBarButtonController(activity, new NavigationIconResolver(activity, ImageLoaderMock.mock()), ImageLoaderMock.mock(), optionsPresenter, button, buttonCreatorMock, (buttonId) -> {});
54
+        uut = new TitleBarButtonController(activity, new NavigationIconResolver(activity, ImageLoaderMock.mock()), optionsPresenter, button, buttonCreatorMock, (buttonId) -> {});
55
 
55
 
56
         stackController.ensureViewIsCreated();
56
         stackController.ensureViewIsCreated();
57
     }
57
     }
87
         button.disabledColor = new Colour(Color.BLACK);
87
         button.disabledColor = new Colour(Color.BLACK);
88
         uut.addToMenu(getTitleBar(), 0);
88
         uut.addToMenu(getTitleBar(), 0);
89
 
89
 
90
-        verify(optionsPresenter, times(1)).tint(any(), eq(Color.BLACK));
90
+        verify(optionsPresenter).tint(any(), eq(Color.BLACK));
91
     }
91
     }
92
 
92
 
93
     @Test
93
     @Test

+ 6
- 8
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/button/NavigationIconResolverTest.java View File

1
 package com.reactnativenavigation.viewcontrollers.button;
1
 package com.reactnativenavigation.viewcontrollers.button;
2
 
2
 
3
-import android.content.Context;
3
+import android.app.Activity;
4
 import android.graphics.Color;
4
 import android.graphics.Color;
5
 import android.graphics.drawable.Drawable;
5
 import android.graphics.drawable.Drawable;
6
-import android.view.View;
7
 
6
 
8
 import com.reactnativenavigation.BaseTest;
7
 import com.reactnativenavigation.BaseTest;
8
+import com.reactnativenavigation.mocks.BackDrawable;
9
 import com.reactnativenavigation.mocks.ImageLoaderMock;
9
 import com.reactnativenavigation.mocks.ImageLoaderMock;
10
 import com.reactnativenavigation.parse.params.Button;
10
 import com.reactnativenavigation.parse.params.Button;
11
 import com.reactnativenavigation.parse.params.Colour;
11
 import com.reactnativenavigation.parse.params.Colour;
20
 import static org.mockito.ArgumentMatchers.eq;
20
 import static org.mockito.ArgumentMatchers.eq;
21
 import static org.mockito.Mockito.spy;
21
 import static org.mockito.Mockito.spy;
22
 import static org.mockito.Mockito.verify;
22
 import static org.mockito.Mockito.verify;
23
-import static org.mockito.Mockito.verifyZeroInteractions;
24
 
23
 
25
 public class NavigationIconResolverTest extends BaseTest {
24
 public class NavigationIconResolverTest extends BaseTest {
26
     private static final String ICON_URI = "someIconUri";
25
     private static final String ICON_URI = "someIconUri";
27
     private NavigationIconResolver uut;
26
     private NavigationIconResolver uut;
28
     private ImageLoader imageLoader;
27
     private ImageLoader imageLoader;
29
-    private Context context;
28
+    private Activity context;
30
 
29
 
31
     @Override
30
     @Override
32
     public void beforeEach() {
31
     public void beforeEach() {
43
 
42
 
44
             }
43
             }
45
         });
44
         });
46
-        uut.resolve(iconButton(), View.LAYOUT_DIRECTION_LTR, onSuccess);
45
+        uut.resolve(iconButton(), onSuccess);
47
         verify(imageLoader).loadIcon(eq(context), eq(ICON_URI), any());
46
         verify(imageLoader).loadIcon(eq(context), eq(ICON_URI), any());
48
         verify(onSuccess).run(any(Drawable.class));
47
         verify(onSuccess).run(any(Drawable.class));
49
     }
48
     }
56
 
55
 
57
             }
56
             }
58
         });
57
         });
59
-        uut.resolve(backButton(), View.LAYOUT_DIRECTION_LTR, onSuccess);
60
-        verifyZeroInteractions(imageLoader);
61
-        verify(onSuccess).run(any());
58
+        uut.resolve(backButton(), onSuccess);
59
+        verify(onSuccess).run(any(BackDrawable.class));
62
     }
60
     }
63
 
61
 
64
     private Button iconButton() {
62
     private Button iconButton() {

+ 2
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.java View File

32
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
32
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
33
 import com.reactnativenavigation.viewcontrollers.ParentController;
33
 import com.reactnativenavigation.viewcontrollers.ParentController;
34
 import com.reactnativenavigation.viewcontrollers.ViewController;
34
 import com.reactnativenavigation.viewcontrollers.ViewController;
35
+import com.reactnativenavigation.viewcontrollers.button.NavigationIconResolver;
35
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
36
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
36
 import com.reactnativenavigation.views.StackLayout;
37
 import com.reactnativenavigation.views.StackLayout;
37
 import com.reactnativenavigation.views.element.ElementTransitionManager;
38
 import com.reactnativenavigation.views.element.ElementTransitionManager;
95
         StatusBarUtils.saveStatusBarHeight(63);
96
         StatusBarUtils.saveStatusBarHeight(63);
96
         animator = spy(new NavigationAnimator(activity, Mockito.mock(ElementTransitionManager.class)));
97
         animator = spy(new NavigationAnimator(activity, Mockito.mock(ElementTransitionManager.class)));
97
         childRegistry = new ChildControllersRegistry();
98
         childRegistry = new ChildControllersRegistry();
98
-        presenter = spy(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), new TopBarButtonCreatorMock(), ImageLoaderMock.mock(), new RenderChecker(), new Options()));
99
+        presenter = spy(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), new TopBarButtonCreatorMock(), new NavigationIconResolver(activity, ImageLoaderMock.mock()), new RenderChecker(), new Options()));
99
         child1 = spy(new SimpleViewController(activity, childRegistry, "child1", new Options()));
100
         child1 = spy(new SimpleViewController(activity, childRegistry, "child1", new Options()));
100
         child1a = spy(new SimpleViewController(activity, childRegistry, "child1", new Options()));
101
         child1a = spy(new SimpleViewController(activity, childRegistry, "child1", new Options()));
101
         child2 = spy(new SimpleViewController(activity, childRegistry, "child2", new Options()));
102
         child2 = spy(new SimpleViewController(activity, childRegistry, "child2", new Options()));