Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add layout.insets option #7416

Merged
merged 33 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b1ac48b
Add layout.insets
yogevbd Dec 28, 2021
e12fb10
Merge branch 'master' into layoutInsets
yogevbd Dec 28, 2021
2c9c4c9
f
yogevbd Dec 29, 2021
8608acf
Merge branch 'layoutInsets' of github.com:wix/react-native-navigation…
yogevbd Dec 29, 2021
8858eca
android logic
swabbass Dec 29, 2021
8e8fd3c
create insets options
swabbass Dec 29, 2021
62ed51f
dp extentions
swabbass Dec 29, 2021
4a474a1
dereference parent
swabbass Dec 29, 2021
6621ca1
Overlays hidden when keyboard is open
swabbass Dec 29, 2021
6e8feaf
apply insets on presenter
swabbass Dec 29, 2021
0bd4386
Update Presenter.java
swabbass Dec 29, 2021
53c44ef
Update StackAnimator.kt
swabbass Dec 29, 2021
5520a7d
Update ViewController.java
swabbass Dec 29, 2021
b98a574
Update Navigator.java
swabbass Dec 29, 2021
ebcaf97
Add layout.adjustResize
yogevbd Dec 29, 2021
dcdbb8b
return unconsumed insets
swabbass Dec 29, 2021
fbedc46
add adjust resize toggle
swabbass Dec 29, 2021
4758046
mock top most parent
swabbass Dec 29, 2021
e771e9e
tmp for detox checking the test
swabbass Dec 30, 2021
ccd4f69
fix e2e
swabbass Jan 2, 2022
358fd8b
Update test-e2e.js
swabbass Jan 2, 2022
12253b4
Update Overlay.test.js
swabbass Jan 2, 2022
69f086b
Update OverlayScreen.tsx
swabbass Jan 2, 2022
c177383
Fix tests
yogevbd Jan 2, 2022
532bbca
f
yogevbd Jan 2, 2022
eec4fa7
Fix tests
yogevbd Jan 2, 2022
fe6501f
Another test fix
yogevbd Jan 2, 2022
c10ee6e
Update overlay_banner_padding.png
swabbass Jan 3, 2022
709a4ab
use 3rd party lib to compare images
swabbass Jan 3, 2022
0d98267
Update Overlay.test.js
swabbass Jan 3, 2022
4a36084
Merge branch 'master' into layoutInsets
yogevbd Jan 3, 2022
b8d7fee
Disable pointer location
yogevbd Jan 3, 2022
cd7be44
fix banner screenshot
yogevbd Jan 3, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions e2e/AndroidUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,28 @@ const utils = {
executeShellCommand: (command) => {
exec.execSync(`adb -s ${device.id} shell ${command}`);
},
setDemoMode: () => {
// enter demo mode
utils.executeShellCommand('settings put global sysui_demo_allowed 1');
// display time 12:00
utils.executeShellCommand(
'am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1200'
);
// Display full mobile data with 4g type and no wifi
utils.executeShellCommand(
'am broadcast -a com.android.systemui.demo -e command network -e mobile show -e level 4 -e datatype 4g -e wifi false'
);
// Hide notifications
utils.executeShellCommand(
'am broadcast -a com.android.systemui.demo -e command notifications -e visible false'
);
// Disable pointer location
utils.executeShellCommand('settings put system pointer_location 0');
// Show full battery but not in charging state
utils.executeShellCommand(
'am broadcast -a com.android.systemui.demo -e command battery -e plugged false -e level 100'
);
},
};

export default utils;
24 changes: 23 additions & 1 deletion e2e/Overlay.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import Utils from './Utils';
import TestIDs from '../playground/src/testIDs';
import Android from './AndroidUtils';

const { elementByLabel, elementById } = Utils;
const { elementByLabel, elementById, expectImagesToBeEqual,expectImagesToBeNotEqual } = Utils;

describe('Overlay', () => {
beforeEach(async () => {
Expand Down Expand Up @@ -54,6 +55,27 @@ describe('Overlay', () => {
await elementById(TestIDs.HIDE_TOP_BAR_BUTTON).tap();
await expect(elementById(TestIDs.TOP_BAR_ELEMENT)).toBeVisible();
});

it.e2e(':android: should show banner overlay and not block the screen', async () => {
const snapshottedImagePath = './e2e/assets/overlay_banner_padding.png';
Android.setDemoMode();
let expected = await device.takeScreenshot('without_banner');
await elementById(TestIDs.SHOW_BANNER_OVERLAY).tap();
await expect(elementById(TestIDs.BANNER_OVERLAY)).toBeVisible();
const actual = await device.takeScreenshot('with_banner');
expectImagesToBeNotEqual(expected, actual)
await elementById(TestIDs.SET_LAYOUT_BOTTOM_INSETS).tap();
expected = await device.takeScreenshot('with_banner');
expectImagesToBeEqual(expected, snapshottedImagePath)
});

it.e2e(':ios: should show banner overlay and not block the screen', async () => {
await elementById(TestIDs.SHOW_BANNER_OVERLAY).tap();
await expect(elementById(TestIDs.BANNER_OVERLAY)).toBeVisible();
await expect(elementById(TestIDs.FOOTER_TEXT)).toBeNotVisible();
await elementById(TestIDs.SET_LAYOUT_BOTTOM_INSETS).tap();
await expect(elementById(TestIDs.FOOTER_TEXT)).toBeVisible();
});
});

describe('Overlay Dismiss all', () => {
Expand Down
23 changes: 23 additions & 0 deletions e2e/Utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
import { readFileSync } from 'fs';
function bitmapDiff(imagePath, expectedImagePath) {
const PNG = require('pngjs').PNG;
const pixelmatch = require('pixelmatch');
const img1 = PNG.sync.read(readFileSync(imagePath));
const img2 = PNG.sync.read(readFileSync(expectedImagePath));
const {width, height} = img1;
const diff = new PNG({width, height});

return pixelmatch(img1.data, img2.data, diff.data, width, height, {threshold: 0.0})
}
const utils = {
elementByLabel: (label) => {
return element(by.text(label));
Expand All @@ -18,6 +29,18 @@ const utils = {
}
},
sleep: (ms) => new Promise((res) => setTimeout(res, ms)),
expectImagesToBeEqual:(imagePath, expectedImagePath)=>{
let diff = bitmapDiff(imagePath,expectedImagePath);
if(diff!==0){
throw Error(`${imagePath} should be the same as ${expectedImagePath}, with diff: ${diff}`)
}
} ,
expectImagesToBeNotEqual:(imagePath, expectedImagePath)=>{
let diff = bitmapDiff(imagePath,expectedImagePath);
if(diff===0){
throw Error(`${imagePath} should be the same as ${expectedImagePath}, with diff: ${diff}`)
}
}
};

export default utils;
Binary file added e2e/assets/overlay_banner_padding.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions e2e/iOSUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { execSync } from 'shell-utils/src/exec';

const utils = {
setDemoMode: () => {
execSync(
'xcrun simctl status_bar "iPhone 11" override --time "12:00" --batteryState charged --batteryLevel 100 --wifiBars 3 --cellularMode active --cellularBars 4'
);
},
};

export default utils;

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import android.content.Context;


import com.reactnativenavigation.options.layout.LayoutOptions;
import com.reactnativenavigation.options.params.NullNumber;
import com.reactnativenavigation.options.params.NullText;
import com.reactnativenavigation.options.parsers.TypefaceLoader;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.reactnativenavigation.options.layout

import com.reactnativenavigation.utils.dp
import org.json.JSONObject

class LayoutInsets(
var top: Int?=null,
var left: Int?=null,
var bottom: Int?=null,
var right: Int?=null
) {
fun merge(toMerge: LayoutInsets?, defaults: LayoutInsets?) {
toMerge?.let { options->
options.top?.let { this.top = it }
options.bottom?.let { this.bottom = it }
options.left?.let { this.left = it }
options.right?.let { this.right = it }
}

defaults?.let {
options->
top = top?:options.top
left = left?:options.left
right = right?:options.right
bottom = bottom?:options.bottom
}
}

companion object{
fun parse(jsonObject: JSONObject?): LayoutInsets {
return LayoutInsets(
jsonObject?.optInt("top")?.dp,
jsonObject?.optInt("left")?.dp,
jsonObject?.optInt("bottom")?.dp,
jsonObject?.optInt("right")?.dp
)
}
}

fun hasValue(): Boolean {
return top!=null || bottom!=null || left!=null || right!=null
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.reactnativenavigation.options.layout

import android.content.Context
import com.reactnativenavigation.options.LayoutDirection
import com.reactnativenavigation.options.OrientationOptions
import com.reactnativenavigation.options.params.*
import com.reactnativenavigation.options.params.Number
import com.reactnativenavigation.options.parsers.BoolParser
import com.reactnativenavigation.options.parsers.NumberParser
import org.json.JSONObject

class LayoutOptions {
@JvmField
var backgroundColor: ThemeColour = NullThemeColour()

@JvmField
var componentBackgroundColor: ThemeColour = NullThemeColour()

@JvmField
var topMargin: Number = NullNumber()

@JvmField
var adjustResize: Bool = NullBool()

@JvmField
var orientation = OrientationOptions()

@JvmField
var direction = LayoutDirection.DEFAULT

var insets: LayoutInsets = LayoutInsets()


fun mergeWith(other: LayoutOptions) {
if (other.backgroundColor.hasValue()) backgroundColor = other.backgroundColor
if (other.componentBackgroundColor.hasValue()) componentBackgroundColor = other.componentBackgroundColor
if (other.topMargin.hasValue()) topMargin = other.topMargin
if (other.orientation.hasValue()) orientation = other.orientation
if (other.direction.hasValue()) direction = other.direction
if (other.adjustResize.hasValue()) adjustResize = other.adjustResize
insets.merge(other.insets, null)
}

fun mergeWithDefault(defaultOptions: LayoutOptions) {
if (!backgroundColor.hasValue()) backgroundColor = defaultOptions.backgroundColor
if (!componentBackgroundColor.hasValue()) componentBackgroundColor = defaultOptions.componentBackgroundColor
if (!topMargin.hasValue()) topMargin = defaultOptions.topMargin
if (!orientation.hasValue()) orientation = defaultOptions.orientation
if (!direction.hasValue()) direction = defaultOptions.direction
if (!adjustResize.hasValue()) adjustResize = defaultOptions.adjustResize
insets.merge(null, defaultOptions.insets)

}

companion object {
@JvmStatic
fun parse(context: Context?, json: JSONObject?): LayoutOptions {
val result = LayoutOptions()
if (json == null) return result
result.backgroundColor = ThemeColour.parse(context!!, json.optJSONObject("backgroundColor"))
result.componentBackgroundColor = ThemeColour.parse(context, json.optJSONObject("componentBackgroundColor"))
result.topMargin = NumberParser.parse(json, "topMargin")
result.insets = LayoutInsets.parse(json.optJSONObject("insets"))
result.orientation = OrientationOptions.parse(json)
result.direction = LayoutDirection.fromString(json.optString("direction", ""))
result.adjustResize = BoolParser.parse(json, "adjustResize")
return result
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.reactnativenavigation.utils

import android.content.res.Resources

val Int.dp: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()

val Float.dp: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
Original file line number Diff line number Diff line change
Expand Up @@ -144,16 +144,17 @@ public void applyBottomInset() {
protected WindowInsetsCompat onApplyWindowInsets(View view, WindowInsetsCompat insets) {
ViewController<?> viewController = findController(view);
if (viewController == null || viewController.getView() == null) return insets;
final Insets keyboardInsets = insets.getInsets( WindowInsetsCompat.Type.ime());
final int keyboardBottomInset = options.layout.adjustResize.get(true) ? insets.getInsets( WindowInsetsCompat.Type.ime()).bottom : 0;
final Insets systemBarsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars() );
final int visibleNavBar = resolveCurrentOptions(presenter.defaultOptions).navigationBar.isVisible.isTrueOrUndefined()?1:0;
final WindowInsetsCompat finalInsets = new WindowInsetsCompat.Builder().setInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.ime(),
Insets.of(systemBarsInsets.left,
0,
systemBarsInsets.right,
Math.max(visibleNavBar*systemBarsInsets.bottom,keyboardInsets.bottom))
Math.max(visibleNavBar*systemBarsInsets.bottom,keyboardBottomInset))
).build();
return ViewCompat.onApplyWindowInsets(viewController.getView(), finalInsets);
ViewCompat.onApplyWindowInsets(viewController.getView(), finalInsets);
return insets;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
import android.content.res.Configuration;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.view.WindowInsetsCompat;

import com.facebook.react.ReactInstanceManager;
import com.reactnativenavigation.options.Options;
Expand Down Expand Up @@ -82,6 +84,8 @@ public Navigator(final Activity activity, ChildControllersRegistry childRegistry
overlaysLayout = new CoordinatorLayout(getActivity());
}



public void bindViews() {
modalStack.setModalsLayout(modalsLayout);
modalStack.setRootLayout(rootLayout);
Expand Down Expand Up @@ -147,6 +151,7 @@ public void setRoot(final ViewController<?> appearing, CommandListener commandLi
final ViewController<?> disappearing = previousRoot;
root = appearing;
root.setOverlay(new RootOverlay(getActivity(), contentLayout));
root.setParentController(this);
rootPresenter.setRoot(appearing, disappearing, defaultOptions, new CommandListenerAdapter(commandListener) {
@Override
public void onSuccess(String childId) {
Expand Down
Loading