1// Copyright © 2018 650 Industries. All rights reserved.
2
3#import <EXSplashScreen/EXSplashScreenService.h>
4#import <EXSplashScreen/EXSplashScreenViewNativeProvider.h>
5#import <UMCore/UMDefines.h>
6
7@interface EXSplashScreenService ()
8
9@property (nonatomic, strong) NSMapTable<UIViewController *, EXSplashScreenViewController *> *splashScreenControllers;
10
11@end
12
13@implementation EXSplashScreenService
14
15UM_REGISTER_SINGLETON_MODULE(SplashScreen);
16
17- (instancetype)init
18{
19  if (self = [super init]) {
20    _splashScreenControllers = [NSMapTable weakToStrongObjectsMapTable];
21  }
22  return self;
23}
24
25- (void)showSplashScreenFor:(UIViewController *)viewController
26{
27  id<EXSplashScreenViewProvider> splashScreenViewProvider = [EXSplashScreenViewNativeProvider new];
28  return [self showSplashScreenFor:viewController
29          splashScreenViewProvider:splashScreenViewProvider
30                   successCallback:^{}
31                   failureCallback:^(NSString *message){ UMLogWarn(@"%@", message); }];
32}
33
34
35- (void)showSplashScreenFor:(UIViewController *)viewController
36   splashScreenViewProvider:(id<EXSplashScreenViewProvider>)splashScreenViewProvider
37            successCallback:(void (^)(void))successCallback
38            failureCallback:(void (^)(NSString * _Nonnull))failureCallback
39{
40  if ([self.splashScreenControllers objectForKey:viewController]) {
41    return failureCallback(@"'SplashScreen.show' has already been called for given view controller.");
42  }
43
44
45  UIView *rootView = viewController.view;
46  UIView *splashScreenView = [splashScreenViewProvider createSplashScreenView];
47  EXSplashScreenViewController *splashScreenController = [[EXSplashScreenViewController alloc] initWithRootView:rootView
48                                                                                               splashScreenView:splashScreenView];
49
50  [self showSplashScreenFor:viewController
51     splashScreenController:splashScreenController
52            successCallback:successCallback
53            failureCallback:failureCallback];
54}
55
56- (void)showSplashScreenFor:(UIViewController *)viewController
57     splashScreenController:(EXSplashScreenViewController *)splashScreenController
58            successCallback:(void (^)(void))successCallback
59            failureCallback:(void (^)(NSString * _Nonnull))failureCallback
60{
61  if ([self.splashScreenControllers objectForKey:viewController]) {
62    return failureCallback(@"'SplashScreen.show' has already been called for given view controller.");
63  }
64
65  [self.splashScreenControllers setObject:splashScreenController forKey:viewController];
66  [[self.splashScreenControllers objectForKey:viewController] showWithCallback:successCallback
67                                                               failureCallback:failureCallback];
68}
69
70- (void)preventSplashScreenAutoHideFor:(UIViewController *)viewController
71                       successCallback:(void (^)(BOOL hasEffect))successCallback
72                       failureCallback:(void (^)(NSString * _Nonnull))failureCallback
73{
74  if (![self.splashScreenControllers objectForKey:viewController]) {
75    return failureCallback(@"No native splash screen registered for given view controller. Call 'SplashScreen.show' for given view controller first.");
76  }
77
78  return [[self.splashScreenControllers objectForKey:viewController] preventAutoHideWithCallback:successCallback
79                                                                                 failureCallback:failureCallback];
80}
81
82- (void)hideSplashScreenFor:(UIViewController *)viewController
83            successCallback:(void (^)(BOOL hasEffect))successCallback
84            failureCallback:(void (^)(NSString * _Nonnull))failureCallback
85{
86  if (![self.splashScreenControllers objectForKey:viewController]) {
87    return failureCallback(@"No native splash screen registered for given view controller. Call 'SplashScreen.show' for given view controller first.");
88  }
89  return [[self.splashScreenControllers objectForKey:viewController] hideWithCallback:successCallback
90                                                                      failureCallback:failureCallback];
91}
92
93- (void)onAppContentDidAppear:(UIViewController *)viewController
94{
95  if (![self.splashScreenControllers objectForKey:viewController]) {
96    UMLogWarn(@"No native splash screen registered for given view controller. Call 'SplashScreen.show' for given view controller first.");
97  }
98  [[self.splashScreenControllers objectForKey:viewController] onAppContentDidAppear];
99}
100
101- (void)onAppContentWillReload:(UIViewController *)viewController
102{
103  if (![self.splashScreenControllers objectForKey:viewController]) {
104    UMLogWarn(@"No native splash screen registered for given view controller. Call 'SplashScreen.show' for given view controller first.");
105  }
106  [[self.splashScreenControllers objectForKey:viewController] onAppContentWillReload];
107}
108
109# pragma mark - UIApplicationDelegate
110
111- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
112{
113  UIViewController *rootViewController = [[application keyWindow] rootViewController];
114  if (rootViewController) {
115    [self showSplashScreenFor:rootViewController];
116  }
117  return YES;
118}
119
120@end
121