Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

[AUD-1889] Fix notification drawer swipes on tab screens #1209

Merged
merged 4 commits into from
Apr 14, 2022
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
19 changes: 19 additions & 0 deletions packages/mobile/patches/@react-navigation+drawer+6.3.1.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
diff --git a/node_modules/@react-navigation/drawer/src/views/legacy/Drawer.tsx b/node_modules/@react-navigation/drawer/src/views/legacy/Drawer.tsx
index bebfcbf..0211168 100644
--- a/node_modules/@react-navigation/drawer/src/views/legacy/Drawer.tsx
+++ b/node_modules/@react-navigation/drawer/src/views/legacy/Drawer.tsx
@@ -530,7 +530,13 @@ export default class DrawerView extends React.Component<DrawerProps> {
return (
<DrawerProgressContext.Provider value={progress}>
<PanGestureHandler
- activeOffsetX={[-SWIPE_DISTANCE_MINIMUM, SWIPE_DISTANCE_MINIMUM]}
+ // When the drawer is closed, allow swipe open.
+ // When the drawer is open, allow swipe closed.
+ activeOffsetX={
+ isOpen
+ ? [-SWIPE_DISTANCE_MINIMUM, Number.MAX_SAFE_INTEGER]
+ : [-1 * Number.MAX_SAFE_INTEGER, SWIPE_DISTANCE_MINIMUM]
+ }
failOffsetY={[-SWIPE_DISTANCE_MINIMUM, SWIPE_DISTANCE_MINIMUM]}
onGestureEvent={this.handleGestureEvent}
onHandlerStateChange={this.handleGestureStateChange}
12 changes: 10 additions & 2 deletions packages/mobile/patches/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,16 @@ This directory contains patch files generated by [patch-package](https://www.npm

## react-native-pager-view+5.4.6.patch

Patch to support full screen swipe gestures in native stack. See https://github.com/callstack/react-native-pager-view/pull/500
Patch to support full screen swipe gestures in native stack and navigation drawers and their interplay with material top tabs. See https://github.com/callstack/react-native-pager-view/pull/500

## react-native-screens+3.13.0.patch

Patch to support full screen swipe gestures in native stack. See https://github.com/callstack/react-native-pager-view/pull/500
Patch to support full screen swipe gestures in native stack and navigation drawers and their interplay with material top tabs. See https://github.com/callstack/react-native-pager-view/pull/500

## @react-navigation+drawer+6.3.1.patch

Patch to support full screen swipe gestures in native stack. and navigation drawers and their interplay with material top tabs.See https://github.com/callstack/react-native-pager-view/pull/500

## react-native-gesture-handler+1.10.3.patch

Patch to support full screen swipe gestures in native stack. and navigation drawers and their interplay with material top tabs.See https://github.com/callstack/react-native-pager-view/pull/500
55 changes: 55 additions & 0 deletions packages/mobile/patches/react-native-gesture-handler+1.10.3.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
diff --git a/node_modules/react-native-gesture-handler/ios/RNGestureHandler.h b/node_modules/react-native-gesture-handler/ios/RNGestureHandler.h
index f952c15..2f4e9bd 100644
--- a/node_modules/react-native-gesture-handler/ios/RNGestureHandler.h
+++ b/node_modules/react-native-gesture-handler/ios/RNGestureHandler.h
@@ -55,6 +55,7 @@ if (value != nil) recognizer.prop = [RCTConvert type:value]; \
@property (nonatomic, readonly, nullable) UIGestureRecognizer *recognizer;
@property (nonatomic) BOOL enabled;
@property(nonatomic) BOOL shouldCancelWhenOutside;
+@property (nonatomic) BOOL frozen;

- (void)bindToView:(nonnull UIView *)view;
- (void)unbindFromView;
@@ -69,5 +70,7 @@ if (value != nil) recognizer.prop = [RCTConvert type:value]; \
forViewWithTag:(nonnull NSNumber *)reactTag
withExtraData:(RNGestureHandlerEventExtraData *)extraData;

++ (NSHashTable<RNGestureHandler *> *)getGestureHandlers;
+
@end

diff --git a/node_modules/react-native-gesture-handler/ios/RNGestureHandler.m b/node_modules/react-native-gesture-handler/ios/RNGestureHandler.m
index 998c059..b239ba7 100644
--- a/node_modules/react-native-gesture-handler/ios/RNGestureHandler.m
+++ b/node_modules/react-native-gesture-handler/ios/RNGestureHandler.m
@@ -73,6 +73,7 @@ - (instancetype)initWithTag:(NSNumber *)tag
_tag = tag;
_lastState = RNGestureHandlerStateUndetermined;
_hitSlop = RNGHHitSlopEmpty;
+ _frozen = NO;

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
@@ -132,8 +133,10 @@ - (void)configure:(NSDictionary *)config

- (void)setEnabled:(BOOL)enabled
{
- _enabled = enabled;
- self.recognizer.enabled = enabled;
+ if (_frozen == NO) {
+ _enabled = enabled;
+ self.recognizer.enabled = enabled;
+ }
}

- (void)bindToView:(UIView *)view
@@ -341,4 +344,9 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceive
return YES;
}

++ (NSHashTable<RNGestureHandler *> *)getGestureHandlers
+{
+ return allGestureHandlers;
+}
+
@end
158 changes: 150 additions & 8 deletions packages/mobile/patches/react-native-pager-view+5.4.6.patch
Original file line number Diff line number Diff line change
@@ -1,44 +1,186 @@
diff --git a/node_modules/react-native-pager-view/ios/ReactNativePageView.h b/node_modules/react-native-pager-view/ios/ReactNativePageView.h
index f7f31a5..c6a0356 100644
--- a/node_modules/react-native-pager-view/ios/ReactNativePageView.h
+++ b/node_modules/react-native-pager-view/ios/ReactNativePageView.h
@@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, copy) RCTDirectEventBlock onPageScrollStateChanged;
@property(nonatomic) BOOL overdrag;
@property(nonatomic) NSString* layoutDirection;
-
+@property(nonatomic) NSUInteger previousNavigationStackCount;

- (void)goTo:(NSInteger)index animated:(BOOL)animated;
- (void)shouldScroll:(BOOL)scrollEnabled;
diff --git a/node_modules/react-native-pager-view/ios/ReactNativePageView.m b/node_modules/react-native-pager-view/ios/ReactNativePageView.m
index 78f266b..cc094a3 100644
index 78f266b..b3a2585 100644
--- a/node_modules/react-native-pager-view/ios/ReactNativePageView.m
+++ b/node_modules/react-native-pager-view/ios/ReactNativePageView.m
@@ -83,6 +83,16 @@ - (void)didMoveToWindow {
@@ -3,6 +3,7 @@
#import "React/RCTLog.h"
#import <React/RCTViewManager.h>

+#import "RNGestureHandler.h"
#import "UIViewController+CreateExtension.h"
#import "RCTOnPageScrollEvent.h"
#import "RCTOnPageScrollStateChanged.h"
@@ -47,6 +48,7 @@ - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher {
_cachedControllers = [NSHashTable weakObjectsHashTable];
_overdrag = NO;
_layoutDirection = @"ltr";
+ _previousNavigationStackCount = 1;
}
return self;
}
@@ -83,6 +85,59 @@ - (void)didMoveToWindow {
[self embed];
[self setupInitialController];
}
+
+ if (self.reactViewController.navigationController != nil) {
+ for (UIGestureRecognizer *recognizer in self.reactViewController.navigationController.view.gestureRecognizers) {
+ [self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:recognizer];
+ NSUInteger count = [self.reactViewController.navigationController.viewControllers count];
+
+ if (count >= _previousNavigationStackCount) {
+ // We are pushing to the stack, always enable the stack navigator
+ for (UIGestureRecognizer *recognizer in self.reactViewController.navigationController.view.gestureRecognizers) {
+ recognizer.enabled = YES;
+ }
+ } else {
+ // We are popping from the stack, only enable stack if we're on the first tab
+ if (self.currentIndex == 0) {
+ for (UIGestureRecognizer *recognizer in self.reactViewController.navigationController.view.gestureRecognizers) {
+ recognizer.enabled = YES;
+ }
+ } else {
+ for (UIGestureRecognizer *recognizer in self.reactViewController.navigationController.view.gestureRecognizers) {
+ // Do not disable the gesture immediately as the window is popping.
+ NSTimeInterval delayInSeconds = 0.1;
+ dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
+ dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
+ recognizer.enabled = NO;
+ });
+ }
+ }
+ }
+
+ if (self.currentIndex == 0) {
+ // On the first tab, we want to listen to the drawer's gestures, so
+ // swiping it open works.
+ NSHashTable<RNGestureHandler *> *handlers = [RNGestureHandler getGestureHandlers];
+ NSEnumerator *enumerator = [handlers objectEnumerator];
+ RNGestureHandler* handler;
+ while ((handler = [enumerator nextObject])) {
+ handler.recognizer.enabled = YES;
+ handler.frozen = NO;
+ [self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:handler.recognizer];
+ }
+ } else {
+ // On the other tabs tab, we should disable the drawer's gestures.
+ NSHashTable<RNGestureHandler *> *handlers = [RNGestureHandler getGestureHandlers];
+ NSEnumerator *enumerator = [handlers objectEnumerator];
+ RNGestureHandler* handler;
+ while ((handler = [enumerator nextObject])) {
+ handler.recognizer.enabled = NO;
+ handler.frozen = YES;
+ }
+ }
+ }
+
+ // Disable tab swipes when the stack navigator receives a "pop" gesture
+ if (self.reactViewController.navigationController != nil && self.reactViewController.navigationController.interactivePopGestureRecognizer != nil) {
+ [self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:self.reactViewController.navigationController.interactivePopGestureRecognizer];
+ }
}

- (void)embed {
@@ -333,6 +343,23 @@ - (void)pageViewController:(UIPageViewController *)pageViewController
@@ -191,6 +246,42 @@ - (void)setReactViewControllers:(NSInteger)index
strongSelf.lastReportedIndex = strongSelf.currentIndex;
}
}
+
+ if (self.reactViewController.navigationController != nil) {
+ if (strongSelf.currentIndex == 0) {
+ // On the first tab, we want to listen to the navigation's gestures, so
+ // swipe back works.
+ for (UIGestureRecognizer *recognizer in self.reactViewController.navigationController.view.gestureRecognizers) {
+ recognizer.enabled = YES;
+ [self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:recognizer];
+ }
+
+ // On the first tab, we want to listen to the drawer's gestures, so
+ // swiping it open works.
+ NSHashTable<RNGestureHandler *> *handlers = [RNGestureHandler getGestureHandlers];
+ NSEnumerator *enumerator = [handlers objectEnumerator];
+ RNGestureHandler* handler;
+ while ((handler = [enumerator nextObject])) {
+ handler.recognizer.enabled = YES;
+ handler.frozen = NO;
+ [self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:handler.recognizer];
+ }
+ } else {
+ // On other tabs, we should disable the navigations's gestures
+ for (UIGestureRecognizer *recognizer in self.reactViewController.navigationController.view.gestureRecognizers) {
+ recognizer.enabled = NO;
+ }
+
+ // On the other tabs tab, we should disable the drawer's gestures.
+ NSHashTable<RNGestureHandler *> *handlers = [RNGestureHandler getGestureHandlers];
+ NSEnumerator *enumerator = [handlers objectEnumerator];
+ RNGestureHandler* handler;
+ while ((handler = [enumerator nextObject])) {
+ handler.recognizer.enabled = NO;
+ handler.frozen = YES;
+ }
+ }
+ }
}];
}

@@ -322,7 +413,6 @@ - (void)pageViewController:(UIPageViewController *)pageViewController
didFinishAnimating:(BOOL)finished
previousViewControllers:(nonnull NSArray<UIViewController *> *)previousViewControllers
transitionCompleted:(BOOL)completed {
-
if (completed) {
UIViewController* currentVC = [self currentlyDisplayed];
NSUInteger currentIndex = [self.reactSubviews indexOfObject:currentVC.view];
@@ -333,6 +423,42 @@ - (void)pageViewController:(UIPageViewController *)pageViewController
[self.eventDispatcher sendEvent:[[RCTOnPageSelected alloc] initWithReactTag:self.reactTag position:@(currentIndex) coalescingKey:_coalescingKey++]];
[self.eventDispatcher sendEvent:[[RCTOnPageScrollEvent alloc] initWithReactTag:self.reactTag position:@(currentIndex) offset:@(0.0)]];
self.lastReportedIndex = currentIndex;
+
+ if (self.reactViewController.navigationController != nil) {
+ if (currentIndex == 0) {
+ if (self.currentIndex == 0) {
+ // On the first tab, we want to listen to the navigation's gestures, so
+ // swipe back works.
+ for (UIGestureRecognizer *recognizer in self.reactViewController.navigationController.view.gestureRecognizers) {
+ recognizer.enabled = YES;
+ [self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:recognizer];
+ }
+
+ // On the first tab, we want to listen to the drawer's gestures, so
+ // swiping it open works.
+ NSHashTable<RNGestureHandler *> *handlers = [RNGestureHandler getGestureHandlers];
+ NSEnumerator *enumerator = [handlers objectEnumerator];
+ RNGestureHandler* handler;
+ while ((handler = [enumerator nextObject])) {
+ handler.recognizer.enabled = YES;
+ handler.frozen = NO;
+ [self.scrollView.panGestureRecognizer requireGestureRecognizerToFail:handler.recognizer];
+ }
+ } else {
+ // On other tabs, we should disable the navigations's gestures
+ for (UIGestureRecognizer *recognizer in self.reactViewController.navigationController.view.gestureRecognizers) {
+ recognizer.enabled = NO;
+ }
+ }
+
+ // On the other tabs tab, we should disable the drawer's gestures.
+ NSHashTable<RNGestureHandler *> *handlers = [RNGestureHandler getGestureHandlers];
+ NSEnumerator *enumerator = [handlers objectEnumerator];
+ RNGestureHandler* handler;
+ while ((handler = [enumerator nextObject])) {
+ handler.recognizer.enabled = NO;
+ handler.frozen = YES;
+ }
+ }
+ }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,7 @@ export const useAppScreenOptions = () => {
styles,
neutralLight4,
accentOrangeLight1,
notificationCount,
goBack
notificationCount
]
)

Expand Down