@lodev09/react-native-true-sheet 3.8.0-beta.3 → 3.8.0-beta.4

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.
@@ -25,6 +25,7 @@
25
25
 
26
26
  @implementation TrueSheetViewController {
27
27
  CGFloat _lastPosition;
28
+ CGFloat _lastWidth;
28
29
  NSInteger _pendingDetentIndex;
29
30
  BOOL _pendingContentSizeChange;
30
31
  BOOL _pendingDetentsChange;
@@ -211,6 +212,7 @@
211
212
  dispatch_async(dispatch_get_main_queue(), ^{
212
213
  NSInteger index = [self currentDetentIndex];
213
214
  CGFloat detent = [self detentValueForIndex:index];
215
+ [self.delegate viewControllerDidChangeSize:self.view.frame.size];
214
216
  [self.delegate viewControllerDidPresentAtIndex:index position:self.currentPosition detent:detent];
215
217
  [self.delegate viewControllerDidFocus];
216
218
 
@@ -288,7 +290,12 @@
288
290
  - (void)viewDidLayoutSubviews {
289
291
  [super viewDidLayoutSubviews];
290
292
 
291
- [self.delegate viewControllerDidChangeSize:self.view.frame.size];
293
+ // Update state on rotation (width change)
294
+ CGFloat width = self.view.frame.size.width;
295
+ if (_lastWidth != width) {
296
+ _lastWidth = width;
297
+ [self.delegate viewControllerDidChangeSize:self.view.frame.size];
298
+ }
292
299
 
293
300
  if (_pendingDetentIndex >= 0) {
294
301
  NSInteger pendingIndex = _pendingDetentIndex;
@@ -297,6 +304,7 @@
297
304
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
298
305
  [self storeResolvedPositionForIndex:pendingIndex];
299
306
  CGFloat detent = [self detentValueForIndex:pendingIndex];
307
+ [self.delegate viewControllerDidChangeSize:self.view.frame.size];
300
308
  [self.delegate viewControllerDidChangeDetent:pendingIndex position:self.currentPosition detent:detent];
301
309
  [self emitChangePositionDelegateWithPosition:self.currentPosition realtime:NO debug:@"pending detent change"];
302
310
  });
@@ -735,6 +743,7 @@
735
743
  NSInteger index = self.currentDetentIndex;
736
744
  if (index >= 0) {
737
745
  CGFloat detent = [self detentValueForIndex:index];
746
+ [self.delegate viewControllerDidChangeSize:self.view.frame.size];
738
747
  [self.delegate viewControllerDidChangeDetent:index position:self.currentPosition detent:detent];
739
748
  }
740
749
  });
@@ -19,15 +19,21 @@ using namespace facebook::react;
19
19
  @implementation RNScreensEventObserver {
20
20
  std::weak_ptr<const EventDispatcher> _eventDispatcher;
21
21
  std::shared_ptr<const EventListener> _eventListener;
22
+ NSInteger _presenterScreenTag;
22
23
  NSMutableSet<NSNumber *> *_screenTags;
23
24
  __weak UIViewController *_presenterScreenController;
25
+ __weak UIViewController *_parentScreenController;
26
+ __weak UIWindow *_window;
24
27
  BOOL _dismissedByNavigation;
25
28
  }
26
29
 
27
30
  - (instancetype)init {
28
31
  if (self = [super init]) {
32
+ _presenterScreenTag = 0;
29
33
  _screenTags = [NSMutableSet new];
30
34
  _presenterScreenController = nil;
35
+ _parentScreenController = nil;
36
+ _window = nil;
31
37
  }
32
38
  return self;
33
39
  }
@@ -56,9 +62,11 @@ using namespace facebook::react;
56
62
  Tag screenTag = family->getTag();
57
63
 
58
64
  if (event.type == "topWillDisappear") {
59
- if ([strongSelf shouldDismissForScreenTag:screenTag]) {
60
- strongSelf->_dismissedByNavigation = YES;
61
- [strongSelf.delegate presenterScreenWillDisappear];
65
+ if ([strongSelf->_screenTags containsObject:@(screenTag)]) {
66
+ if ([strongSelf shouldDismissForScreenTag:screenTag]) {
67
+ strongSelf->_dismissedByNavigation = YES;
68
+ [strongSelf.delegate presenterScreenWillDisappear];
69
+ }
62
70
  }
63
71
  } else if (event.type == "topWillAppear") {
64
72
  if ([strongSelf->_screenTags containsObject:@(screenTag)] && strongSelf->_dismissedByNavigation) {
@@ -85,40 +93,68 @@ using namespace facebook::react;
85
93
  }
86
94
 
87
95
  - (void)capturePresenterScreenFromView:(UIView *)view {
96
+ _presenterScreenTag = 0;
88
97
  [_screenTags removeAllObjects];
89
98
  _presenterScreenController = nil;
99
+ _parentScreenController = nil;
100
+ _window = view.window;
90
101
 
91
102
  for (UIView *current = view.superview; current; current = current.superview) {
92
103
  if ([NSStringFromClass([current class]) isEqualToString:@"RNSScreenView"]) {
93
104
  [_screenTags addObject:@(current.tag)];
94
105
 
95
- // Capture the view controller from the first (immediate presenter) screen
96
- if (!_presenterScreenController) {
97
- for (UIResponder *r = current.nextResponder; r; r = r.nextResponder) {
98
- if ([r isKindOfClass:[UIViewController class]]) {
99
- _presenterScreenController = (UIViewController *)r;
100
- break;
101
- }
106
+ UIViewController *screenVC = nil;
107
+ for (UIResponder *r = current.nextResponder; r; r = r.nextResponder) {
108
+ if ([r isKindOfClass:[UIViewController class]]) {
109
+ screenVC = (UIViewController *)r;
110
+ break;
102
111
  }
103
112
  }
113
+
114
+ if (!_presenterScreenController) {
115
+ _presenterScreenTag = current.tag;
116
+ _presenterScreenController = screenVC;
117
+ } else if (!_parentScreenController && screenVC) {
118
+ _parentScreenController = screenVC;
119
+ }
104
120
  }
105
121
  }
106
122
  }
107
123
 
108
124
  - (BOOL)shouldDismissForScreenTag:(NSInteger)screenTag {
109
- if (![_screenTags containsObject:@(screenTag)]) {
125
+ // For parent screens (not immediate presenter), check if the presenter screen is being removed
126
+ // This handles nested stack removal case
127
+ if (screenTag != _presenterScreenTag) {
128
+ UINavigationController *parentNav = _parentScreenController.navigationController;
129
+
130
+ // Modal case: parent's nav is presented -> let sheet dismiss naturally
131
+ // Nested stack case: parent's nav is not presented (embedded) -> need to dismiss
132
+ if (parentNav.presentingViewController != nil) {
133
+ return NO;
134
+ }
135
+
136
+ if (!_parentScreenController) {
137
+ return NO;
138
+ }
139
+
140
+ // If presenter view is no longer in window, the nested stack is being removed
141
+ UIView *presenterView = [_window viewWithTag:_presenterScreenTag];
142
+ if (presenterView == nil || presenterView.window == nil) {
143
+ return YES;
144
+ }
145
+
110
146
  return NO;
111
147
  }
112
148
 
149
+ // For immediate presenter screen
113
150
  UINavigationController *navController = _presenterScreenController.navigationController;
114
151
 
115
- // If nav controller is nil or being dismissed, dismiss the sheet
116
152
  if (!navController || navController.isBeingDismissed) {
117
153
  return YES;
118
154
  }
119
155
 
120
- // Skip if screen is still top of nav stack (e.g. modal dismiss - sheet dismisses naturally with modal)
121
- // Dismiss if a new screen was pushed or popped
156
+ // Dismiss if presenter is no longer top of nav stack (pushed/popped)
157
+ // Skip if still top (e.g. modal dismiss - sheet dismisses naturally)
122
158
  return navController.topViewController != _presenterScreenController;
123
159
  }
124
160
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodev09/react-native-true-sheet",
3
- "version": "3.8.0-beta.3",
3
+ "version": "3.8.0-beta.4",
4
4
  "description": "The true native bottom sheet experience for your React Native Apps.",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./lib/module/index.js",
@@ -56,7 +56,7 @@
56
56
  "clean": "scripts/clean.sh",
57
57
  "prepare": "bob build",
58
58
  "release": "release-it",
59
- "release:beta": "yarn release --preRelease=beta"
59
+ "release:beta": "yarn release --preRelease=beta --no-github.release"
60
60
  },
61
61
  "keywords": [
62
62
  "react-native",
@@ -178,7 +178,8 @@
178
178
  "release-it": {
179
179
  "git": {
180
180
  "commitMessage": "chore: release ${version}",
181
- "tagName": "v${version}"
181
+ "tagName": "v${version}",
182
+ "tagExclude": "*-beta*"
182
183
  },
183
184
  "npm": {
184
185
  "publish": false