Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
02e2146
run modals and test overlays temp
swabbass Jul 22, 2021
aa21f3a
Merge branch 'master' into declartive-modals
swabbass Jul 22, 2021
190be12
Merge branch 'master' into declartive-modals
swabbass Jul 22, 2021
9c22fc7
tmp
swabbass Aug 2, 2021
4a883fc
Merge branch 'master' into declartive-modals
swabbass Aug 2, 2021
501a62c
modal component return null when not visible
swabbass Aug 9, 2021
84d3770
temp
swabbass Aug 9, 2021
73d2b33
tmp
swabbass Aug 9, 2021
ec8839f
use react context instead of activity
swabbass Aug 11, 2021
b6cd275
Update DeclaredLayoutHost.kt
swabbass Aug 11, 2021
2a9c16f
showing modal + dismiss changing visible
swabbass Aug 11, 2021
5417253
Merge branch 'master' into declartive-modals
swabbass Aug 20, 2021
af8d4cb
tmpo
swabbass Sep 15, 2021
910d468
add events
swabbass Sep 16, 2021
e1555a5
make children collapsable (native managed)
swabbass Sep 16, 2021
b07e790
Squashed commit of the following:
swabbass Sep 16, 2021
94095b2
Rename and Refactor Declared to Modal
swabbass Sep 16, 2021
000befa
Merge branch 'master' into declartive-modals
swabbass Sep 16, 2021
16e49ef
Update NavigationReactInitializer.java
swabbass Oct 3, 2021
6bcab70
Update ReactGateway.java
swabbass Oct 3, 2021
00abb93
Update NavigationReactInitializer.java
swabbass Oct 3, 2021
63334f3
Update NavigationReactInitializer.java
swabbass Oct 3, 2021
46cd4be
Update CoordinatorLayoutUtils.java
swabbass Oct 3, 2021
0945b90
Update ModalStack.java
swabbass Oct 3, 2021
beff45f
Update ModalStack.java
swabbass Oct 3, 2021
2997e11
Update ModalStack.java
swabbass Oct 3, 2021
3e91575
Update Navigator.java
swabbass Oct 3, 2021
37c50ee
Update TouchablePreview.tsx
swabbass Oct 3, 2021
04aa5dd
Update LayoutsScreen.tsx
swabbass Oct 3, 2021
6bf9efe
Update testIDs.ts
swabbass Oct 3, 2021
e391f68
Update TouchablePreview.tsx
swabbass Oct 3, 2021
368595c
Update ModalScreen.tsx
swabbass Oct 3, 2021
9b49d9f
Update ModalScreen.tsx
swabbass Oct 3, 2021
76f2464
Update testIDs.ts
swabbass Oct 3, 2021
900de0f
add more e2e tests
swabbass Oct 3, 2021
c7f3826
Update NavigationActivity.java
swabbass Oct 3, 2021
fafc170
fix tests
swabbass Oct 3, 2021
a013e28
Update build.gradle
swabbass Oct 3, 2021
728b69c
Squashed commit of the following:
swabbass Oct 3, 2021
2c8416f
Merge branch 'master' into declartive-modals
swabbass Oct 3, 2021
01fdfa4
revert local changes
swabbass Oct 3, 2021
5921e4d
Merge branch 'declartive-modals' of https://github.com/wix/react-nati…
swabbass Oct 3, 2021
8623fec
remove unused event
swabbass Oct 3, 2021
9d36bb6
add missing props
swabbass Oct 3, 2021
9867283
Update ModalViewManager.kt
swabbass Oct 3, 2021
0f8890e
rename
swabbass Oct 3, 2021
bc1f4a3
rename
swabbass Oct 3, 2021
791d266
Update ModalLayoutController.kt
swabbass Oct 3, 2021
a52bedb
Update NavigationModule.java
swabbass Oct 4, 2021
9d4db17
update docs
swabbass Oct 4, 2021
53d1544
Merge branch 'master' into declartive-modals
swabbass Oct 4, 2021
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
50 changes: 47 additions & 3 deletions e2e/Modals.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,54 @@ describe('modal', () => {
await expect(elementByLabel('dismissModal promise resolved with: UniqueStackId')).toBeVisible();
});

it('dismiss previous react-native modal', async () => {
await elementById(TestIDs.TOGGLE_REACT_NATIVE_MODAL).tap();
await elementById(TestIDs.SHOW_MODAL_AND_DISMISS_REACT_NATIVE_MODAL).tap();
it.e2e('should show declated modal', async () => {
await elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL).tap();
await expect(elementByLabel("Dismiss declared Modal")).toBeVisible();
await elementById(TestIDs.DISMISS_MODAL_BTN).tap();
await expect(elementById(TestIDs.MODAL_SCREEN_HEADER)).toBeVisible();
});

it.e2e('should show and dismiss multiple modals including declared modal', async () => {
await elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL).tap();
await elementById(TestIDs.SHOW_MODAL_FROM_DECLARED_BUTTON).tap();
await expect(elementByLabel("Toggle declared modal")).toBeVisible();
await elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL).tap();
await elementById(TestIDs.DISMISS_MODAL_BTN).tap();
await elementById(TestIDs.DISMISS_MODAL_BTN).tap();
await expect(elementByLabel("Dismiss declared Modal")).toBeVisible();
await elementById(TestIDs.DISMISS_MODAL_BTN).tap();

await expect(elementById(TestIDs.MODAL_SCREEN_HEADER)).toBeVisible();
});

it.e2e('overlay should be on top of all modals', async () => {
await elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL).tap();
await elementById(TestIDs.OVERLAY_BTN).tap();
await expect(elementByLabel("Dismiss declared Modal")).toBeVisible();
await expect(elementById(TestIDs.DISMISS_ALL_OVERLAYS_BUTTON)).toBeVisible();

await elementById(TestIDs.SHOW_MODAL_FROM_DECLARED_BUTTON).tap();
await expect(elementByLabel("Modal Lifecycle")).toBeVisible();

await elementById(TestIDs.DISMISS_MODAL_BTN).tap();
await elementById(TestIDs.DISMISS_MODAL_BTN).tap();

await elementById(TestIDs.DISMISS_ALL_OVERLAYS_BUTTON).tap();
});



it.e2e(':android: should handle back properly', async () => {
await elementById(TestIDs.TOGGLE_REACT_DECLARED_MODAL).tap();
await elementById(TestIDs.SHOW_MODAL_FROM_DECLARED_BUTTON).tap();
await expect(elementByLabel("Toggle declared modal")).toBeVisible();

Android.pressBack();

await expect(elementByLabel("Dismiss declared Modal")).toBeVisible();

Android.pressBack();

await expect(elementByLabel("Toggle declared modal")).toBeVisible();
});
});

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.reactnativenavigation.react

import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
import com.reactnativenavigation.NavigationActivity
import com.reactnativenavigation.options.LayoutFactory
import com.reactnativenavigation.react.modal.ModalViewManager

class NavigationPackage(private val reactNativeHost: ReactNativeHost) : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf(
NavigationModule(
reactContext,
reactNativeHost.reactInstanceManager,
LayoutFactory(reactNativeHost.reactInstanceManager)
)
)
}

override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {

return listOf(ModalViewManager((reactContext.currentActivity as NavigationActivity).navigator))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,67 +9,67 @@

public class NavigationReactInitializer implements ReactInstanceManager.ReactInstanceEventListener {

private final ReactInstanceManager reactInstanceManager;
private final DevPermissionRequest devPermissionRequest;
private boolean waitingForAppLaunchEvent = true;
private boolean isActivityReadyForUi = false;
private final ReactInstanceManager reactInstanceManager;
private final DevPermissionRequest devPermissionRequest;
private boolean waitingForAppLaunchEvent = true;
private boolean isActivityReadyForUi = false;

NavigationReactInitializer(ReactInstanceManager reactInstanceManager, boolean isDebug) {
this.reactInstanceManager = reactInstanceManager;
this.devPermissionRequest = new DevPermissionRequest(isDebug);
}
NavigationReactInitializer(ReactInstanceManager reactInstanceManager, boolean isDebug) {
this.reactInstanceManager = reactInstanceManager;
this.devPermissionRequest = new DevPermissionRequest(isDebug);
}

void onActivityCreated() {
reactInstanceManager.addReactInstanceEventListener(this);
waitingForAppLaunchEvent = true;
}
void onActivityCreated() {
reactInstanceManager.addReactInstanceEventListener(this);
waitingForAppLaunchEvent = true;
}

void onActivityResumed(NavigationActivity activity) {
if (devPermissionRequest.shouldAskPermission(activity)) {
devPermissionRequest.askPermission(activity);
} else {
reactInstanceManager.onHostResume(activity, activity);
void onActivityResumed(NavigationActivity activity) {
if (devPermissionRequest.shouldAskPermission(activity)) {
devPermissionRequest.askPermission(activity);
} else {
reactInstanceManager.onHostResume(activity, activity);
isActivityReadyForUi = true;
prepareReactApp();
}
}
prepareReactApp();
}
}

void onActivityPaused(NavigationActivity activity) {
void onActivityPaused(NavigationActivity activity) {
isActivityReadyForUi = false;
if (reactInstanceManager.hasStartedCreatingInitialContext()) {
reactInstanceManager.onHostPause(activity);
}
}
if (reactInstanceManager.hasStartedCreatingInitialContext()) {
reactInstanceManager.onHostPause(activity);
}
}

void onActivityDestroyed(NavigationActivity activity) {
reactInstanceManager.removeReactInstanceEventListener(this);
if (reactInstanceManager.hasStartedCreatingInitialContext()) {
reactInstanceManager.onHostDestroy(activity);
}
}
void onActivityDestroyed(NavigationActivity activity) {
reactInstanceManager.removeReactInstanceEventListener(this);
if (reactInstanceManager.hasStartedCreatingInitialContext()) {
reactInstanceManager.onHostDestroy(activity);
}
}

private void prepareReactApp() {
if (shouldCreateContext()) {
reactInstanceManager.createReactContextInBackground();
} else if (waitingForAppLaunchEvent) {
private void prepareReactApp() {
if (shouldCreateContext()) {
reactInstanceManager.createReactContextInBackground();
} else if (waitingForAppLaunchEvent) {
if (reactInstanceManager.getCurrentReactContext() != null) {
emitAppLaunched(reactInstanceManager.getCurrentReactContext());
emitAppLaunched(reactInstanceManager.getCurrentReactContext());
}
}
}
}
}

private void emitAppLaunched(@NonNull ReactContext context) {
if (!isActivityReadyForUi) return;
waitingForAppLaunchEvent = false;
new EventEmitter(context).appLaunched();
}
private void emitAppLaunched(@NonNull ReactContext context) {
if (!isActivityReadyForUi) return;
waitingForAppLaunchEvent = false;
new EventEmitter(context).appLaunched();
}

private boolean shouldCreateContext() {
return !reactInstanceManager.hasStartedCreatingInitialContext();
}
private boolean shouldCreateContext() {
return !reactInstanceManager.hasStartedCreatingInitialContext();
}

@Override
public void onReactContextInitialized(final ReactContext context) {
@Override
public void onReactContextInitialized(final ReactContext context) {
emitAppLaunched(context);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.reactnativenavigation.react.modal

import com.facebook.react.uimanager.events.Event
import com.facebook.react.uimanager.events.RCTEventEmitter

open class RequestCloseModalEvent(viewTag: Int) : Event<RequestCloseModalEvent>(viewTag) {

companion object{
const val EVENT_NAME = "topRequestClose"
}

override fun getEventName(): String {
return EVENT_NAME
}

override fun dispatch(rctEventEmitter: RCTEventEmitter) {
rctEventEmitter.receiveEvent(viewTag, eventName, null)
}
}

open class ShowModalEvent(viewTag: Int) : Event<ShowModalEvent>(viewTag) {

companion object{
const val EVENT_NAME = "topShow"
}

override fun getEventName(): String {
return EVENT_NAME
}

override fun dispatch(rctEventEmitter: RCTEventEmitter) {
rctEventEmitter.receiveEvent(viewTag, eventName, null)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.reactnativenavigation.react.modal

import android.content.Context
import android.view.MotionEvent
import android.view.View
import com.facebook.react.bridge.*
import com.facebook.react.uimanager.*
import com.facebook.react.uimanager.events.EventDispatcher
import com.facebook.react.views.view.ReactViewGroup


class ModalContentLayout(context: Context?) : ReactViewGroup(context), RootView{
private var hasAdjustedSize = false
private var viewWidth = 0
private var viewHeight = 0
private val mJSTouchDispatcher = JSTouchDispatcher(this)

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
viewWidth = w
viewHeight = h
this.updateFirstChildView()
}
private fun updateFirstChildView() {
if (this.childCount > 0) {
hasAdjustedSize = false
val viewTag = getChildAt(0).id
val reactContext: ReactContext = this.getReactContext()
reactContext.runOnNativeModulesQueueThread(object : GuardedRunnable(reactContext) {
override fun runGuarded() {
val uiManager = this@ModalContentLayout.getReactContext().getNativeModule<UIManagerModule>(
UIManagerModule::class.java
) as UIManagerModule
uiManager.updateNodeSize(
viewTag,
this@ModalContentLayout.viewWidth,
this@ModalContentLayout.viewHeight
)
}
})
} else {
hasAdjustedSize = true
}
}

override fun addView(child: View?, index: Int, params: LayoutParams?) {
super.addView(child, index, params)
if (hasAdjustedSize) {
updateFirstChildView()
}
}
override fun onChildStartedNativeGesture(androidEvent: MotionEvent?) {
mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, this.getEventDispatcher())
}
override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
private fun getEventDispatcher(): EventDispatcher? {
val reactContext: ReactContext = this.getReactContext()
return reactContext.getNativeModule(UIManagerModule::class.java)!!.eventDispatcher
}


override fun handleException(t: Throwable?) {
getReactContext().handleException(RuntimeException(t))
}

private fun getReactContext(): ReactContext {
return this.context as ReactContext
}

override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
mJSTouchDispatcher.handleTouchEvent(event, getEventDispatcher())
return super.onInterceptTouchEvent(event)
}

override fun onTouchEvent(event: MotionEvent?): Boolean {
mJSTouchDispatcher.handleTouchEvent(event, getEventDispatcher())
super.onTouchEvent(event)
return true
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.reactnativenavigation.react.modal

import android.widget.FrameLayout
import com.facebook.react.bridge.ReactContext
import com.reactnativenavigation.utils.StatusBarUtils

class ModalFrameLayout(context: ReactContext) : FrameLayout(context) {
val modalContentLayout = ModalContentLayout(context)

init {
addView(modalContentLayout, MarginLayoutParams(MarginLayoutParams.WRAP_CONTENT, MarginLayoutParams.WRAP_CONTENT)
.apply {
val translucent = context.currentActivity?.window?.let {
StatusBarUtils.isTranslucent(context.currentActivity?.window)
} ?: false
topMargin = if (translucent) 0 else StatusBarUtils.getStatusBarHeight(context)
})
}
}
Loading