guardia-messenger/node_modules/expo-splash-screen/ios/EXSplashScreen/EXSplashScreenModule.m
DESKTOP-TKLFCPRython f29f525c77 refactor: 101.79.17.164 → zioinfo.co.kr 전체 도메인 변환 + Manager UI 배포
- 37개 파일 IP → zioinfo.co.kr 치환 (소스/매뉴얼/설정/하네스)
- Manager DrConsole/NetworkConsole/CsapConsole 빌드 + /var/www/manager/ 배포
- 테스트: Manager HTTP 200, ITSM 신규 API 7개 전체 200

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 10:09:17 +09:00

173 lines
6.1 KiB
Objective-C

// Copyright 2018-present 650 Industries. All rights reserved.
#import <EXSplashScreen/EXSplashScreenModule.h>
#import <EXSplashScreen/EXSplashScreenService.h>
#import <React/RCTRootView.h>
#import <ExpoModulesCore/EXAppLifecycleService.h>
#import <ExpoModulesCore/EXUtilities.h>
@protocol EXSplashScreenUtilService
- (UIViewController *)currentViewController;
@end
@interface EXSplashScreenModule ()
@property (nonatomic, weak) EXModuleRegistry *moduleRegistry;
@property (nonatomic, weak) id<EXUtilitiesInterface> utilities;
@end
@implementation EXSplashScreenModule
EX_EXPORT_MODULE(ExpoSplashScreen);
- (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry
{
_moduleRegistry = moduleRegistry;
_utilities = [moduleRegistry getModuleImplementingProtocol:@protocol(EXUtilitiesInterface)];
[[moduleRegistry getModuleImplementingProtocol:@protocol(EXAppLifecycleService)] registerAppLifecycleListener:self];
}
EX_EXPORT_METHOD_AS(hideAsync,
hideWithResolve:(EXPromiseResolveBlock)resolve
reject:(EXPromiseRejectBlock)reject)
{
EX_WEAKIFY(self);
dispatch_async(dispatch_get_main_queue(), ^{
EX_ENSURE_STRONGIFY(self);
UIViewController *currentViewController = [self reactViewController];
[[self splashScreenService] hideSplashScreenFor:currentViewController
options:EXSplashScreenDefault
successCallback:^(BOOL hasEffect){ resolve(@(hasEffect)); }
failureCallback:^(NSString *message){ reject(@"ERR_SPLASH_SCREEN_CANNOT_HIDE", message, nil); }];
});
}
EX_EXPORT_METHOD_AS(preventAutoHideAsync,
preventAutoHideWithResolve:(EXPromiseResolveBlock)resolve
reject:(EXPromiseRejectBlock)reject)
{
EX_WEAKIFY(self);
dispatch_async(dispatch_get_main_queue(), ^{
EX_ENSURE_STRONGIFY(self);
UIViewController *currentViewController = [self reactViewController];
[[self splashScreenService] preventSplashScreenAutoHideFor:currentViewController
options:EXSplashScreenDefault
successCallback:^(BOOL hasEffect){ resolve(@(hasEffect)); }
failureCallback:^(NSString *message){ reject(@"ERR_SPLASH_SCREEN_CANNOT_PREVENT_AUTOHIDE", message, nil); }];
});
}
# pragma mark - EXAppLifecycleListener
- (void)onAppBackgrounded {}
- (void)onAppForegrounded {}
- (void)onAppContentDidAppear
{
EX_WEAKIFY(self);
dispatch_async(dispatch_get_main_queue(), ^{
EX_ENSURE_STRONGIFY(self);
UIViewController* currentViewController = [self reactViewController];
[[self splashScreenService] onAppContentDidAppear:currentViewController];
});
}
- (void)onAppContentWillReload
{
EX_WEAKIFY(self);
dispatch_async(dispatch_get_main_queue(), ^{
EX_ENSURE_STRONGIFY(self);
UIViewController* currentViewController = [self reactViewController];
[[self splashScreenService] onAppContentWillReload:currentViewController];
});
}
# pragma mark - internals
/**
* Tries to obtain singleton module that is registered as "SplashScreen".
* Silent agreement is that registered module conforms to "EXSplashScreenService" protocol.
*/
- (id<EXSplashScreenService>)splashScreenService
{
return [self.moduleRegistry getSingletonModuleForName:@"SplashScreen"];
}
/**
* Tries to obtain a reference to the UIViewController for the main RCTRootView
* by iterating through all of the application's windows and their viewControllers
* until it finds one with a RCTRootView.
*/
- (UIViewController *)reactViewController
{
dispatch_assert_queue(dispatch_get_main_queue());
// first check to see if the host application has a module that provides the reference we want
// (this is the case in Expo Go and in the ExpoKit pod used in `expo build` apps)
id<EXSplashScreenUtilService> utilService = [_moduleRegistry getSingletonModuleForName:@"Util"];
if (utilService != nil) {
return [utilService currentViewController];
}
UIViewController *controller = [self viewControllerContainingRCTRootView];
if (!controller) {
// no RCTRootView was found, so just fall back to the key window's root view controller
controller = self.utilities.currentViewController;
while ([controller isKindOfClass:[UIAlertController class]] &&
controller.presentingViewController != nil) {
controller = controller.presentingViewController;
}
return controller;
}
UIViewController *presentedController = controller.presentedViewController;
while (presentedController &&
![presentedController isBeingDismissed] &&
![presentedController isKindOfClass:[UIAlertController class]]) {
controller = presentedController;
presentedController = controller.presentedViewController;
}
return controller;
}
- (nullable UIViewController *)viewControllerContainingRCTRootView
{
NSArray<UIWindow *> *allWindows;
if (@available(iOS 13, *)) {
NSSet<UIScene *> *allWindowScenes = UIApplication.sharedApplication.connectedScenes;
NSMutableArray<UIWindow *> *allForegroundWindows = [NSMutableArray new];
for (UIScene *scene in allWindowScenes.allObjects) {
if ([scene isKindOfClass:[UIWindowScene class]] && scene.activationState == UISceneActivationStateForegroundActive) {
[allForegroundWindows addObjectsFromArray:((UIWindowScene *)scene).windows];
}
}
allWindows = allForegroundWindows;
} else {
allWindows = UIApplication.sharedApplication.windows;
}
for (UIWindow *window in allWindows) {
UIViewController *controller = window.rootViewController;
if ([controller.view isKindOfClass:[RCTRootView class]]) {
return controller;
}
UIViewController *presentedController = controller.presentedViewController;
while (presentedController && ![presentedController isBeingDismissed]) {
if ([presentedController.view isKindOfClass:[RCTRootView class]]) {
return presentedController;
}
controller = presentedController;
presentedController = controller.presentedViewController;
}
}
// no RCTRootView was found
return nil;
}
@end