Skip to content

Commit

Permalink
feat(ios): Improve method of getting UI state and Add NightMode
Browse files Browse the repository at this point in the history
sync from hippy2
  • Loading branch information
wwwcg committed Oct 13, 2023
1 parent 5a25dc4 commit f7b8c3a
Show file tree
Hide file tree
Showing 15 changed files with 297 additions and 425 deletions.
4 changes: 2 additions & 2 deletions framework/examples/ios-demo/podfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ENV["layout_engine"]="Taitank"
# ENV["layout_engine"]="Taitank"
# ENV["js_engine"] = "v8"
install! 'cocoapods',
:deterministic_uuids => false,
Expand Down Expand Up @@ -38,4 +38,4 @@ post_install do |installer|
#change search path for HippyDemo
rewriteConfigFile("#{_pod_debug_config_dir_}", "${PODS_ROOT}/hippy", "#{_hippy_dir_}")
rewriteConfigFile("#{_pod_release_config_dir_}", "${PODS_ROOT}/hippy", "#{_hippy_dir_}")
end
end
7 changes: 6 additions & 1 deletion framework/ios/base/HippyDeviceBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,15 @@

NS_ASSUME_NONNULL_BEGIN

HIPPY_EXTERN NSDictionary *HippyExportedDimensions(void);
HIPPY_EXTERN NSDictionary *hippyExportedDimensions(HippyBridge *);
HIPPY_EXTERN NSString *const HippyDimensionsShouldUpdateNotification;

/// A Helper class that collects `Dimensions` info
@interface HippyDeviceBaseInfo : NSObject <HippyBridgeModule>

/// Whether is UIScreen in system dark mode.
+ (BOOL)isUIScreenInOSDarkMode;

@end

NS_ASSUME_NONNULL_END
204 changes: 87 additions & 117 deletions framework/ios/base/HippyDeviceBaseInfo.mm
Original file line number Diff line number Diff line change
Expand Up @@ -21,167 +21,137 @@
*/

#import <UIKit/UIApplication.h>

#import "HippyAsserts.h"
#import "HippyUtils.h"
#import "HippyDeviceBaseInfo.h"
#import "HippyEventDispatcher.h"

static BOOL IsiPhoneX() {
if (@available(iOS 11.0, *)) {
CGFloat height = [[UIApplication sharedApplication] delegate].window.safeAreaInsets.bottom;
return (height > 0);
} else {
return NO;
}
}

static NSDictionary *gDimensions = nil;

static dispatch_semaphore_t DimesionSemaphore(void) {
static dispatch_semaphore_t semaphore = nil;
NSDictionary *hippyExportedDimensions(HippyBridge *bridge) {
NSCAssert([NSThread mainThread], @"this function can only be called in main thread");
CGSize screenSize = [UIScreen mainScreen].bounds.size;
CGSize windowSize = HippyKeyWindow() ? HippyKeyWindow().bounds.size : screenSize;
// To be replace by HippyKeyWindow().windowScene.statusBarManager.statusBarFrame;
CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
if (statusBarHeight == 0) {
// Since different devices have different statusbar height values,
// It is not recommended to use it for layout,
// but, it has been used in some scenarios,
// To reduce the impact of the problem, provide a default value when not available.
if ([bridge.delegate respondsToSelector:@selector(defaultStatusBarHeightNoMatterHiddenOrNot)]) {
statusBarHeight = bridge.delegate.defaultStatusBarHeightNoMatterHiddenOrNot ?: 0.0;
}
}
static NSNumber *screenScale = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
semaphore = dispatch_semaphore_create(1);
});
return semaphore;
}

static NSDictionary *InitializeDimesions(void) {
__block CGSize screenSize = CGSizeZero;
__block CGSize windowSize = CGSizeZero;
__block CGFloat statusBarHeight = 0.f;
__block NSNumber *screenScale = nil;

dispatch_block_t block = ^(void){
screenSize = [UIScreen mainScreen].bounds.size;
windowSize = HippyKeyWindow() ? HippyKeyWindow().bounds.size : screenSize;
statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
if (statusBarHeight == 0) {
statusBarHeight = IsiPhoneX() ? 44 : 20;
}
screenScale = @([UIScreen mainScreen].scale);
};
HippyExecuteOnMainThread(block, YES);
gDimensions = @{
// 备注,window和screen的区别在于有没有底bar虚拟导航栏,而iOS没有这个东西,所以window和screen是一样的
@"window":
@ { @"width": @(windowSize.width), @"height": @(windowSize.height), @"scale": screenScale, @"statusBarHeight": @(statusBarHeight) },
@"screen": @ {
});
NSDictionary *dimensions = @{
@"window" : @{
@"width": @(windowSize.width),
@"height": @(windowSize.height),
@"scale": screenScale,
@"statusBarHeight": @(statusBarHeight)
},
@"screen" : @{
@"width": @(screenSize.width),
@"height": @(screenSize.height),
@"scale": screenScale,
@"fontScale": @(1),
@"statusBarHeight": @(statusBarHeight)
}
};
return gDimensions;
}

static void DisposeDimesions(void) {
dispatch_semaphore_wait(DimesionSemaphore(), DISPATCH_TIME_FOREVER);
gDimensions = nil;
dispatch_semaphore_signal(DimesionSemaphore());
}

NSDictionary *HippyExportedDimensions(void) {
NSDictionary *dic = nil;
dispatch_semaphore_wait(DimesionSemaphore(), DISPATCH_TIME_FOREVER);
if (gDimensions) {
dic = [gDimensions copy];
}
else {
dic = [InitializeDimesions() copy];
}
dispatch_semaphore_signal(DimesionSemaphore());
return dic;
return dimensions;
}

@protocol HippyStatusBarOrientationChangedProtocol <NSObject>

@required
- (void)statusBarOrientationChanged;

@end
#pragma mark -

@interface HippyBaseInfoInternal : NSObject {
NSHashTable<id<HippyStatusBarOrientationChangedProtocol>> *_observers;
@interface HippyDeviceBaseInfo () {
id<NSObject> _statusBarOrientationNotificationObserver;
id<NSObject> _applicationDidBecomeActiveNotificationObserver;
UIInterfaceOrientation _currentInterfaceOrientation;
}

+ (instancetype)sharedInstance;
@end

- (void)addObserver:(id<HippyStatusBarOrientationChangedProtocol>)observer;
@implementation HippyDeviceBaseInfo

- (void)removeObserver:(id<HippyStatusBarOrientationChangedProtocol>)observer;
HIPPY_EXPORT_MODULE(DeviceBaseInfo)

@end
NSString *const HippyDimensionsShouldUpdateNotification = @"HippyDimensionsShouldUpdateNotification";

@implementation HippyBaseInfoInternal
@synthesize bridge = _bridge;

+ (instancetype)sharedInstance {
static HippyBaseInfoInternal *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[HippyBaseInfoInternal alloc] init];
});
return instance;
static UIInterfaceOrientation getStatusBarOrientation(void) {
return [[UIApplication sharedApplication] statusBarOrientation];
}

- (instancetype)init {
self = [super init];
if (self) {
_observers = [NSHashTable weakObjectsHashTable];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(statusBarOrientationChanged)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
__weak HippyDeviceBaseInfo *devInfo = self;
NSString *notificationName;
if ([_bridge.delegate respondsToSelector:@selector(shouldUseViewWillTransitionMethodToMonitorOrientation)]
&& _bridge.delegate.shouldUseViewWillTransitionMethodToMonitorOrientation) {
notificationName = HippyDimensionsShouldUpdateNotification;
} else {
notificationName = UIApplicationDidChangeStatusBarOrientationNotification;
}
_statusBarOrientationNotificationObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:notificationName
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *_Nonnull note) {
if (devInfo) {
HippyDeviceBaseInfo *strongSelf = devInfo;
UIInterfaceOrientation previousInterfaceOrientation = strongSelf->_currentInterfaceOrientation;
UIInterfaceOrientation currentInterfaceOrientation = getStatusBarOrientation();
if (previousInterfaceOrientation != currentInterfaceOrientation) {
NSDictionary *dim = hippyExportedDimensions(strongSelf->_bridge);
[strongSelf->_bridge.eventDispatcher dispatchEvent:@"Dimensions" methodName:@"set" args:dim];
}
strongSelf->_currentInterfaceOrientation = currentInterfaceOrientation;
}
}];

_applicationDidBecomeActiveNotificationObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:UIApplicationDidBecomeActiveNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *_Nonnull note) {
if (devInfo) {
HippyDeviceBaseInfo *strongSelf = devInfo;
UIInterfaceOrientation currentInterfaceOrientation = strongSelf->_currentInterfaceOrientation;
UIInterfaceOrientation activeStatusBarOrientation = getStatusBarOrientation();
if (currentInterfaceOrientation != activeStatusBarOrientation) {
NSDictionary *dim = hippyExportedDimensions(strongSelf->_bridge);
[strongSelf->_bridge.eventDispatcher dispatchEvent:@"Dimensions" methodName:@"set" args:dim];
}
strongSelf->_currentInterfaceOrientation = activeStatusBarOrientation;
}
}];
}
return self;
}

- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)addObserver:(id<HippyStatusBarOrientationChangedProtocol>)observer {
[_observers addObject:observer];
}

- (void)removeObserver:(id<HippyStatusBarOrientationChangedProtocol>)observer {
[_observers removeObject:observer];
}

- (void)statusBarOrientationChanged {
DisposeDimesions();
for (id<HippyStatusBarOrientationChangedProtocol> observer in _observers) {
[observer statusBarOrientationChanged];
}
}

@end

@interface HippyDeviceBaseInfo ()<HippyStatusBarOrientationChangedProtocol> {
[[NSNotificationCenter defaultCenter] removeObserver:_statusBarOrientationNotificationObserver];
[[NSNotificationCenter defaultCenter] removeObserver:_applicationDidBecomeActiveNotificationObserver];
}

@end

@implementation HippyDeviceBaseInfo

HIPPY_EXPORT_MODULE(DeviceBaseInfo)

@synthesize bridge = _bridge;
#pragma mark - Uitls

- (instancetype)init {
self = [super init];
if (self) {
[[HippyBaseInfoInternal sharedInstance] addObserver:self];
+ (BOOL)isUIScreenInOSDarkMode {
if (@available(iOS 12.0, *)) {
return (UIUserInterfaceStyleDark == [UIScreen mainScreen].traitCollection.userInterfaceStyle);
} else {
return NO;
}
return self;
}

- (void)statusBarOrientationChanged {
NSDictionary *dim = HippyExportedDimensions();
[[self bridge].eventDispatcher dispatchEvent:@"Dimensions" methodName:@"set" args:dim];
}

@end
16 changes: 11 additions & 5 deletions framework/ios/base/bridge/HippyBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,6 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass);
*/
- (void)setRedBoxShowEnabled:(BOOL)enabled;

/**
* just for debugger
*/
- (void)bindKeys;

/**
* Use this to check if the bridge has been invalidated.
*/
Expand Down Expand Up @@ -312,6 +307,17 @@ HIPPY_EXTERN NSString *HippyBridgeModuleNameForClass(Class bridgeModuleClass);
- (void)resetRootSize:(CGSize)size;


#pragma mark - App UI State Related

/// NightMode or not, default is NO.
/// Updated by HippyRootView
@property (atomic, assign, readonly) BOOL isOSNightMode;

/// update `NightMode` state when changed
/// - Parameter isOSNightMode: bool
/// - Parameter rootViewTag: rootView's hippyTag
- (void)setOSNightMode:(BOOL)isOSNightMode withRootViewTag:(NSNumber *)rootViewTag;


@end

Expand Down
Loading

0 comments on commit f7b8c3a

Please sign in to comment.