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

Fix modals #1603

Merged
merged 4 commits into from
Sep 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import android.util.Log
import android.view.MotionEvent
import android.view.ViewGroup
import android.view.ViewParent
import com.facebook.react.ReactRootView
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.common.ReactConstants
import com.facebook.react.views.modal.RNGHModalUtils
import com.facebook.react.uimanager.RootView
import com.facebook.react.views.modal.ReactModalHostView
import com.swmansion.gesturehandler.GestureHandler
import com.swmansion.gesturehandler.GestureHandlerOrchestrator

Expand Down Expand Up @@ -71,10 +71,8 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
val event = MotionEvent.obtain(time, time, MotionEvent.ACTION_CANCEL, 0f, 0f, 0).apply {
action = MotionEvent.ACTION_CANCEL
}
if (rootView is ReactRootView) {
if (rootView is RootView) {
rootView.onChildStartedNativeGesture(event)
} else {
RNGHModalUtils.dialogRootViewGroupOnChildStartedNativeGesture(rootView, event)
}
}
}
Expand Down Expand Up @@ -122,7 +120,7 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
private fun findRootViewTag(viewGroup: ViewGroup): ViewGroup {
UiThreadUtil.assertOnUiThread()
var parent: ViewParent? = viewGroup
while (parent != null && parent !is ReactRootView && !RNGHModalUtils.isDialogRootViewGroup(parent)) {
while (parent != null && parent !is RootView) {
parent = parent.parent
}
checkNotNull(parent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import android.content.Context
import android.util.Log
import android.view.MotionEvent
import android.view.ViewGroup
import android.view.ViewParent
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.common.ReactConstants
import com.facebook.react.uimanager.RootView
import com.facebook.react.views.modal.ReactModalHostView
import com.facebook.react.views.view.ReactViewGroup

class RNGestureHandlerRootView(context: Context?) : ReactViewGroup(context) {
Expand Down Expand Up @@ -51,6 +54,12 @@ class RNGestureHandlerRootView(context: Context?) : ReactViewGroup(context) {
if (parent is RNGestureHandlerEnabledRootView || parent is RNGestureHandlerRootView) {
return true
}
// Checks other roots views but it's mainly for ReactModalHostView.DialogRootViewGroup
// since modals are outside RN hierachy and we have to initialize GH's root view for it
// Note that RNGestureHandlerEnabledRootView implements RootView - that's why this check has to be below
if (parent is RootView) {
return false
}
parent = parent.parent
}
return false
Expand Down
13 changes: 0 additions & 13 deletions example/android/app/src/main/java/com/example/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package com.example;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;

public class MainActivity extends ReactActivity {

Expand All @@ -15,14 +12,4 @@ public class MainActivity extends ReactActivity {
protected String getMainComponentName() {
return "Example";
}

@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
@Override
protected ReactRootView createRootView() {
return new RNGestureHandlerEnabledRootView(MainActivity.this);
}
};
}
}
5 changes: 5 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import DoubleDraggable from './release_tests/doubleDraggable';
import { ComboWithGHScroll } from './release_tests/combo';
import { TouchablesIndex, TouchableExample } from './release_tests/touchables';
import Rows from './release_tests/rows';
import NestedGestureHandlerRootViewWithModal from './release_tests/nestedGHRootViewWithModal';
import { PinchableBox } from './recipes/scaleAndRotate';
import PanAndScroll from './recipes/panAndScroll';
import { BottomSheet } from './showcase/bottomSheet';
Expand Down Expand Up @@ -67,6 +68,10 @@ const EXAMPLES: ExamplesSection[] = [
{
sectionTitle: 'Release tests',
data: [
{
name: 'Modals with nested GHRootViews - issue #139',
component: NestedGestureHandlerRootViewWithModal,
},
{ name: 'Double pinch & rotate', component: DoublePinchRotate },
{ name: 'Double draggable', component: DoubleDraggable },
{ name: 'Rows', component: Rows },
Expand Down
63 changes: 63 additions & 0 deletions example/src/release_tests/nestedGHRootViewWithModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as React from 'react';
import { useState } from 'react';
import { StyleSheet, Modal, View, Text } from 'react-native';

import {
GestureHandlerRootView,
TouchableOpacity,
} from 'react-native-gesture-handler';
import { DraggableBox } from '../basic/draggable';

export default function App() {
const [isModalVisible, setIsModalVisible] = useState(false);

function ToggleModalButton() {
return (
<TouchableOpacity
style={styles.button}
onPress={() => setIsModalVisible((visible) => !visible)}>
<Text>{isModalVisible ? 'Close' : 'Open'} modal</Text>
</TouchableOpacity>
);
}

return (
<GestureHandlerRootView style={styles.container}>
<Text style={styles.description}>
DraggableBox inside modal should be moveable
</Text>
<ToggleModalButton />
<Modal visible={isModalVisible}>
<GestureHandlerRootView style={{ flex: 1 }}>
<View style={styles.modalView}>
<DraggableBox />
<ToggleModalButton />
</View>
</GestureHandlerRootView>
</Modal>
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
modalView: {
margin: 20,
marginTop: 200,
backgroundColor: 'transparent',
borderRadius: 6,
padding: 20,
alignItems: 'center',
borderWidth: 2,
},
container: {
flex: 1,
display: 'flex',
alignItems: 'center',
},
description: {
margin: 20,
},
button: {
borderWidth: 2,
padding: 10,
},
});
34 changes: 9 additions & 25 deletions src/GestureHandlerRootView.android.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,18 @@
import * as React from 'react';
import { PropsWithChildren } from 'react';
import { View, requireNativeComponent } from 'react-native';
import { requireNativeComponent } from 'react-native';
import { GestureHandlerRootViewProps } from './GestureHandlerRootView';

const GestureHandlerRootViewNative = requireNativeComponent(
'GestureHandlerRootView'
);

const GestureHandlerRootViewContext = React.createContext(false);

type Props = PropsWithChildren<Record<string, unknown>>;

export default function GestureHandlerRootView({ children, ...rest }: Props) {
export default function GestureHandlerRootView({
children,
...rest
}: GestureHandlerRootViewProps) {
return (
<GestureHandlerRootViewContext.Consumer>
{(available) => {
if (available) {
// If we already have a parent wrapped in the gesture handler root view,
// We don't need to wrap it again in root view
// We still wrap it in a normal view so our styling stays the same
return <View {...rest}>{children}</View>;
}

return (
<GestureHandlerRootViewContext.Provider value>
<GestureHandlerRootViewNative {...rest}>
{children}
</GestureHandlerRootViewNative>
</GestureHandlerRootViewContext.Provider>
);
}}
</GestureHandlerRootViewContext.Consumer>
<GestureHandlerRootViewNative {...rest}>
{children}
</GestureHandlerRootViewNative>
);
}
13 changes: 11 additions & 2 deletions src/GestureHandlerRootView.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import { View } from 'react-native';
import * as React from 'react';
import { PropsWithChildren } from 'react';
import { View, ViewProps } from 'react-native';

export default View;
export interface GestureHandlerRootViewProps
extends PropsWithChildren<ViewProps> {}

export default function GestureHandlerRootView({
...rest
}: GestureHandlerRootViewProps) {
return <View {...rest} />;
}