react-native-screens 1.0.0-alpha.2 → 1.0.0-alpha.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +163 -1
  2. package/RNScreens.podspec +24 -0
  3. package/android/build.gradle +17 -10
  4. package/android/src/main/java/com/swmansion/rnscreens/LifecycleHelper.java +4 -8
  5. package/android/src/main/java/com/swmansion/rnscreens/{RNScreenPackage.java → RNScreensPackage.java} +1 -2
  6. package/android/src/main/java/com/swmansion/rnscreens/Screen.java +44 -3
  7. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.java +61 -18
  8. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.java +1 -1
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.java +3 -3
  10. package/ios/RNSScreen.h +2 -0
  11. package/ios/RNSScreen.m +51 -7
  12. package/ios/RNSScreenContainer.h +0 -8
  13. package/ios/RNSScreenContainer.m +93 -24
  14. package/ios/RNScreens.xcodeproj/project.pbxproj +170 -7
  15. package/package.json +11 -6
  16. package/src/screens.d.ts +22 -0
  17. package/src/screens.native.js +120 -0
  18. package/src/screens.web.js +113 -0
  19. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.java +0 -35
  20. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.java +0 -24
  21. package/ios/RNSScreenStack.h +0 -14
  22. package/ios/RNSScreenStack.m +0 -245
  23. package/ios/RNScreens.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  24. package/ios/RNScreens.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  25. package/ios/RNScreens.xcodeproj/project.xcworkspace/xcuserdata/mdk.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  26. package/ios/RNScreens.xcodeproj/xcuserdata/mdk.xcuserdatad/xcschemes/xcschememanagement.plist +0 -24
  27. package/src/screens.js +0 -14
@@ -0,0 +1,113 @@
1
+ import debounce from 'debounce';
2
+ import React from 'react';
3
+ import { Animated, View } from 'react-native';
4
+
5
+ let _shouldUseScreens = true;
6
+
7
+ export function useScreens(shouldUseScreens = true) {
8
+ if (shouldUseScreens) {
9
+ console.warn(
10
+ 'react-native-screens is not fully supported on this platform yet.'
11
+ );
12
+ }
13
+ _shouldUseScreens = shouldUseScreens;
14
+ }
15
+
16
+ export function screensEnabled() {
17
+ return _shouldUseScreens;
18
+ }
19
+
20
+ function isAnimatedValue(value) {
21
+ return value && value.__getValue && value.addListener;
22
+ }
23
+
24
+ function isPropTruthy(prop) {
25
+ let activeValue = prop;
26
+ if (isAnimatedValue(prop)) {
27
+ activeValue = prop.__getValue();
28
+ }
29
+
30
+ return !!activeValue;
31
+ }
32
+
33
+ export class Screen extends React.Component {
34
+ static defaultProps = {
35
+ active: true,
36
+ };
37
+
38
+ listenerId = null;
39
+
40
+ constructor(props) {
41
+ super(props);
42
+
43
+ this._onAnimatedValueUpdated = debounce(this._onAnimatedValueUpdated, 10);
44
+ this._addListener(props.active);
45
+ }
46
+
47
+ componentWillUnmount() {
48
+ this._removeListener(this.props.active);
49
+ }
50
+
51
+ _addListener = possibleListener => {
52
+ if (this.listenerId)
53
+ throw new Error(
54
+ 'Screen: Attempting to observe an animated value while another value is already observed.'
55
+ );
56
+ if (isAnimatedValue(possibleListener)) {
57
+ this.listenerId = possibleListener.addListener(
58
+ this._onAnimatedValueUpdated
59
+ );
60
+ }
61
+ };
62
+
63
+ _removeListener = possibleListener => {
64
+ if (isAnimatedValue(possibleListener)) {
65
+ possibleListener.removeListener(this.listenerId);
66
+ this.listenerId = null;
67
+ }
68
+ };
69
+
70
+ shouldComponentUpdate({ active: nextActive }) {
71
+ const { active } = this.props;
72
+ if (nextActive !== active) {
73
+ this._removeListener(active);
74
+ this._addListener(nextActive);
75
+ this._updateDisplay(isPropTruthy(nextActive));
76
+ return false;
77
+ }
78
+ return true;
79
+ }
80
+
81
+ _onAnimatedValueUpdated = ({ value }) => {
82
+ this._updateDisplay(!!value);
83
+ };
84
+
85
+ _updateDisplay = isActive => {
86
+ if (isActive === undefined) {
87
+ isActive = isPropTruthy(this.props.active);
88
+ }
89
+ const display = isActive ? 'flex' : 'none';
90
+ this.setNativeProps({ style: { display } });
91
+ };
92
+
93
+ setNativeProps = nativeProps => {
94
+ if (this._view) {
95
+ this._view.setNativeProps(nativeProps);
96
+ }
97
+ };
98
+
99
+ _setRef = view => {
100
+ this._view = view;
101
+ this._updateDisplay();
102
+ };
103
+
104
+ render() {
105
+ return <Animated.View {...this.props} ref={this._setRef} />;
106
+ }
107
+ }
108
+
109
+ export const ScreenContainer = View;
110
+
111
+ export const NativeScreen = View;
112
+
113
+ export const NativeScreenContainer = View;
@@ -1,35 +0,0 @@
1
- package com.swmansion.rnscreens;
2
-
3
- import android.content.Context;
4
-
5
- import java.util.List;
6
-
7
- public class ScreenStack extends ScreenContainer {
8
-
9
- private float mTransitioning;
10
-
11
- public ScreenStack(Context context) {
12
- super(context);
13
- }
14
-
15
- public void setTransitioning(float transitioning) {
16
- if (transitioning != mTransitioning) {
17
- mTransitioning = transitioning;
18
- markUpdated();
19
- }
20
- }
21
-
22
- @Override
23
- protected boolean isScreenActive(Screen screen, List<Screen> allScreens) {
24
- int size = allScreens.size();
25
- if (size < 1) {
26
- return false;
27
- }
28
- Screen lastScreen = allScreens.get(size - 1);
29
- if (mTransitioning != 0 && size > 1) {
30
- Screen secondToLast = allScreens.get(size - 2);
31
- return screen == lastScreen || screen == secondToLast;
32
- }
33
- return screen == lastScreen;
34
- }
35
- }
@@ -1,24 +0,0 @@
1
- package com.swmansion.rnscreens;
2
-
3
- import com.facebook.react.uimanager.ThemedReactContext;
4
- import com.facebook.react.uimanager.annotations.ReactProp;
5
-
6
- public class ScreenStackViewManager extends ScreenContainerViewManager {
7
-
8
- protected static final String REACT_CLASS = "RNSScreenStack";
9
-
10
- @Override
11
- public String getName() {
12
- return REACT_CLASS;
13
- }
14
-
15
- @Override
16
- protected ScreenContainer createViewInstance(ThemedReactContext reactContext) {
17
- return new ScreenStack(reactContext);
18
- }
19
-
20
- @ReactProp(name = "transitioning", defaultFloat = 0)
21
- public void setTransitioning(ScreenStack view, float transitioning) {
22
- view.setTransitioning(transitioning);
23
- }
24
- }
@@ -1,14 +0,0 @@
1
- #import <React/RCTViewManager.h>
2
- #import <React/RCTUIManagerObserverCoordinator.h>
3
- #import "RNSScreenContainer.h"
4
-
5
- @interface RNSScreenStackView : UIView <RNSScreenContainerDelegate>
6
-
7
- - (void)markChildUpdated;
8
- - (void)didUpdateChildren;
9
-
10
- @end
11
-
12
- @interface RNSScreenStackManager : RCTViewManager
13
-
14
- @end
@@ -1,245 +0,0 @@
1
- #import "RNSScreenStack.h"
2
- #import "RNSScreen.h"
3
-
4
- #import <React/RCTBridge.h>
5
- #import <React/RCTUIManager.h>
6
- #import <React/RCTUIManagerUtils.h>
7
-
8
- @interface RNSCustomAnimator : NSObject <UIViewControllerAnimatedTransitioning>
9
-
10
- @property (nonatomic) BOOL presenting;
11
-
12
- @end
13
-
14
- @implementation RNSCustomAnimator
15
-
16
- - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
17
- {
18
- UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
19
- UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
20
-
21
- UIView *container = transitionContext.containerView;
22
- if (_presenting) {
23
- [container addSubview:toView];
24
- toView.alpha = 0.99;
25
- } else {
26
- [container insertSubview:toView belowSubview:fromView];
27
- }
28
-
29
- // When view is added to UINavController it flattens view's translation into frame and makes it
30
- // so that the view with translation applied is centered. We often don't want that as we want the
31
- // view to animated from side. In order to achieve this we reset the translation applied to the
32
- // view such that the frame is at point 0,0 and translation adds an offset from that position.
33
- CATransform3D origTransform = toView.layer.transform;
34
- toView.transform = CGAffineTransformIdentity;
35
- toView.frame = CGRectMake(0, 0, toView.frame.size.width, toView.frame.size.height);
36
- toView.layer.transform = origTransform;
37
-
38
- [UIView
39
- animateWithDuration:[self transitionDuration:transitionContext]
40
- animations:^{
41
- // We need to animate at least one property, otherwise the interactive animation wouldn't
42
- // behave as expected. I haven't had enough time to investigate and hence as a workaround
43
- // we are animating alpha from 1 to 0.99
44
- if (_presenting) {
45
- toView.alpha = 1.0;
46
- } else {
47
- fromView.alpha = 0.99;
48
- }
49
- } completion:^(BOOL finished) {
50
- BOOL success = !transitionContext.transitionWasCancelled;
51
- if (!success) {
52
- [toView removeFromSuperview];
53
- }
54
- [transitionContext completeTransition:success];
55
- }];
56
- }
57
-
58
- - (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
59
- {
60
- // as long as it is non-zero it does not matter what value is here, we turn animation into
61
- // "interactive" mode anyways which make it be controlled by "progress" property anyways.
62
- return 0.1;
63
- }
64
-
65
- @end
66
-
67
- @interface RNSScreenStackView () <UINavigationControllerDelegate>
68
-
69
- @property (nonatomic) NSInteger transitioning;
70
- @property (nonatomic) CGFloat progress;
71
-
72
- @end
73
-
74
- @implementation RNSScreenStackView {
75
- BOOL _needUpdate;
76
- BOOL _transitioningStateChanged;
77
- UINavigationController *_controller;
78
- NSMutableSet<RNSScreenView *> *_activeScreens;
79
- NSMutableArray<RNSScreenView *> *_reactSubviews;
80
- UIPercentDrivenInteractiveTransition *_interactor;
81
- __weak RNSScreenStackManager *_manager;
82
- }
83
-
84
- - (instancetype)initWithManager:(RNSScreenStackManager*)manager
85
- {
86
- if (self = [super init]) {
87
- _manager = manager;
88
- _reactSubviews = [NSMutableArray new];
89
- _controller = [[UINavigationController alloc] init];
90
- _controller.navigationBarHidden = YES;
91
- _controller.delegate = self;
92
- _needUpdate = NO;
93
- [self addSubview:_controller.view];
94
- }
95
- return self;
96
- }
97
-
98
- - (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
99
- interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
100
- {
101
- return _interactor;
102
- }
103
-
104
- - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
105
- animationControllerForOperation:(UINavigationControllerOperation)operation
106
- fromViewController:(UIViewController *)fromVC
107
- toViewController:(UIViewController *)toVC
108
- {
109
- RNSCustomAnimator *animator = [RNSCustomAnimator new];
110
- animator.presenting = _transitioning > 0;
111
- return animator;
112
- }
113
-
114
- - (void)markUpdated
115
- {
116
- // We want 'updateContainer' to be executed on main thread after all enqueued operations in
117
- // uimanager are complete. In order to achieve that we enqueue call on UIManagerQueue from which
118
- // we enqueue call on the main queue. This seems to be working ok in all the cases I've tried but
119
- // there is a chance it is not the correct way to do that.
120
- if (!_needUpdate) {
121
- _needUpdate = YES;
122
- RCTExecuteOnUIManagerQueue(^{
123
- RCTExecuteOnMainQueue(^{
124
- _needUpdate = NO;
125
- [self updateContainer];
126
- });
127
- });
128
- }
129
- }
130
-
131
- - (void)markChildUpdated
132
- {
133
- // do nothing
134
- }
135
-
136
- - (void)didUpdateChildren
137
- {
138
- // do nothing
139
- }
140
-
141
- - (void)setProgress:(CGFloat)progress
142
- {
143
- _progress = progress;
144
- [_interactor updateInteractiveTransition:progress];
145
- }
146
-
147
- - (void)setTransitioning:(NSInteger)transitioning
148
- {
149
- if (_transitioning == transitioning) {
150
- return;
151
- }
152
- _transitioningStateChanged = YES;
153
- _transitioning = transitioning;
154
- [self markUpdated];
155
- }
156
-
157
- - (void)insertReactSubview:(RNSScreenView *)subview atIndex:(NSInteger)atIndex
158
- {
159
- subview.hidden = NO;
160
- subview.reactSuperview = self;
161
- [_reactSubviews insertObject:subview atIndex:atIndex];
162
- [self markUpdated];
163
- }
164
-
165
- - (void)removeReactSubview:(RNSScreenView *)subview
166
- {
167
- // Right after the view gets removed properties such as transform will get reset. In addition to
168
- // that UINavigationController takes a snapshot of the view before it gets completely unmounted.
169
- // This causes an effect in which even so the view are detached from the hierarchy they could still
170
- // be visible for a frame. This is often undesirable e.g. in a case when we want to slide view
171
- // outside of the visible bounds, because as a result it will jump back to position 0,0 right before
172
- // the transition is over. To prevent that we hide the view right before removing it from the subviews
173
- // array.
174
- subview.hidden = YES;
175
- subview.reactSuperview = nil;
176
- [_reactSubviews removeObject:subview];
177
- [self markUpdated];
178
- }
179
-
180
- - (NSArray<UIView *> *)reactSubviews
181
- {
182
- return _reactSubviews;
183
- }
184
-
185
- - (void)didUpdateReactSubviews
186
- {
187
- // do nothing
188
- }
189
-
190
- - (void)updateContainer
191
- {
192
- NSMutableArray<UIViewController *> *controllers = [NSMutableArray new];
193
- for (RNSScreenView *screen in _reactSubviews) {
194
- [controllers addObject:screen.controller];
195
- }
196
- if (_transitioningStateChanged) {
197
- if (_transitioning == 0) {
198
- // finish or cancel transitioning
199
- if ([_controller.viewControllers indexOfObject:controllers.lastObject] != NSNotFound) {
200
- [_interactor finishInteractiveTransition];
201
- } else {
202
- [_interactor cancelInteractiveTransition];
203
- }
204
- _interactor = nil;
205
- } else {
206
- _interactor = [UIPercentDrivenInteractiveTransition new];
207
- if (_transitioning < 0) {
208
- [_controller setViewControllers:controllers animated:NO];
209
- [_controller popViewControllerAnimated:YES];
210
- } else {
211
- UIViewController *lastController = [controllers lastObject];
212
- [controllers removeLastObject];
213
- [_controller setViewControllers:controllers animated:NO];
214
- [_controller pushViewController:lastController animated:YES];
215
- }
216
- }
217
- _transitioningStateChanged = NO;
218
- } else {
219
- [_controller setViewControllers:controllers animated:NO];
220
- }
221
- }
222
-
223
- - (void)layoutSubviews
224
- {
225
- [super layoutSubviews];
226
- [self reactAddControllerToClosestParent:_controller];
227
- _controller.view.frame = self.bounds;
228
- }
229
-
230
- @end
231
-
232
-
233
- @implementation RNSScreenStackManager
234
-
235
- RCT_EXPORT_MODULE()
236
-
237
- RCT_EXPORT_VIEW_PROPERTY(transitioning, NSInteger)
238
- RCT_EXPORT_VIEW_PROPERTY(progress, CGFloat)
239
-
240
- - (UIView *)view
241
- {
242
- return [[RNSScreenStackView alloc] initWithManager:self];
243
- }
244
-
245
- @end
@@ -1,7 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <Workspace
3
- version = "1.0">
4
- <FileRef
5
- location = "self:">
6
- </FileRef>
7
- </Workspace>
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>IDEDidComputeMac32BitWarning</key>
6
- <true/>
7
- </dict>
8
- </plist>
@@ -1,24 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>SchemeUserState</key>
6
- <dict>
7
- <key>RNReanimated.xcscheme</key>
8
- <dict>
9
- <key>orderHint</key>
10
- <integer>0</integer>
11
- </dict>
12
- <key>RNSScreen.xcscheme</key>
13
- <dict>
14
- <key>orderHint</key>
15
- <integer>0</integer>
16
- </dict>
17
- <key>RNScreens.xcscheme</key>
18
- <dict>
19
- <key>orderHint</key>
20
- <integer>37</integer>
21
- </dict>
22
- </dict>
23
- </dict>
24
- </plist>
package/src/screens.js DELETED
@@ -1,14 +0,0 @@
1
- import { Animated, requireNativeComponent } from 'react-native';
2
-
3
- export const Screen = Animated.createAnimatedComponent(
4
- requireNativeComponent('RNSScreen', null)
5
- );
6
-
7
- export const ScreenContainer = requireNativeComponent(
8
- 'RNSScreenContainer',
9
- null
10
- );
11
-
12
- export const ScreenStack = Animated.createAnimatedComponent(
13
- requireNativeComponent('RNSScreenStack', null)
14
- );