Created
June 5, 2021 02:39
-
-
Save jupdike/9763c67277659df87cef8e75a53fc380 to your computer and use it in GitHub Desktop.
RCTDeviceInfo.mm changes to add a timer for MacCatalyst so window resizing works with React Native Dimensions, as expected
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (c) Facebook, Inc. and its affiliates. | |
* | |
* This source code is licensed under the MIT license found in the | |
* LICENSE file in the root directory of this source tree. | |
*/ | |
#import "RCTDeviceInfo.h" | |
#import <FBReactNativeSpec/FBReactNativeSpec.h> | |
#import <React/RCTAccessibilityManager.h> | |
#import <React/RCTAssert.h> | |
#import <React/RCTConstants.h> | |
#import <React/RCTEventDispatcher.h> | |
#import <React/RCTUIUtils.h> | |
#import <React/RCTUtils.h> | |
#import "CoreModulesPlugins.h" | |
using namespace facebook::react; | |
@interface RCTDeviceInfo () <NativeDeviceInfoSpec> | |
@end | |
@implementation RCTDeviceInfo { | |
#if !TARGET_OS_TV | |
UIInterfaceOrientation _currentInterfaceOrientation; | |
NSDictionary *_currentInterfaceDimensions; | |
#endif | |
} | |
@synthesize bridge = _bridge; | |
RCT_EXPORT_MODULE() | |
+ (BOOL)requiresMainQueueSetup | |
{ | |
return YES; | |
} | |
- (dispatch_queue_t)methodQueue | |
{ | |
return dispatch_get_main_queue(); | |
} | |
- (void)onTick: (int)dummy | |
{ | |
//// for (UIWindow *window in [[UIApplication class] performSelector:@selector(sharedApplication)].windows) { | |
//// if (window.keyWindow) { | |
//// return window; | |
//// } | |
//// } | |
UIView* mainWindow = RCTKeyWindow(); | |
CGSize windowSize = mainWindow ? mainWindow.bounds.size : CGSizeMake(0, 0); | |
// NSLog(@"onTick: %f, %f", windowSize.width, windowSize.height); | |
//call this with a timer, dern it! | |
[self interfaceFrameDidChange]; | |
} | |
- (void)setBridge:(RCTBridge *)bridge | |
{ | |
_bridge = bridge; | |
[[NSNotificationCenter defaultCenter] addObserver:self | |
selector:@selector(didReceiveNewContentSizeMultiplier) | |
name:RCTAccessibilityManagerDidUpdateMultiplierNotification | |
object:_bridge.accessibilityManager]; | |
#if !TARGET_OS_TV | |
_currentInterfaceOrientation = [RCTSharedApplication() statusBarOrientation]; | |
[[NSNotificationCenter defaultCenter] addObserver:self | |
selector:@selector(interfaceOrientationDidChange) | |
name:UIApplicationDidChangeStatusBarOrientationNotification | |
object:nil]; | |
_currentInterfaceDimensions = RCTExportedDimensions(_bridge); | |
[[NSNotificationCenter defaultCenter] addObserver:self | |
selector:@selector(interfaceFrameDidChange) | |
name:UIApplicationDidBecomeActiveNotification | |
object:nil]; | |
[[NSNotificationCenter defaultCenter] addObserver:self | |
selector:@selector(interfaceFrameDidChange) | |
name:RCTUserInterfaceStyleDidChangeNotification | |
object:nil]; | |
#endif | |
#ifdef TARGET_OS_MACCATALYST | |
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 0.5 | |
target: self | |
selector: @selector(onTick:) | |
userInfo: nil repeats: YES]; | |
#endif | |
} | |
static BOOL RCTIsIPhoneX() | |
{ | |
static BOOL isIPhoneX = NO; | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
RCTAssertMainQueue(); | |
CGSize screenSize = [UIScreen mainScreen].nativeBounds.size; | |
CGSize iPhoneXScreenSize = CGSizeMake(1125, 2436); | |
CGSize iPhoneXMaxScreenSize = CGSizeMake(1242, 2688); | |
CGSize iPhoneXRScreenSize = CGSizeMake(828, 1792); | |
isIPhoneX = CGSizeEqualToSize(screenSize, iPhoneXScreenSize) || | |
CGSizeEqualToSize(screenSize, iPhoneXMaxScreenSize) || CGSizeEqualToSize(screenSize, iPhoneXRScreenSize); | |
}); | |
return isIPhoneX; | |
} | |
static NSDictionary *RCTExportedDimensions(RCTBridge *bridge) | |
{ | |
RCTAssertMainQueue(); | |
RCTDimensions dimensions = RCTGetDimensions(bridge.accessibilityManager.multiplier); | |
__typeof(dimensions.window) window = dimensions.window; | |
NSDictionary<NSString *, NSNumber *> *dimsWindow = @{ | |
@"width" : @(window.width), | |
@"height" : @(window.height), | |
@"scale" : @(window.scale), | |
@"fontScale" : @(window.fontScale) | |
}; | |
__typeof(dimensions.screen) screen = dimensions.screen; | |
NSDictionary<NSString *, NSNumber *> *dimsScreen = @{ | |
@"width" : @(screen.width), | |
@"height" : @(screen.height), | |
@"scale" : @(screen.scale), | |
@"fontScale" : @(screen.fontScale) | |
}; | |
return @{@"window" : dimsWindow, @"screen" : dimsScreen}; | |
} | |
- (NSDictionary<NSString *, id> *)constantsToExport | |
{ | |
return [self getConstants]; | |
} | |
- (NSDictionary<NSString *, id> *)getConstants | |
{ | |
return @{ | |
@"Dimensions" : RCTExportedDimensions(_bridge), | |
// Note: | |
// This prop is deprecated and will be removed in a future release. | |
// Please use this only for a quick and temporary solution. | |
// Use <SafeAreaView> instead. | |
@"isIPhoneX_deprecated" : @(RCTIsIPhoneX()), | |
}; | |
} | |
- (void)didReceiveNewContentSizeMultiplier | |
{ | |
RCTBridge *bridge = _bridge; | |
RCTExecuteOnMainQueue(^{ | |
// Report the event across the bridge. | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Wdeprecated-declarations" | |
[bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" body:RCTExportedDimensions(bridge)]; | |
#pragma clang diagnostic pop | |
}); | |
} | |
#if !TARGET_OS_TV | |
- (void)interfaceOrientationDidChange | |
{ | |
__weak __typeof(self) weakSelf = self; | |
RCTExecuteOnMainQueue(^{ | |
[weakSelf _interfaceOrientationDidChange]; | |
}); | |
} | |
- (void)_interfaceOrientationDidChange | |
{ | |
UIInterfaceOrientation nextOrientation = [RCTSharedApplication() statusBarOrientation]; | |
// Update when we go from portrait to landscape, or landscape to portrait | |
if ((UIInterfaceOrientationIsPortrait(_currentInterfaceOrientation) && | |
!UIInterfaceOrientationIsPortrait(nextOrientation)) || | |
(UIInterfaceOrientationIsLandscape(_currentInterfaceOrientation) && | |
!UIInterfaceOrientationIsLandscape(nextOrientation))) { | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Wdeprecated-declarations" | |
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" body:RCTExportedDimensions(_bridge)]; | |
#pragma clang diagnostic pop | |
} | |
_currentInterfaceOrientation = nextOrientation; | |
} | |
- (void)interfaceFrameDidChange | |
{ | |
// NSLog(@"interfaceFrameDidChange"); | |
__weak __typeof(self) weakSelf = self; | |
RCTExecuteOnMainQueue(^{ | |
[weakSelf _interfaceFrameDidChange]; | |
}); | |
} | |
- (void)_interfaceFrameDidChange | |
{ | |
NSDictionary *nextInterfaceDimensions = RCTExportedDimensions(_bridge); | |
if (!([nextInterfaceDimensions isEqual:_currentInterfaceDimensions])) { | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Wdeprecated-declarations" | |
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" body:nextInterfaceDimensions]; | |
#pragma clang diagnostic pop | |
} | |
_currentInterfaceDimensions = nextInterfaceDimensions; | |
} | |
#endif // TARGET_OS_TV | |
- (std::shared_ptr<TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<CallInvoker>)jsInvoker | |
nativeInvoker:(std::shared_ptr<CallInvoker>)nativeInvoker | |
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger | |
{ | |
return std::make_shared<NativeDeviceInfoSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger); | |
} | |
@end | |
Class RCTDeviceInfoCls(void) | |
{ | |
return RCTDeviceInfo.class; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment