Skip to content

Commit 67a4a0f

Browse files
Refactor Redbox, Logbox, and DevLoadingView as Sheets (#2151)
* fix(iOS): adjust RCTRedBox to work for iPad and support orientation changes (facebook#41217) Summary: When opening `RCTRedBox` on an iPad (and also visionOS) there was an issue with buttons width going out of screen. When changing screen orientation, RedBox wasn't recalculating view positions. **Root cause**: Getting frame of root view to display this modal and basing all calculations on it. **Solution**: Use Auto Layout to build UI that responds to orientation changes and device specific modal presentation. I've also tested it with adding custom buttons to RedBox and it works properly. [IOS] [FIXED] - adjust RCTRedBox to work for iPad and support orientation changes Pull Request resolved: facebook#41217 Test Plan: Launch the app without metro running and check out RedBox that's shown there. Also change screen orientation to see proper recalculation of view positions. https://github.com/facebook/react-native/assets/52801365/892dcfe7-246f-4f36-be37-12c139c207ac https://github.com/facebook/react-native/assets/52801365/dfd0c3d8-5997-462d-97ec-dcc3de452e26 Reviewed By: GijsWeterings Differential Revision: D50734569 Pulled By: javache fbshipit-source-id: 51b854a47caf90ae46fcd32c4adcc64ec2ceb63f * refactor: use less verbose API for RCTRedBox constraints (facebook#42261) Summary: This PR is a continuation of my previous PR where I refactored RCTRedBox to use Auto Layout (facebook#41217). This PR uses less verbose API for defining constraints. ## Changelog: [IOS] [CHANGED] - use less verbose Auto Layout API for RCTRedBox constraints Pull Request resolved: facebook#42261 Test Plan: Launch the app without metro enabled to see the RCTRedBox ![CleanShot 2024-01-12 at 14 54 20@2x](https://github.com/facebook/react-native/assets/52801365/32ee9916-3e32-46c3-9f6b-c313631aa1e5) ![CleanShot 2024-01-12 at 14 54 16@2x](https://github.com/facebook/react-native/assets/52801365/c625b9b9-b462-4e67-831f-0192427bbe93) Reviewed By: NickGerleman Differential Revision: D52730458 Pulled By: javache fbshipit-source-id: dc7227e7b6e3238c195342cb0460850b57eb75c3 * refactor Redbox on macOS and present as a sheet * present RCTDevLoadingView as a sheet * refactor Logbox and present as a sheet * change RCTRootView.loadingView to RCTPlatformView * update Podfile.lock * PR feedback --------- Co-authored-by: Oskar Kwaśniewski <[email protected]>
1 parent 042cd6c commit 67a4a0f

File tree

12 files changed

+619
-798
lines changed

12 files changed

+619
-798
lines changed

packages/react-native/React/Base/RCTRootView.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ extern
135135
* with a blank screen. By default this is nil, but you can override it with
136136
* (for example) a UIActivityIndicatorView or a placeholder image.
137137
*/
138-
@property (nonatomic, strong, nullable) RCTUIView *loadingView; // [macOS]
138+
@property (nonatomic, strong, nullable) RCTPlatformView *loadingView; // [macOS]
139139

140140
/**
141141
* When set, any touches on the RCTRootView that are not matched up to any of the child

packages/react-native/React/Base/RCTRootView.m

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -166,20 +166,15 @@ - (void)layoutSubviews
166166
#if !TARGET_OS_OSX // [macOS]
167167
_loadingView.center = (CGPoint){CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)};
168168
#else // [macOS
169-
NSRect bounds = self.bounds;
170-
NSSize loadingViewSize = _loadingView.frame.size;
171-
CGFloat scale = self.window.backingScaleFactor;
172-
if (scale == 0.0 && RCTRunningInTestEnvironment()) {
173-
// When running in the test environment the view is not on screen.
174-
// Use a scaleFactor of 1 so that the test results are machine independent.
175-
scale = 1;
176-
}
177-
RCTAssert(scale != 0.0, @"Layout occurs before the view is in a window?");
178-
179-
_loadingView.frameOrigin = NSMakePoint(
180-
RCTRoundPixelValue(bounds.origin.x + ((bounds.size.width - loadingViewSize.width) / 2), scale),
181-
RCTRoundPixelValue(bounds.origin.y + ((bounds.size.height - loadingViewSize.height) / 2), scale)
169+
CGFloat centerX = CGRectGetMidX(self.bounds);
170+
CGFloat centerY = CGRectGetMidY(self.bounds);
171+
NSRect newFrame = NSMakeRect(
172+
centerX - _loadingView.frame.size.width / 2.0,
173+
centerY - _loadingView.frame.size.height / 2.0,
174+
_loadingView.frame.size.width,
175+
_loadingView.frame.size.height
182176
);
177+
_loadingView.frame = newFrame;
183178
#endif // macOS]
184179
}
185180

packages/react-native/React/Base/RCTUIKit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,9 +526,11 @@ NS_ASSUME_NONNULL_END
526526
#if !TARGET_OS_OSX
527527
typedef UIApplication RCTUIApplication;
528528
typedef UIWindow RCTUIWindow;
529+
typedef UIViewController RCTUIViewController;
529530
#else
530531
typedef NSApplication RCTUIApplication;
531532
typedef NSWindow RCTUIWindow;
533+
typedef NSViewController RCTUIViewController;
532534
#endif
533535

534536
//

packages/react-native/React/Base/macOS/RCTUIKit.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,7 @@ - (void)drawRect:(CGRect)rect
522522

523523
- (void)layout
524524
{
525+
[super layout];
525526
if (self.window != nil) {
526527
[self layoutSubviews];
527528
}

packages/react-native/React/CoreModules/RCTDevLoadingView.mm

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ - (void)showMessage:(NSString *)message color:(RCTUIColor *)color backgroundColo
123123

124124
if (!self->_window && !RCTRunningInTestEnvironment()) {
125125
#if !TARGET_OS_OSX // [macOS]
126-
UIWindow *window = RCTKeyWindow();
126+
UIWindow *window = RCTKeyWindow(); // [macOS]
127127
CGFloat windowWidth = window.bounds.size.width;
128128

129129
self->_window = [[UIWindow alloc] initWithWindowScene:window.windowScene];
@@ -138,8 +138,7 @@ - (void)showMessage:(NSString *)message color:(RCTUIColor *)color backgroundColo
138138
self->_label.font = [UIFont monospacedDigitSystemFontOfSize:12.0 weight:UIFontWeightRegular];
139139
self->_label.textAlignment = NSTextAlignmentCenter;
140140
#else // [macOS
141-
NSRect screenFrame = [NSScreen mainScreen].visibleFrame;
142-
self->_window = [[NSPanel alloc] initWithContentRect:NSMakeRect(screenFrame.origin.x + round((screenFrame.size.width - 375) / 2), screenFrame.size.height - 20, 375, 19)
141+
self->_window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 375, 20)
143142
styleMask:NSWindowStyleMaskBorderless
144143
backing:NSBackingStoreBuffered
145144
defer:YES];
@@ -153,6 +152,7 @@ - (void)showMessage:(NSString *)message color:(RCTUIColor *)color backgroundColo
153152
label.selectable = NO;
154153
label.wantsLayer = YES;
155154
label.layer.cornerRadius = label.frame.size.height / 3;
155+
label.layer.cornerCurve = kCACornerCurveContinuous;
156156
self->_label = label;
157157
[[self->_window contentView] addSubview:label];
158158
#endif // macOS]
@@ -169,7 +169,7 @@ - (void)showMessage:(NSString *)message color:(RCTUIColor *)color backgroundColo
169169
self->_label.textColor = color;
170170

171171
self->_label.backgroundColor = backgroundColor;
172-
[self->_window orderFront:nil];
172+
[RCTKeyWindow() beginSheet:self->_window completionHandler:nil];
173173
#endif // macOS]
174174
});
175175

@@ -195,10 +195,10 @@ - (void)showMessage:(NSString *)message color:(RCTUIColor *)color backgroundColo
195195

196196
dispatch_async(dispatch_get_main_queue(), ^{
197197
self->_hiding = YES;
198+
#if !TARGET_OS_OSX // [macOS]
198199
const NSTimeInterval MIN_PRESENTED_TIME = 0.6;
199200
NSTimeInterval presentedTime = [[NSDate date] timeIntervalSinceDate:self->_showDate];
200201
NSTimeInterval delay = MAX(0, MIN_PRESENTED_TIME - presentedTime);
201-
#if !TARGET_OS_OSX // [macOS]
202202
CGRect windowFrame = self->_window.frame;
203203
[UIView animateWithDuration:0.25
204204
delay:delay
@@ -213,14 +213,7 @@ - (void)showMessage:(NSString *)message color:(RCTUIColor *)color backgroundColo
213213
self->_hiding = false;
214214
}];
215215
#else // [macOS]
216-
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
217-
[NSAnimationContext runAnimationGroup:^(__unused NSAnimationContext *context) {
218-
self->_window.animator.alphaValue = 0.0;
219-
} completionHandler:^{
220-
[self->_window close];
221-
self->_window = nil;
222-
}];
223-
});
216+
[RCTKeyWindow() endSheet:self->_window];
224217
#endif // macOS]
225218
});
226219
}

packages/react-native/React/CoreModules/RCTLogBox.mm

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,27 +55,15 @@ - (void)setSurfacePresenter:(id<RCTSurfacePresenterStub>)surfacePresenter
5555
}
5656

5757
if (strongSelf->_bridgelessSurfacePresenter) {
58-
#if !TARGET_OS_OSX // [macOS]
5958
strongSelf->_view = [[RCTLogBoxView alloc] initWithWindow:RCTKeyWindow()
6059
surfacePresenter:strongSelf->_bridgelessSurfacePresenter];
61-
#else // [macOS
62-
strongSelf->_view = [[RCTLogBoxView alloc] initWithSurfacePresenter:strongSelf->_bridgelessSurfacePresenter];
63-
#endif // macOS]
6460
[strongSelf->_view show];
6561
} else if (strongSelf->_bridge && strongSelf->_bridge.valid) {
6662
if (strongSelf->_bridge.surfacePresenter) {
67-
#if !TARGET_OS_OSX // [macOS]
6863
strongSelf->_view = [[RCTLogBoxView alloc] initWithWindow:RCTKeyWindow()
6964
surfacePresenter:strongSelf->_bridge.surfacePresenter];
70-
#else // [macOS
71-
strongSelf->_view = [[RCTLogBoxView alloc] initWithSurfacePresenter:strongSelf->_bridge.surfacePresenter];
72-
#endif // macOS]
7365
} else {
74-
#if !TARGET_OS_OSX // [macOS]
7566
strongSelf->_view = [[RCTLogBoxView alloc] initWithWindow:RCTKeyWindow() bridge:strongSelf->_bridge];
76-
#else // [macOS
77-
strongSelf->_view = [[RCTLogBoxView alloc] initWithBridge:self->_bridge];
78-
#endif // macOS]
7967
}
8068
[strongSelf->_view show];
8169
}

packages/react-native/React/CoreModules/RCTLogBoxView.h

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,25 @@
1111
#import <React/RCTUIKit.h> // [macOS]
1212

1313
#if !TARGET_OS_OSX // [macOS]
14-
1514
@interface RCTLogBoxView : UIWindow
15+
#else // [macOS
16+
@interface RCTLogBoxView : NSWindow
17+
#endif // macOS]
1618

19+
#if !TARGET_OS_OSX // [macOS]
1720
- (instancetype)initWithFrame:(CGRect)frame;
21+
#endif // [macOS]
1822

19-
- (void)createRootViewController:(UIView *)view;
23+
- (void)createRootViewController:(RCTUIView *)view; // [macOS]
2024

21-
- (instancetype)initWithWindow:(UIWindow *)window bridge:(RCTBridge *)bridge;
22-
- (instancetype)initWithWindow:(UIWindow *)window surfacePresenter:(id<RCTSurfacePresenterStub>)surfacePresenter;
25+
- (instancetype)initWithWindow:(RCTUIWindow *)window bridge:(RCTBridge *)bridge; // [macOS]
26+
- (instancetype)initWithWindow:(RCTUIWindow *)window surfacePresenter:(id<RCTSurfacePresenterStub>)surfacePresenter; // [macOS]
2327

2428
- (void)show;
25-
26-
@end
27-
28-
#else // [macOS
29-
30-
@interface RCTLogBoxView : NSWindow
31-
32-
- (instancetype)initWithSurfacePresenter:(id<RCTSurfacePresenterStub>)surfacePresenter;
33-
- (instancetype)initWithBridge:(RCTBridge *)bridge;
34-
29+
#if TARGET_OS_OSX // [macOS
3530
- (void)setHidden:(BOOL)hidden;
36-
37-
- (void)show;
31+
#endif // macOS]
3832

3933
@end
4034

41-
#endif // macOS]
35+

0 commit comments

Comments
 (0)