react-native-navigation的迁移库

RCCManagerModule.m 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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. setRootController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps)
  150. {
  151. if ([[RCCManager sharedInstance] getBridge].loading) {
  152. [self deferSetRootControllerWhileBridgeLoading:layout animationType:animationType globalProps:globalProps];
  153. return;
  154. }
  155. dispatch_async(dispatch_get_main_queue(), ^{
  156. [self performSetRootController:layout animationType:animationType globalProps:globalProps];
  157. });
  158. }
  159. /**
  160. * on RN31 there's a timing issue, we must wait for the bridge to finish loading
  161. */
  162. -(void)deferSetRootControllerWhileBridgeLoading:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps
  163. {
  164. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0001 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  165. [self setRootController:layout animationType:animationType globalProps:globalProps];
  166. });
  167. }
  168. -(void)performSetRootController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps
  169. {
  170. // first clear the registry to remove any refernece to the previous controllers
  171. [[RCCManager sharedInstance] clearModuleRegistry];
  172. // create the new controller
  173. UIViewController *controller = [RCCViewController controllerWithLayout:layout globalProps:globalProps bridge:[[RCCManager sharedInstance] getBridge]];
  174. if (controller == nil) return;
  175. id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
  176. BOOL animated = !((appDelegate.window.rootViewController == nil) || ([animationType isEqualToString:@"none"]));
  177. // if we're animating - add a snapshot now
  178. UIViewController *presentedViewController = nil;
  179. UIView *snapshot = nil;
  180. if (animated)
  181. {
  182. if(appDelegate.window.rootViewController.presentedViewController != nil)
  183. presentedViewController = appDelegate.window.rootViewController.presentedViewController;
  184. else
  185. presentedViewController = appDelegate.window.rootViewController;
  186. snapshot = [presentedViewController.view snapshotViewAfterScreenUpdates:NO];
  187. [appDelegate.window.rootViewController.view addSubview:snapshot];
  188. }
  189. // dismiss the modal controllers without animation just so they can be released
  190. [self dismissAllControllers:@"none" resolver:^(id result)
  191. {
  192. // set the new controller as the root
  193. appDelegate.window.rootViewController = controller;
  194. [appDelegate.window makeKeyAndVisible];
  195. [presentedViewController dismissViewControllerAnimated:NO completion:nil];
  196. if (animated)
  197. {
  198. // move the snaphot to the new root and animate it
  199. [appDelegate.window.rootViewController.view addSubview:snapshot];
  200. [self animateSnapshot:snapshot animationType:animationType resolver:nil];
  201. }
  202. } rejecter:nil];
  203. }
  204. RCT_EXPORT_METHOD(
  205. NavigationControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams)
  206. {
  207. if (!controllerId || !performAction) return;
  208. RCCNavigationController* controller = [[RCCManager sharedInstance] getControllerWithId:controllerId componentType:@"NavigationControllerIOS"];
  209. if (!controller || ![controller isKindOfClass:[RCCNavigationController class]]) return;
  210. return [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedInstance] getBridge]];
  211. }
  212. RCT_EXPORT_METHOD(
  213. DrawerControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams)
  214. {
  215. if (!controllerId || !performAction) return;
  216. id<RCCDrawerDelegate> controller = [[RCCManager sharedIntance] getControllerWithId:controllerId componentType:@"DrawerControllerIOS"];
  217. if (!controller || (![controller isKindOfClass:[RCCDrawerController class]] && ![controller isKindOfClass:[RCCTheSideBarManagerViewController class]])) return;
  218. return [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedIntance] getBridge]];
  219. }
  220. RCT_EXPORT_METHOD(
  221. TabBarControllerIOS:(NSString*)controllerId performAction:(NSString*)performAction actionParams:(NSDictionary*)actionParams resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  222. {
  223. if (!controllerId || !performAction)
  224. {
  225. [RCCManagerModule handleRCTPromiseRejectBlock:reject
  226. error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleMissingParamsErrorCode description:@"missing params"]];
  227. return;
  228. }
  229. RCCTabBarController* controller = [[RCCManager sharedInstance] getControllerWithId:controllerId componentType:@"TabBarControllerIOS"];
  230. if (!controller || ![controller isKindOfClass:[RCCTabBarController class]])
  231. {
  232. [RCCManagerModule handleRCTPromiseRejectBlock:reject
  233. error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleCantFindTabControllerErrorCode description:@"could not find UITabBarController"]];
  234. return;
  235. }
  236. [controller performAction:performAction actionParams:actionParams bridge:[[RCCManager sharedInstance] getBridge] completion:^(){ resolve(nil); }];
  237. }
  238. RCT_EXPORT_METHOD(
  239. modalShowLightBox:(NSDictionary*)params)
  240. {
  241. [RCCLightBox showWithParams:params];
  242. }
  243. RCT_EXPORT_METHOD(
  244. modalDismissLightBox)
  245. {
  246. [RCCLightBox dismiss];
  247. }
  248. RCT_EXPORT_METHOD(
  249. showController:(NSDictionary*)layout animationType:(NSString*)animationType globalProps:(NSDictionary*)globalProps resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  250. {
  251. UIViewController *controller = [RCCViewController controllerWithLayout:layout globalProps:globalProps bridge:[[RCCManager sharedInstance] getBridge]];
  252. if (controller == nil)
  253. {
  254. [RCCManagerModule handleRCTPromiseRejectBlock:reject
  255. error:[RCCManagerModule rccErrorWithCode:RCCManagerModuleCantCreateControllerErrorCode description:@"could not create controller"]];
  256. return;
  257. }
  258. [[RCCManagerModule lastModalPresenterViewController] presentViewController:controller
  259. animated:![animationType isEqualToString:@"none"]
  260. completion:^(){ resolve(nil); }];
  261. }
  262. -(BOOL)viewControllerIsModal:(UIViewController*)viewController
  263. {
  264. BOOL viewControllerIsModal = (viewController.presentingViewController.presentedViewController == viewController)
  265. || ((viewController.navigationController != nil) && (viewController.navigationController.presentingViewController.presentedViewController == viewController.navigationController) && (viewController == viewController.navigationController.viewControllers[0]))
  266. || ([viewController.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]]);
  267. return viewControllerIsModal;
  268. }
  269. RCT_EXPORT_METHOD(
  270. dismissController:(NSString*)animationType resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  271. {
  272. UIViewController* vc = [RCCManagerModule lastModalPresenterViewController];
  273. if ([self viewControllerIsModal:vc])
  274. {
  275. [[RCCManager sharedIntance] unregisterController:vc];
  276. [vc dismissViewControllerAnimated:![animationType isEqualToString:@"none"]
  277. completion:^(){ resolve(nil); }];
  278. }
  279. }
  280. RCT_EXPORT_METHOD(
  281. dismissAllControllers:(NSString*)animationType resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  282. {
  283. if([UIApplication sharedApplication].delegate.window.rootViewController.presentedViewController == nil)
  284. {//if there are no modal - do nothing
  285. resolve(nil);
  286. return;
  287. }
  288. NSMutableArray *allPresentedViewControllers = [NSMutableArray array];
  289. [RCCManagerModule modalPresenterViewControllers:allPresentedViewControllers];
  290. BOOL animated = ![animationType isEqualToString:@"none"];
  291. if (animated)
  292. {
  293. id<UIApplicationDelegate> appDelegate = [UIApplication sharedApplication].delegate;
  294. UIView *snapshot = [appDelegate.window snapshotViewAfterScreenUpdates:NO];
  295. [appDelegate.window addSubview:snapshot];
  296. [self dismissAllModalPresenters:allPresentedViewControllers resolver:^(id result)
  297. {
  298. [self animateSnapshot:snapshot animationType:animationType resolver:resolve];
  299. }];
  300. }
  301. else
  302. {
  303. [self dismissAllModalPresenters:allPresentedViewControllers resolver:resolve];
  304. }
  305. }
  306. RCT_EXPORT_METHOD(
  307. showNotification:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  308. {
  309. [RCCNotification showWithParams:params resolver:resolve rejecter:reject];
  310. }
  311. RCT_EXPORT_METHOD(
  312. dismissNotification:(NSDictionary*)params resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
  313. {
  314. [RCCNotification dismissWithParams:params resolver:resolve rejecter:reject];
  315. }
  316. RCT_EXPORT_METHOD(
  317. cancelAllReactTouches)
  318. {
  319. [RCCManagerModule cancelAllRCCViewControllerReactTouches];
  320. }
  321. @end