Skip to content

Commit

Permalink
feat: move react-native-window-view to screens package (#1096)
Browse files Browse the repository at this point in the history
Moved the `WindowView` to this repo and renamed it to `RNSFullWindowOverlay`. Removed the necessity of adding changes to `AppDelegate.m` by providing an extension of `UIWindow` in the package.
  • Loading branch information
WoLewicki authored Sep 8, 2021
1 parent aca5d4c commit 3f8e4aa
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 0 deletions.
1 change: 1 addition & 0 deletions TestsExample/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import Test1032 from './src/Test1032';
import Test1036 from './src/Test1036';
import Test1072 from './src/Test1072';
import Test1084 from './src/Test1084';
import Test1096 from './src/Test1096';

export default function App() {
return (
Expand Down
89 changes: 89 additions & 0 deletions TestsExample/src/Test1096.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import * as React from 'react';

import { Button, StyleSheet, View, Modal } from 'react-native';
import {FullWindowOverlay} from 'react-native-screens';
import {
createNativeStackNavigator,
NativeStackNavigationProp,
} from 'react-native-screens/native-stack';
import { NavigationContainer, ParamListBase } from '@react-navigation/native';

function Home({
navigation,
}: {
navigation: NativeStackNavigationProp<ParamListBase>;
}) {
const [isShowModal, setIsShowModal] = React.useState(false);

return (
<View style={styles.container}>
<Button title="show rn modal" onPress={() => setIsShowModal(true)} />
<Button
title="Go to RNScreens modal"
onPress={() => navigation.navigate('Modal')}
/>
<Modal
animationType="slide"
visible={isShowModal}
presentationStyle="pageSheet"
>
<View style={styles.container}>
<Button
title="dismiss rn modal"
onPress={() => setIsShowModal(false)}
/>
</View>
</Modal>
<FullWindowOverlay style={{position: 'absolute', width: '100%', height: '100%', justifyContent: 'center'}}>
<View style={styles.box} />
<Button title="click me" onPress={() => console.warn('clicked')} />
</FullWindowOverlay>
</View>
);
}

function ModalScreen({
navigation,
}: {
navigation: NativeStackNavigationProp<ParamListBase>;
}) {
return (
<View style={styles.container}>
<Button title="dismiss modal" onPress={() => navigation.goBack()} />
</View>
);
}

const NativeStack = createNativeStackNavigator();

export default function App() {
return (
<NavigationContainer>
<NativeStack.Navigator>
<NativeStack.Screen name="Home" component={Home} />
<NativeStack.Screen
name="Modal"
component={ModalScreen}
options={{ stackPresentation: 'modal' }}
/>
</NativeStack.Navigator>
</NavigationContainer>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'flex-start',
justifyContent: 'center',
},

box: {
width: 40,
height: 40,
borderRadius: 10,
borderWidth: 2,
borderColor: 'black',
backgroundColor: 'red',
},
});
15 changes: 15 additions & 0 deletions ios/RNSFullWindowOverlay.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#import <React/RCTInvalidating.h>
#import <React/RCTView.h>
#import <React/RCTViewManager.h>

@interface RNSFullWindowOverlayManager : RCTViewManager

@end

@interface RNSFullWindowOverlayContainer : UIView

@end

@interface RNSFullWindowOverlay : RCTView <RCTInvalidating>

@end
105 changes: 105 additions & 0 deletions ios/RNSFullWindowOverlay.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#import <UIKit/UIKit.h>

#import "RNSFullWindowOverlay.h"

#import <React/RCTTouchHandler.h>

@implementation RNSFullWindowOverlayContainer

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
for (UIView *view in [self subviews]) {
if (view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event]) {
return YES;
}
}
return NO;
}

@end

@implementation RNSFullWindowOverlay {
__weak RCTBridge *_bridge;
RNSFullWindowOverlayContainer *_container;
CGRect _reactFrame;
RCTTouchHandler *_touchHandler;
}

- (instancetype)initWithBridge:(RCTBridge *)bridge
{
if (self = [super init]) {
_bridge = bridge;
_reactFrame = CGRectNull;
_container = self.container;
[self show];
}

return self;
}

- (void)reactSetFrame:(CGRect)frame
{
_reactFrame = frame;
[_container setFrame:frame];
}

- (void)addSubview:(UIView *)view
{
[_container addSubview:view];
}

- (RNSFullWindowOverlayContainer *)container
{
if (_container == nil) {
_container = [[RNSFullWindowOverlayContainer alloc] initWithFrame:_reactFrame];
}

return _container;
}

- (void)show
{
UIWindow *window = RCTSharedApplication().delegate.window;
[window addSubview:_container];
}

- (void)hide
{
if (!_container) {
return;
}

[_container removeFromSuperview];
}

- (void)didMoveToWindow
{
if (self.window == nil) {
[self hide];
[_touchHandler detachFromView:_container];
} else {
if (_touchHandler == nil) {
_touchHandler = [[RCTTouchHandler alloc] initWithBridge:_bridge];
}
[_touchHandler attachToView:_container];
}
}

- (void)invalidate
{
[self hide];
_container = nil;
}

@end

@implementation RNSFullWindowOverlayManager

RCT_EXPORT_MODULE()

- (UIView *)view
{
return [[RNSFullWindowOverlay alloc] initWithBridge:self.bridge];
}

@end
9 changes: 9 additions & 0 deletions ios/UIWindow+RNScreens.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIWindow (RNScreens)

@end

NS_ASSUME_NONNULL_END
17 changes: 17 additions & 0 deletions ios/UIWindow+RNScreens.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#import "RNSFullWindowOverlay.h"
#import "UIWindow+RNScreens.h"

@implementation UIWindow (RNScreens)

- (void)didAddSubview:(UIView *)subview
{
if (![subview isKindOfClass:[RNSFullWindowOverlayContainer class]]) {
for (UIView *view in self.subviews) {
if ([view isKindOfClass:[RNSFullWindowOverlayContainer class]]) {
[self bringSubviewToFront:view];
}
}
}
}

@end
15 changes: 15 additions & 0 deletions src/index.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ let NativeScreenStackHeaderSubview: React.ComponentType<React.PropsWithChildren<
>>;
let AnimatedNativeScreen: React.ComponentType<ScreenProps>;
let NativeSearchBar: React.ComponentType<SearchBarProps>;
let NativeFullWindowOverlay: React.ComponentType<View>;

const ScreensNativeModules = {
get NativeScreen() {
Expand Down Expand Up @@ -112,6 +113,12 @@ const ScreensNativeModules = {
NativeSearchBar = NativeSearchBar || requireNativeComponent('RNSSearchBar');
return NativeSearchBar;
},

get NativeFullWindowOverlay() {
NativeFullWindowOverlay =
NativeFullWindowOverlay || requireNativeComponent('RNSFullWindowOverlay');
return NativeFullWindowOverlay;
},
};

class Screen extends React.Component<ScreenProps> {
Expand Down Expand Up @@ -347,6 +354,14 @@ module.exports = {

return ScreensNativeModules.NativeSearchBar;
},
get FullWindowOverlay() {
if (Platform.OS !== 'ios') {
console.warn('Importing FullWindowOverlay is only valid on iOS devices.');
return View;
}

return ScreensNativeModules.NativeFullWindowOverlay;
},
// these are functions and will not be evaluated until used
// so no need to use getters for them
ScreenStackHeaderBackButtonImage,
Expand Down
2 changes: 2 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export const NativeScreenNavigationContainer: React.ComponentType<ScreenContaine

export const ScreenStack: React.ComponentType<ScreenStackProps> = View;

export const FullWindowOverlay = View;

export const ScreenStackHeaderBackButtonImage = (
props: ImageProps
): JSX.Element => (
Expand Down

0 comments on commit 3f8e4aa

Please sign in to comment.