Skip to content

Commit

Permalink
feat: first look at adding full screen swipe
Browse files Browse the repository at this point in the history
  • Loading branch information
WoLewicki committed Oct 5, 2023
1 parent 7585306 commit a6b4d8d
Show file tree
Hide file tree
Showing 28 changed files with 440 additions and 61 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module.exports = {
'react-native-screens',
'react-native-screens/native-stack',
'react-native-screens/reanimated',
'react-native-screens/gesture-handler',
],
'import/ignore': [
'node_modules/react-native/index\\.js$',
Expand Down
29 changes: 9 additions & 20 deletions Example/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import Events from './src/screens/Events';
import Gestures from './src/screens/Gestures';

import { enableFreeze } from 'react-native-screens';
import { GestureDetectorProvider } from 'react-native-screens/gesture-handler';
import { GestureHandlerRootView } from 'react-native-gesture-handler';

enableFreeze();

Expand Down Expand Up @@ -150,26 +152,13 @@ const MainScreen = ({ navigation }: MainScreenProps): JSX.Element => (
);

const ExampleApp = (): JSX.Element => (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
direction: I18nManager.isRTL ? 'rtl' : 'ltr',
}}>
<Stack.Screen
name="Main"
options={{ title: '📱 React Native Screens Examples' }}
component={MainScreen}
/>
{Object.keys(SCREENS).map(name => (
<Stack.Screen
key={name}
name={name}
getComponent={() => SCREENS[name].component}
options={{ headerShown: false }}
/>
))}
</Stack.Navigator>
</NavigationContainer>
<GestureHandlerRootView style={{ flex: 1 }}>
<GestureDetectorProvider>
<NavigationContainer>
<SimpleNativeStack />
</NavigationContainer>
</GestureDetectorProvider>
</GestureHandlerRootView>
);

const styles = StyleSheet.create({
Expand Down
12 changes: 6 additions & 6 deletions Example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ PODS:
- glog
- react-native-restart (0.0.27):
- React-Core
- react-native-safe-area-context (4.7.1):
- react-native-safe-area-context (4.7.2):
- React-Core
- React-NativeModulesApple (0.72.4):
- hermes-engine
Expand Down Expand Up @@ -489,7 +489,7 @@ PODS:
- React-jsi (= 0.72.4)
- React-logger (= 0.72.4)
- React-perflogger (= 0.72.4)
- RNGestureHandler (2.12.1):
- RNGestureHandler (2.13.1):
- React-Core
- RNScreens (3.25.0):
- React-Core
Expand Down Expand Up @@ -680,7 +680,7 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"

SPEC CHECKSUMS:
boost: a7c83b31436843459a1961bfd74b96033dc77234
boost: 57d2868c099736d80fcd648bf211b4431e51a558
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
FBLazyVector: 5d4a3b7f411219a45a6d952f77d2c0a6c9989da5
Expand All @@ -694,7 +694,7 @@ SPEC CHECKSUMS:
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
FlipperKit: 2efad7007d6745a3f95e4034d547be637f89d3f6
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 3d02b25ca00c2d456734d0bcff864cbc62f6ae1a
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
hermes-engine: 81191603c4eaa01f5e4ae5737a9efcf64756c7b2
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
Expand All @@ -714,7 +714,7 @@ SPEC CHECKSUMS:
React-jsinspector: aaed4cf551c4a1c98092436518c2d267b13a673f
React-logger: da1ebe05ae06eb6db4b162202faeafac4b435e77
react-native-restart: 7595693413fe3ca15893702f2c8306c62a708162
react-native-safe-area-context: 9697629f7b2cda43cf52169bb7e0767d330648c2
react-native-safe-area-context: 7aa8e6d9d0f3100a820efb1a98af68aa747f9284
React-NativeModulesApple: edb5ace14f73f4969df6e7b1f3e41bef0012740f
React-perflogger: 496a1a3dc6737f964107cb3ddae7f9e265ddda58
React-RCTActionSheet: 02904b932b50e680f4e26e7a686b33ebf7ef3c00
Expand All @@ -732,7 +732,7 @@ SPEC CHECKSUMS:
React-runtimescheduler: 4941cc1b3cf08b792fbf666342c9fc95f1969035
React-utils: b79f2411931f9d3ea5781404dcbb2fa8a837e13a
ReactCommon: 4b2bdcb50a3543e1c2b2849ad44533686610826d
RNGestureHandler: c0d04458598fcb26052494ae23dda8f8f5162b13
RNGestureHandler: 38aa38413896620338948fbb5c90579a7b1c3fde
RNScreens: 85d3880b52d34db7b8eeebe2f1a0e807c05e69fa
RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Expand Down
1 change: 1 addition & 0 deletions Example/metro.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const root = path.resolve(__dirname, '..');
const modules = [
'@react-navigation/native',
'react-native-safe-area-context',
'react-native-gesture-handler',
...Object.keys(pack.peerDependencies),
];

Expand Down
2 changes: 1 addition & 1 deletion Example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"nanoid": "^4.0.2",
"react": "18.2.0",
"react-native": "0.72.4",
"react-native-gesture-handler": "^2.12.1",
"react-native-gesture-handler": "^2.13.1",
"react-native-restart": "^0.0.27",
"react-native-safe-area-context": "^4.7.1",
"react-native-screens": "link:../",
Expand Down
8 changes: 4 additions & 4 deletions Example/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6689,10 +6689,10 @@ react-native-codegen@^0.71.3:
jscodeshift "^0.13.1"
nullthrows "^1.1.1"

react-native-gesture-handler@^2.12.1:
version "2.12.1"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-2.12.1.tgz#f11a99fb95169810c6886fad5efa01a17fd81660"
integrity sha512-deqh36bw82CFUV9EC4tTo2PP1i9HfCOORGS3Zmv71UYhEZEHkzZv18IZNPB+2Awzj45vLIidZxGYGFxHlDSQ5A==
react-native-gesture-handler@^2.13.1:
version "2.13.1"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-2.13.1.tgz#bad89caacd62c4560b9953b02f85f37ee42d5d4c"
integrity sha512-hW454X7sjuiBN+lobqw63pmT3boAmTl5OP6zQLq83iEe4T6PcHZ9lxzgCrebtgmutY8cJfq9rM2dOUVh9WBcww==
dependencies:
"@egjs/hammerjs" "^2.0.17"
hoist-non-react-statics "^3.3.0"
Expand Down
2 changes: 1 addition & 1 deletion FabricExample/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ SPEC CHECKSUMS:
React-perflogger: 496a1a3dc6737f964107cb3ddae7f9e265ddda58
React-RCTActionSheet: 02904b932b50e680f4e26e7a686b33ebf7ef3c00
React-RCTAnimation: 88feaf0a85648fb8fd497ce749829774910276d6
React-RCTAppDelegate: 365227d2a737855924db21c5a810e39c353ef137
React-RCTAppDelegate: a95d68b4763a2e84e5b3e8d117524e2a5ee7dee7
React-RCTBlob: 0dbc9e2a13d241b37d46b53e54630cbad1f0e141
React-RCTFabric: 0d443ab3cc3f0af82442ec95747d503cee955f26
React-RCTImage: b111645ab901f8e59fc68fbe31f5731bdbeef087
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import com.facebook.react.uimanager.ViewManager

class RNScreensPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
emptyList()
listOf<NativeModule>(
ScreensModule(reactContext)
)

override fun createViewManagers(reactContext: ReactApplicationContext) =
listOf<ViewManager<*, *>>(
Expand Down
19 changes: 19 additions & 0 deletions android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import com.facebook.react.ReactRootView
import com.facebook.react.bridge.ReactContext
import com.facebook.react.modules.core.ChoreographerCompat
import com.facebook.react.modules.core.ReactChoreographer
import com.facebook.react.uimanager.UIManagerHelper
import com.swmansion.rnscreens.Screen.ActivityState
import com.swmansion.rnscreens.events.ScreenDismissedEvent

open class ScreenContainer(context: Context?) : ViewGroup(context) {
@JvmField
Expand Down Expand Up @@ -200,6 +202,23 @@ open class ScreenContainer(context: Context?) : ViewGroup(context) {
transaction.add(id, fragment)
}

fun attachBelowTop() {
val transaction = createTransaction()
attachScreen(transaction, mScreenFragments[mScreenFragments.size - 2].fragment)
}

fun detachTop() {
val transaction = createTransaction()
val top = topScreen as Screen
// detachScreen(transaction, top.fragment as Fragment)
if (context is ReactContext) {
val surfaceId = UIManagerHelper.getSurfaceId(context)
UIManagerHelper
.getEventDispatcherForReactTag(context as ReactContext, top.id)
?.dispatchEvent(ScreenDismissedEvent(surfaceId, top.id))
}
}

private fun detachScreen(transaction: FragmentTransaction, fragment: Fragment) {
transaction.remove(fragment)
}
Expand Down
60 changes: 60 additions & 0 deletions android/src/main/java/com/swmansion/rnscreens/ScreensModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.swmansion.rnscreens

import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.UIManagerHelper

@ReactModule(name = ScreensModule.REACT_CLASS)
class ScreensModule(private val mReactContext: ReactApplicationContext) : ReactContextBaseJavaModule(
mReactContext
) {
override fun getName(): String {
return REACT_CLASS
}

@ReactMethod
fun startTransition(reactTag: Int) {
UiThreadUtil.runOnUiThread(
Runnable {
val uiManager = UIManagerHelper.getUIManagerForReactTag(mReactContext, reactTag)
val stack = uiManager?.resolveView(reactTag)
if (stack is ScreenStack) {
stack.attachBelowTop()
}
}
)
}

@ReactMethod
fun updateTransition(reactTag: Int, progress: Double) {
UiThreadUtil.runOnUiThread(
Runnable {
val uiManager = UIManagerHelper.getUIManagerForReactTag(mReactContext, reactTag)
val stack = uiManager?.resolveView(reactTag)
if (stack is ScreenStack) {
// stack.attachBelowTop()
}
}
)
}

@ReactMethod
fun finishTransition(reactTag: Int, canceled: Boolean) {
UiThreadUtil.runOnUiThread(
Runnable {
val uiManager = UIManagerHelper.getUIManagerForReactTag(mReactContext, reactTag)
val stack = uiManager?.resolveView(reactTag)
if (stack is ScreenStack) {
stack.detachTop()
}
}
)
}

companion object {
const val REACT_CLASS = "RNSModule"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ object DeviceUtils {
fun isPlatformAndroidTV(context: Context?): Boolean {
return context?.packageManager?.hasSystemFeature(PackageManager.FEATURE_LEANBACK) == true
}

}
6 changes: 6 additions & 0 deletions gesture-handler/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"main": "../lib/commonjs/gesture-handler/index",
"module": "../lib/module/gesture-handler/index",
"react-native": "../src/gesture-handler/index",
"types": "../lib/typescript/gesture-handler/index"
}
13 changes: 13 additions & 0 deletions ios/RNSModule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifdef RCT_NEW_ARCH_ENABLED
#import <rnscreens/rnscreens.h>
#else
#import <React/RCTBridge.h>
#endif

@interface RNSModule : NSObject
#ifdef RCT_NEW_ARCH_ENABLED
<NativeScreensModuleSpec>
#else
<RCTBridgeModule>
#endif
@end
89 changes: 89 additions & 0 deletions ios/RNSModule.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#import "RNSModule.h"
#import <React/RCTBridge.h>
#import <React/RCTUIManager.h>
#import <React/RCTUIManagerUtils.h>
#import "RNSScreenStack.h"

@implementation RNSModule

RCT_EXPORT_MODULE()

#ifdef RCT_NEW_ARCH_ENABLED
@synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED;
#endif // RCT_NEW_ARCH_ENABLED
@synthesize bridge = _bridge;

- (dispatch_queue_t)methodQueue
{
// It seems that due to how UIBlocks work with uiManager, we need to call the methods there
// for the blocks to be dispatched before the batch is completed
return dispatch_get_main_queue();
}
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(startTransition : (nonnull NSNumber *)reactTag)
{
RNSScreenStackView *view = [self getScreenStackView:reactTag];

if (![view isKindOfClass:[RNSScreenStackView class]]) {
RCTLogError(@"Invalid svg returned from registry, expecting RNSScreenStackView, got: %@", view);
return @(0);
}

dispatch_sync(dispatch_get_main_queue(), ^{
[view startScreenTransition];
});
return @(1);
}

RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(updateTransition : (nonnull NSNumber *)reactTag progress : (double)progress)
{
RNSScreenStackView *view = [self getScreenStackView:reactTag];

if (![view isKindOfClass:[RNSScreenStackView class]]) {
RCTLogError(@"Invalid svg returned from registry, expecting RNSScreenStackView, got: %@", view);
return @(0);
}
dispatch_sync(dispatch_get_main_queue(), ^{
[view updateScreenTransition:progress];
});

return @(1);
}

RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(finishTransition : (nonnull NSNumber *)reactTag canceled : (BOOL)canceled)
{
RNSScreenStackView *view = [self getScreenStackView:reactTag];

if (![view isKindOfClass:[RNSScreenStackView class]]) {
RCTLogError(@"Invalid svg returned from registry, expecting RNSScreenStackView, got: %@", view);
return @(0);
}
dispatch_sync(dispatch_get_main_queue(), ^{
[view finishScreenTransition:canceled];
});
return @(1);
}

- (RNSScreenStackView *)getScreenStackView:(NSNumber *)reactTag
{
__block RNSScreenStackView *view;
#ifdef RCT_NEW_ARCH_ENABLED
dispatch_sync(dispatch_get_main_queue(), ^{
view = [self.viewRegistry_DEPRECATED viewForReactTag:reactTag];
});
#else
dispatch_sync(dispatch_get_main_queue(), ^{
view = [self.bridge.uiManager viewForReactTag:reactTag];
});
#endif // RCT_NEW_ARCH_ENABLED
return view;
}

#ifdef RCT_NEW_ARCH_ENABLED
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeScreensModuleSpecJSI>(params);
}
#endif

@end
5 changes: 5 additions & 0 deletions ios/RNSScreenStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ NS_ASSUME_NONNULL_BEGIN

- (void)markChildUpdated;
- (void)didUpdateChildren;
- (void)startScreenTransition;
- (void)updateScreenTransition:(double)progress;
- (void)finishScreenTransition:(BOOL)canceled;

@property (nonatomic) BOOL customAnimation;

#ifdef RCT_NEW_ARCH_ENABLED
#else
Expand Down
Loading

0 comments on commit a6b4d8d

Please sign in to comment.