react-native-navigation的迁移库

RCCManagerModule.m 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. #import "RCCManagerModule.h"
  2. #import "RCCManager.h"
  3. #import <UIKit/UIKit.h>
  4. #import "RCCNavigationController.h"
  5. #import "RCCViewController.h"
  6. #import "RCCDrawerController.h"
  7. #import "RCCLightBox.h"
  8. #import "RCTConvert.h"
  9. #import "RCCTabBarController.h"
  10. #import "RCCTheSideBarManagerViewController.h"
  11. #import "RCCNotification.h"
  12. #import "RNNViewController.h"
  13. #define kSlideDownAnimationDuration 0.35
  14. typedef NS_ENUM(NSInteger, RCCManagerModuleErrorCode)
  15. {
  16. RCCManagerModuleCantCreateControllerErrorCode = -100,
  17. RCCManagerModuleCantFindTabControllerErrorCode = -200,
  18. RCCManagerModuleMissingParamsErrorCode = -300
  19. };
  20. @implementation RCTConvert (RCCManagerModuleErrorCode)
  21. RCT_ENUM_CONVERTER(RCCManagerModuleErrorCode,
  22. (@{@"RCCManagerModuleCantCreateControllerErrorCode": @(RCCManagerModuleCantCreateControllerErrorCode),
  23. @"RCCManagerModuleCantFindTabControllerErrorCode": @(RCCManagerModuleCantFindTabControllerErrorCode),
  24. }), RCCManagerModuleCantCreateControllerErrorCode, integerValue)
  25. @end
  26. @implementation RCCManagerModule
  27. RCT_EXPORT_MODULE(RCCManager);
  28. #pragma mark - constatnts export
  29. - (NSDictionary *)constantsToExport
  30. {
  31. return @{
  32. //Error codes
  33. @"RCCManagerModuleCantCreateControllerErrorCode" : @(RCCManagerModuleCantCreateControllerErrorCode),
  34. @"RCCManagerModuleCantFindTabControllerErrorCode" : @(RCCManagerModuleCantFindTabControllerErrorCode),
  35. };
  36. }
  37. - (dispatch_queue_t)methodQueue
  38. {
  39. return dispatch_get_main_queue();
  40. }
  41. #pragma mark - helper methods
  42. +(UIViewController*)modalPresenterViewControllers:(NSMutableArray*)returnAllPresenters
  43. {
  44. UIViewController *modalPresenterViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
  45. if ((returnAllPresenters != nil) && (modalPresenterViewController != nil))
  46. {
  47. [returnAllPresenters addObject:modalPresenterViewController];
  48. }
  49. while (modalPresenterViewController.presentedViewController != nil)
  50. {
  51. modalPresenterViewController = modalPresenterViewController.presentedViewController;
  52. if (returnAllPresenters != nil)
  53. {
  54. [returnAllPresenters addObject:modalPresenterViewController];
  55. }
  56. }
  57. return modalPresenterViewController;
  58. }
  59. +(UIViewController*)lastModalPresenterViewController
  60. {
  61. return [self modalPresenterViewControllers:nil];
  62. }
  63. +(NSError*)rccErrorWithCode:(NSInteger)code description:(NSString*)description
  64. {
  65. NSString *safeDescription = (description == nil) ? @"" : description;
  66. return [NSError errorWithDomain:@"RCCControllers" code:code userInfo:@{NSLocalizedDescriptionKey: safeDescription}];
  67. }
  68. +(void)handleRCTPromiseRejectBlock:(RCTPromiseRejectBlock)reject error:(NSError*)error
  69. {
  70. reject([NSString stringWithFormat: @"%lu", (long)error.code], error.localizedDescription, error);
  71. }
  72. +(void)cancelAllRCCViewControllerReactTouches
  73. {
  74. [[NSNotificationCenter defaultCenter] postNotificationName:RCCViewControllerCancelReactTouchesNotification object:nil];
  75. }
  76. -(void)animateSnapshot:(UIView*)snapshot animationType:(NSString*)animationType resolver:(RCTPromiseResolveBlock)resolve
  77. {
  78. [UIView animateWithDuration:kSlideDownAnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^()
  79. {
  80. if (animationType == nil || [animationType isEqualToString:@"slide-down"])
  81. {
  82. snapshot.transform = CGAffineTransformMakeTranslation(0, snapshot.frame.size.height);
  83. }
  84. else if ([animationType isEqualToString:@"fade"])
  85. {
  86. snapshot.alpha = 0;
  87. }
  88. }
  89. completion:^(BOOL finished)
  90. {
  91. [snapshot removeFromSuperview];
  92. if (resolve != nil)
  93. {
  94. resolve(nil);
  95. }
  96. }];
  97. }
  98. -(void)dismissAllModalPresenters:(NSMutableArray*)allPresentedViewControllers resolver:(RCTPromiseResolveBlock)resolve
  99. {
  100. if (allPresentedViewControllers.count > 0)
  101. {
  102. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^
  103. {
  104. __block NSUInteger counter = 0;
  105. for (UIViewController *viewController in allPresentedViewControllers)
  106. {
  107. counter++;
  108. [[RCCManager sharedIntance] unregisterController:viewController];
  109. if (viewController.presentedViewController != nil)
  110. {
  111. dispatch_semaphore_t dismiss_sema = dispatch_semaphore_create(0);
  112. dispatch_async(dispatch_get_main_queue(), ^
  113. {
  114. [viewController dismissViewControllerAnimated:NO completion:^()
  115. {
  116. if (counter == allPresentedViewControllers.count && allPresentedViewControllers.count > 0)
  117. {
  118. [allPresentedViewControllers removeAllObjects];
  119. if (resolve != nil)
  120. {
  121. resolve(nil);
  122. }
  123. }
  124. dispatch_semaphore_signal(dismiss_sema);
  125. }];
  126. });
  127. dispatch_semaphore_wait(dismiss_sema, DISPATCH_TIME_FOREVER);
  128. }
  129. else if (counter == allPresentedViewControllers.count && allPresentedViewControllers.count > 0)
  130. {
  131. [allPresentedViewControllers removeAllObjects];
  132. if (resolve != nil)
  133. {
  134. dispatch_async(dispatch_get_main_queue(), ^
  135. {
  136. resolve(nil);
  137. });
  138. }
  139. }
  140. }
  141. });
  142. }
  143. else if (resolve != nil)
  144. {
  145. resolve(nil);
  146. }
  147. }
  148. -(void)startAppAfterBridgeFinishLoading:(NSDictionary*)layout
  149. {
  150. [[RCCManager sharedInstance] clearModuleRegistry];
  151. UIViewController *controller = [RNNViewController controllerWithLayout:layout bridge:[[RCCManager sharedInstance] getBridge]];
  152. if (controller == nil) return;
  153. id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
  154. appDelegate.window.rootViewController = controller;
  155. [appDelegate.window makeKeyAndVisible];
  156. }
  157. #pragma mark - RCT exported methods
  158. RCT_EXPORT_METHOD(
  159. startApp:(NSDictionary*)layout)
  160. {
  161. if ([[RCCManager sharedInstance] getBridge].loading) {
  162. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0001 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  163. [self startAppAfterBridgeFinishLoading:layout];
  164. });
  165. return;
  166. }
  167. dispatch_async(dispatch_get_main_queue(), ^{
  168. [self startAppAfterBridgeFinishLoading:layout];
  169. });
  170. }
  171. RCT_EXPORT_METHOD(
  172. setRootController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps)
  173. {
  174. if ([[RCCManager sharedInstance] getBridge].loading) {
  175. [self deferSetRootControllerWhileBridgeLoading:layout animationType:animationType globalProps:globalProps];
  176. return;
  177. }
  178. dispatch_async(dispatch_get_main_queue(), ^{
  179. [self performSetRootController:layout animationType:animationType globalProps:globalProps];
  180. });
  181. }
  182. /**
  183. * on RN31 there's a timing issue, we must wait for the bridge to finish loading
  184. */
  185. -(void)deferSetRootControllerWhileBridgeLoading:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps
  186. {
  187. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0001 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  188. [self setRootController:layout animationType:animationType globalProps:globalProps];
  189. });
  190. }
  191. -(void)performSetRootController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps
  192. {
  193. // first clear the registry to remove any refernece to the previous controllers
  194. [[RCCManager sharedInstance] clearModuleRegistry];
  195. // create the new controller
  196. UIViewController *controller = [RCCViewController controllerWithLayout:layout globalProps:globalProps bridge:[[RCCManager sharedInstance] getBridge]];
  197. if (controller == nil) return;
  198. id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
  199. BOOL animated = !((appDelegate.window.rootViewController == nil) || ([animationType isEqualToString:@"none"]));
  200. // if we're animating - add a snapshot now
  201. UIViewController *presentedViewController = nil;
  202. UIView *snapshot = nil;
  203. if (animated)
  204. {
  205. if(appDelegate.window.rootViewController.presentedViewController != nil)
  206. presentedViewController = appDelegate.window.rootViewController.presentedViewController;
  207. else
  208. presentedViewController = appDelegate.window.rootViewController;
  209. snapshot = [presentedViewController.view snapshotViewAfterScreenUpdates:NO];
  210. [appDelegate.window.rootViewController.view addSubview:snapshot];
  211. }
  212. // dismiss the modal controllers without animation just so they can be released
  213. [self dismissAllControllers:@"none" resolver:^(id result)
  214. {
  215. // set the new controller as the root
  216. appDelegate.window.rootViewController = controller;
  217. [appDelegate.window makeKeyAndVisible];
  218. [presentedViewController dismissViewControllerAnimated:NO completion:nil];
  219. if (animated)
  220. {
  221. // move the snaphot to the new root and animate it
  222. [appDelegate.window.rootViewController.view addSubview:snapshot];
  223. [self animateSnapshot:snapshot animationType:animationType resolver:nil];
  224. }
  225. } rejecter:nil];
  226. }
  227. RCT_EXPORT_METHOD(
  228. NavigationControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams)
  229. {
  230. if (!controllerId || !performAction) return;
  231. RCCNavigationController* controller = [[RCCManager sharedInstance] getControllerWithId:controllerId componentType:@"NavigationControllerIOS"];
  232. if (!controller || ![controller isKindOfClass:[RCCNavigationController class]]) return;
  233. return [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedInstance] getBridge]];
  234. }
  235. RCT_EXPORT_METHOD(
  236. DrawerControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams)
  237. {
  238. if (!controllerId || !performAction) return;
  239. id<RCCDrawerDelegate> controller = [[RCCManager sharedIntance] getControllerWithId:controllerId componentType:@"DrawerControllerIOS"];
  240. if (!controller || (![controller isKindOfClass:[RCCDrawerController class]] && ![controller isKindOfClass:[RCCTheSideBarManagerViewController class]])) return;
  241. return [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedIntance] getBridge]];
  242. }
  243. RCT_EXPORT_METHOD(
  244. TabBarControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  245. {
  246. if (!controllerId || !performAction)
  247. {
  248. [RCCManagerModule handleRCTPromiseRejectBlock:reject
  249. error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleMissingParamsErrorCode description:@"missing params"]];
  250. return;
  251. }
  252. RCCTabBarController* controller = [[RCCManager sharedInstance] getControllerWithId:controllerId componentType:@"TabBarControllerIOS"];
  253. if (!controller || ![controller isKindOfClass:[RCCTabBarController class]])
  254. {
  255. [RCCManagerModule handleRCTPromiseRejectBlock:reject
  256. error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleCantFindTabControllerErrorCode description:@"could not find UITabBarController"]];
  257. return;
  258. }
  259. [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedInstance] getBridge] completion:^(){ resolve(nil); }];
  260. }
  261. RCT_EXPORT_METHOD(
  262. modalShowLightBox:(NSDictionary*)params)
  263. {
  264. [RCCLightBox showWithParams:params];
  265. }
  266. RCT_EXPORT_METHOD(
  267. modalDismissLightBox)
  268. {
  269. [RCCLightBox dismiss];
  270. }
  271. RCT_EXPORT_METHOD(
  272. showController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  273. {
  274. UIViewController *controller = [RCCViewController controllerWithLayout:layout globalProps:globalProps bridge:[[RCCManager sharedInstance] getBridge]];
  275. if (controller == nil)
  276. {
  277. [RCCManagerModule handleRCTPromiseRejectBlock:reject
  278. error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleCantCreateControllerErrorCode description:@"could not create controller"]];
  279. return;
  280. }
  281. [[RCCManagerModule lastModalPresenterViewController] presentViewController:controller
  282. animated:![animationType isEqualToString:@"none"]
  283. completion:^(){ resolve(nil); }];
  284. }
  285. -(BOOL)viewControllerIsModal:(UIViewController*)viewController
  286. {
  287. BOOL viewControllerIsModal = (viewController.presentingViewController.presentedViewController == viewController)
  288. || ((viewController.navigationController != nil) && (viewController.navigationController.presentingViewController.presentedViewController == viewController.navigationController) && (viewController == viewController.navigationController.viewControllers[0]))
  289. || ([viewController.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]]);
  290. return viewControllerIsModal;
  291. }
  292. RCT_EXPORT_METHOD(
  293. dismissController:(NSString*)animationType resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  294. {
  295. UIViewController* vc = [RCCManagerModule lastModalPresenterViewController];
  296. if ([self viewControllerIsModal:vc])
  297. {
  298. [[RCCManager sharedIntance] unregisterController:vc];
  299. [vc dismissViewControllerAnimated:![animationType isEqualToString:@"none"]
  300. completion:^(){ resolve(nil); }];
  301. }
  302. }
  303. RCT_EXPORT_METHOD(
  304. dismissAllControllers:(NSString*)animationType resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  305. {
  306. if([UIApplication sharedApplication].delegate.window.rootViewController.presentedViewController == nil)
  307. {//if there are no modal - do nothing
  308. resolve(nil);
  309. return;
  310. }
  311. NSMutableArray *allPresentedViewControllers = [NSMutableArray array];
  312. [RCCManagerModule modalPresenterViewControllers:allPresentedViewControllers];
  313. BOOL animated = ![animationType isEqualToString:@"none"];
  314. if (animated)
  315. {
  316. id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
  317. UIView *snapshot = [appDelegate.window snapshotViewAfterScreenUpdates:NO];
  318. [appDelegate.window addSubview:snapshot];
  319. [self dismissAllModalPresenters:allPresentedViewControllers resolver:^(id result)
  320. {
  321. [self animateSnapshot:snapshot animationType:animationType resolver:resolve];
  322. }];
  323. }
  324. else
  325. {
  326. [self dismissAllModalPresenters:allPresentedViewControllers resolver:resolve];
  327. }
  328. }
  329. RCT_EXPORT_METHOD(
  330. showNotification:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  331. {
  332. [RCCNotification showWithParams:params resolver:resolve rejecter:reject];
  333. }
  334. RCT_EXPORT_METHOD(
  335. dismissNotification:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  336. {
  337. [RCCNotification dismissWithParams:params resolver:resolve rejecter:reject];
  338. }
  339. RCT_EXPORT_METHOD(
  340. cancelAllReactTouches)
  341. {
  342. [RCCManagerModule cancelAllRCCViewControllerReactTouches];
  343. }
  344. @end