Skip to content
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
76 changes: 70 additions & 6 deletions .yarn/patches/react-native-screens-npm-4.18.0-fa7de65975.patch
Original file line number Diff line number Diff line change
@@ -1,19 +1,62 @@
diff --git a/ios/RNSScreen.mm b/ios/RNSScreen.mm
index 65c18f1ddccc64b3169e050e577eab77fd8c183b..8ffd9d4b48f85e53c6fcf0a76963cfcf946dad97 100644
--- a/ios/RNSScreen.mm
+++ b/ios/RNSScreen.mm
@@ -605,6 +605,11 @@
- (void)notifyWillDisappear
{
@@ -38,6 +38,7 @@
#import "RNSTabBarController.h"

#import "RNSDefines.h"
+#import "integrations/RNSLifecycleListenerProtocol.h"
#import "UIView+RNSUtility.h"

#ifdef RCT_NEW_ARCH_ENABLED
@@ -74,6 +75,7 @@ struct ContentWrapperBox {
ContentWrapperBox _contentWrapperBox;
bool _sheetHasInitialDetentSet;
BOOL _shouldUpdateScrollEdgeEffects;
+ RNSScreen *_controllerBeforeInvalidate;
#ifdef RCT_NEW_ARCH_ENABLED
RCTSurfaceTouchHandler *_touchHandler;
react::RNSScreenShadowNode::ConcreteState::Shared _state;
@@ -608,6 +610,26 @@ RNS_IGNORE_SUPER_CALL_END
if (_hideKeyboardOnSwipe) {
[self endEditing:YES];
}
+
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"RNSScreenViewWillDisappear"
+ object:self
+ userInfo:nil];
+ // Notify any presented view controllers that conform to RNSLifecycleListenerProtocol
+ RNSScreen *controller = _controller ?: _controllerBeforeInvalidate;
+ if (controller) {
+ UIViewController *presented = controller.presentedViewController;
+ while (presented) {
+ UIViewController *next = presented.presentedViewController;
+ if ([presented conformsToProtocol:@protocol(RNSLifecycleListenerProtocol)]) {
+ BOOL isPresenterUnmounting = NO;
+ RNSScreen *presenter = (RNSScreen *)presented.presentingViewController;
+ if ([presenter isKindOfClass:[RNSScreen class]]) {
+ isPresenterUnmounting = presenter.screenView.isMarkedForUnmountInCurrentTransaction;
+ }
+ [(id<RNSLifecycleListenerProtocol>)presented screenWillDisappear:controller
+ isPresenterUnmounting:isPresenterUnmounting];
+ }
+ presented = next;
+ }
+ }
+
#ifdef RCT_NEW_ARCH_ENABLED
// If screen is already unmounted then there will be no event emitter
if (_eventEmitter != nullptr) {
@@ -927,6 +949,9 @@ RNS_IGNORE_SUPER_CALL_END

- (void)invalidate
{
+ if (_controller && !_controllerBeforeInvalidate) {
+ _controllerBeforeInvalidate = _controller;
+ }
_controller = nil;
[_sheetsScrollView removeObserver:self forKeyPath:@"bounds" context:nil];
}
diff --git a/ios/RNSScreenStack.mm b/ios/RNSScreenStack.mm
index 51f021831aed26a4eed3c85014020423b7b3108b..268fa69dfee2b20d8b5a66c77c1b4cbd8c831573 100644
--- a/ios/RNSScreenStack.mm
+++ b/ios/RNSScreenStack.mm
@@ -640,8 +640,10 @@ RNS_IGNORE_SUPER_CALL_END
Expand Down Expand Up @@ -64,6 +107,7 @@ diff --git a/ios/RNSScreenStack.mm b/ios/RNSScreenStack.mm

// We didn't detect any controllers for dismissal, thus we start presenting new VCs
diff --git a/ios/integrations/RNSDismissibleModalProtocol.h b/ios/integrations/RNSDismissibleModalProtocol.h
index 006f809d104c1d4fbdf6eccca89d6c6e190cca71..89e297f1b7a9582fee3e19237dfba8d4c87a352f 100644
--- a/ios/integrations/RNSDismissibleModalProtocol.h
+++ b/ios/integrations/RNSDismissibleModalProtocol.h
@@ -1,3 +1,5 @@
Expand All @@ -86,3 +130,23 @@ diff --git a/ios/integrations/RNSDismissibleModalProtocol.h b/ios/integrations/R
@end

NS_ASSUME_NONNULL_END
diff --git a/ios/integrations/RNSLifecycleListenerProtocol.h b/ios/integrations/RNSLifecycleListenerProtocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..025b4231c0b45f9f10034280037617b9b6d6fec4
--- /dev/null
+++ b/ios/integrations/RNSLifecycleListenerProtocol.h
@@ -0,0 +1,14 @@
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@protocol RNSLifecycleListenerProtocol <NSObject>
+
+// Called when a screen in the presenting hierarchy is about to disappear.
+// @param screen The screen controller that is disappearing
+// @param isPresenterUnmounting YES if the presenter (modal) itself is being unmounted
+- (void)screenWillDisappear:(UIViewController *)screen isPresenterUnmounting:(BOOL)isPresenterUnmounting;
+
+@end
+
+NS_ASSUME_NONNULL_END
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

### 🐛 Bug fixes

- Fixed sheet not dismissing when presenter screen is popped from navigation. ([#400](https://github.com/lodev09/react-native-true-sheet/pull/400) by [@lodev09](https://github.com/lodev09))
- Fixed sheet not dismissing when presenter screen is popped from navigation. ([#400](https://github.com/lodev09/react-native-true-sheet/pull/400), [#402](https://github.com/lodev09/react-native-true-sheet/pull/402) by [@lodev09](https://github.com/lodev09))
- **iOS**: Fixed position tracking for pending detent changes. ([#394](https://github.com/lodev09/react-native-true-sheet/pull/394) by [@lodev09](https://github.com/lodev09))
- **Android**: Fixed keyboard and focus handling inside RN Modal. ([#387](https://github.com/lodev09/react-native-true-sheet/pull/387) by [@lodev09](https://github.com/lodev09))

Expand Down
6 changes: 3 additions & 3 deletions android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
if (child is TrueSheetContainerView) {
child.delegate = null

// Dismiss the sheet when container is removed
// Dismiss when container is removed
if (viewController.isPresented) {
viewController.dismiss(animated = false)
dismissAll(false) {}
}
}
viewController.removeView(child)
Expand Down Expand Up @@ -476,7 +476,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
eventDispatcher?.dispatchEvent(BackPressEvent(surfaceId, id))
}

override fun viewControllerDidDetectPresenterDismiss() {
override fun viewControllerDidDetectScreenDismiss() {
dismissAll(animated = true) {}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ interface TrueSheetViewControllerDelegate {
fun viewControllerWillBlur()
fun viewControllerDidBlur()
fun viewControllerDidBackPress()
fun viewControllerDidDetectPresenterDismiss()
fun viewControllerDidDetectScreenDismiss()
}

// =============================================================================
Expand Down Expand Up @@ -540,7 +540,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
onNonModalScreenPushed = {
// Only handle on root sheet (no parent) to trigger dismissAll
if (isPresented && isSheetVisible && parentSheetView == null) {
delegate?.viewControllerDidDetectPresenterDismiss()
delegate?.viewControllerDidDetectScreenDismiss()
}
}
)
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/guides/navigation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export default function SheetLayout() {
## Navigating from Sheets

:::note
Requires a [patch to react-native-screens](https://github.com/lodev09/react-native-true-sheet/blob/main/.yarn/patches/react-native-screens-npm-4.18.0-fa7de65975.patch). See [PR #3415](https://github.com/software-mansion/react-native-screens/pull/3415) and [PR #3525](https://github.com/software-mansion/react-native-screens/pull/3525).
Requires a [patch to react-native-screens](https://github.com/lodev09/react-native-true-sheet/blob/main/.yarn/patches/react-native-screens-npm-4.18.0-fa7de65975.patch). See [PR #3415](https://github.com/software-mansion/react-native-screens/pull/3415), [PR #3526](https://github.com/software-mansion/react-native-screens/pull/3526).
:::

Navigate directly from sheets - they remain visible when presenting modals on top.
Expand Down
4 changes: 2 additions & 2 deletions example/bare/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2646,7 +2646,7 @@ PODS:
- ReactCommon/turbomodule/core
- SocketRocket
- Yoga
- RNTrueSheet (3.7.0-beta.3):
- RNTrueSheet (3.7.0):
- boost
- DoubleConversion
- fast_float
Expand Down Expand Up @@ -3095,7 +3095,7 @@ SPEC CHECKSUMS:
RNGestureHandler: e1cf8ef3f11045536eed6bd4f132b003ef5f9a5f
RNReanimated: f1868b36f4b2b52a0ed00062cfda69506f75eaee
RNScreens: d821082c6dd1cb397cc0c98b026eeafaa68be479
RNTrueSheet: 192e3d4a0e32be2f16a06d1f15e939b6e045af2d
RNTrueSheet: 98de027f434047a746fdf797927f2cfeaf84fc84
RNWorklets: d9c050940f140af5d8b611d937eab1cbfce5e9a5
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Yoga: 689c8e04277f3ad631e60fe2a08e41d411daf8eb
Expand Down
7 changes: 6 additions & 1 deletion example/bare/src/navigators/ModalStackNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ const ModalScreenWrapper = () => {
);
};

const TestScreenWrapper = () => {
const navigation = useNavigation<NativeStackNavigationProp<ModalStackParamList>>();
return <TestScreen onGoBack={() => navigation.goBack()} />;
};

export const ModalStackNavigator = () => {
return (
<ModalStack.Navigator
Expand All @@ -27,7 +32,7 @@ export const ModalStackNavigator = () => {
}}
>
<ModalStack.Screen name="Modal" component={ModalScreenWrapper} />
<ModalStack.Screen name="Test" component={TestScreen} />
<ModalStack.Screen name="Test" component={TestScreenWrapper} />
</ModalStack.Navigator>
);
};
3 changes: 1 addition & 2 deletions example/bare/src/navigators/RootNavigator.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createNativeStackNavigator } from '@react-navigation/native-stack';

import { MapScreen, StandardScreen, TestScreen } from '@example/shared/screens';
import { MapScreen, StandardScreen } from '@example/shared/screens';
import { Map } from '@example/shared/components';
import { ModalStackNavigator } from './ModalStackNavigator';
import { SheetNavigator } from './SheetNavigator';
Expand Down Expand Up @@ -50,7 +50,6 @@ export const RootNavigator = () => {
name="Standard"
component={StandardScreenWrapper}
/>
<Stack.Screen name="Test" component={TestScreen} />
<Stack.Screen
name="ModalStack"
component={ModalStackNavigator}
Expand Down
4 changes: 3 additions & 1 deletion example/expo/app/modal/test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { TestScreen } from '@example/shared/screens';
import { useRouter } from 'expo-router';

export default function Test() {
return <TestScreen />;
const router = useRouter();
return <TestScreen onGoBack={() => router.back()} />;
}
8 changes: 6 additions & 2 deletions example/shared/src/screens/TestScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ import { BLUE, GAP, SPACING } from '../utils';
import { Button } from '../components';
import { BasicSheet, PromptSheet, FlatListSheet } from '../components/sheets';

export const TestScreen = () => {
interface TestScreenProps {
onGoBack: () => void;
}

export const TestScreen = ({ onGoBack }: TestScreenProps) => {
const basicSheet = useRef<TrueSheet>(null);
const promptSheet = useRef<TrueSheet>(null);
const flatListSheet = useRef<TrueSheet>(null);

return (
<TrueSheetProvider>
<View style={styles.content}>
<Button text="Back Sheet" onPress={onGoBack} />
<Button text="Basic Sheet" onPress={() => basicSheet.current?.present()} />
<Button text="Prompt Sheet" onPress={() => promptSheet.current?.present()} />
<Button text="FlatList Sheet" onPress={() => flatListSheet.current?.present()} />
Expand All @@ -29,7 +34,6 @@ export const TestScreen = () => {
const styles = StyleSheet.create({
content: {
backgroundColor: BLUE,
justifyContent: 'center',
flex: 1,
padding: SPACING,
gap: GAP,
Expand Down
20 changes: 19 additions & 1 deletion ios/TrueSheetView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ @implementation TrueSheetView {
TrueSheetViewController *_controller;
RCTSurfaceTouchHandler *_touchHandler;
TrueSheetViewShadowNode::ConcreteState::Shared _state;
UIView *_snapshotView;
CGSize _lastStateSize;
NSInteger _initialDetentIndex;
BOOL _scrollable;
Expand All @@ -69,6 +70,7 @@ - (instancetype)initWithFrame:(CGRect)frame {

_touchHandler = [[RCTSurfaceTouchHandler alloc] init];
_containerView = nil;
_snapshotView = nil;
_lastStateSize = CGSizeZero;
_initialDetentIndex = -1;
_initialDetentAnimated = YES;
Expand Down Expand Up @@ -107,6 +109,9 @@ - (void)dealloc {
_controller.delegate = nil;
_controller = nil;

[_snapshotView removeFromSuperview];
_snapshotView = nil;

[TrueSheetModule unregisterViewWithTag:@(self.tag)];
}

Expand Down Expand Up @@ -280,6 +285,11 @@ - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childCompone
return;
}

if (_snapshotView) {
[_snapshotView removeFromSuperview];
_snapshotView = nil;
}

_containerView = (TrueSheetContainerView *)childComponentView;
_containerView.delegate = self;

Expand Down Expand Up @@ -308,6 +318,14 @@ - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childCompo
if (![childComponentView isKindOfClass:[TrueSheetContainerView class]])
return;

UIView *superView = _containerView.superview;
UIView *snapshot = [_containerView snapshotViewAfterScreenUpdates:NO];
if (snapshot) {
snapshot.frame = _containerView.frame;
[superView insertSubview:snapshot belowSubview:_containerView];
_snapshotView = snapshot;
}

_containerView.delegate = nil;

if (_touchHandler) {
Expand Down Expand Up @@ -523,7 +541,7 @@ - (void)viewControllerDidBlur {
[TrueSheetFocusEvents emitDidBlur:_eventEmitter];
}

- (void)viewControllerDidDetectPresenterDismiss {
- (void)viewControllerDidDetectScreenDismiss {
[self dismissAllAnimated:YES completion:nil];
}

Expand Down
16 changes: 15 additions & 1 deletion ios/TrueSheetViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
#define RNS_DISMISSIBLE_MODAL_PROTOCOL_AVAILABLE 0
#endif

#if __has_include(<RNScreens/RNSLifecycleListenerProtocol.h>)
#import <RNScreens/RNSLifecycleListenerProtocol.h>
#define RNS_LIFECYCLE_LISTENER_PROTOCOL_AVAILABLE 1
#else
#define RNS_LIFECYCLE_LISTENER_PROTOCOL_AVAILABLE 0
#endif

NS_ASSUME_NONNULL_BEGIN

@protocol TrueSheetViewControllerDelegate <NSObject>
Expand All @@ -38,7 +45,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)viewControllerDidFocus;
- (void)viewControllerWillBlur;
- (void)viewControllerDidBlur;
- (void)viewControllerDidDetectPresenterDismiss;

#if RNS_LIFECYCLE_LISTENER_PROTOCOL_AVAILABLE
- (void)viewControllerDidDetectScreenDismiss;
#endif

@end

Expand All @@ -47,6 +57,10 @@ NS_ASSUME_NONNULL_BEGIN
#if RNS_DISMISSIBLE_MODAL_PROTOCOL_AVAILABLE
,
RNSDismissibleModalProtocol
#endif
#if RNS_LIFECYCLE_LISTENER_PROTOCOL_AVAILABLE
,
RNSLifecycleListenerProtocol
#endif
>

Expand Down
Loading