react-native-navigation的迁移库

RCCManagerModule.m 15KB

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