1 | #import "RNSModule.h"
|
2 | #import <React/RCTBridge+Private.h>
|
3 | #import <React/RCTBridge.h>
|
4 | #import <React/RCTUIManager.h>
|
5 | #import <React/RCTUIManagerUtils.h>
|
6 | #import <React/RCTUtils.h>
|
7 | #include <jsi/jsi.h>
|
8 | #import "RNSScreenStack.h"
|
9 | #import "RNScreensTurboModule.h"
|
10 |
|
11 | NS_ASSUME_NONNULL_BEGIN
|
12 |
|
13 | @implementation RNSModule {
|
14 | std::atomic<bool> isActiveTransition;
|
15 | }
|
16 |
|
17 | RCT_EXPORT_MODULE()
|
18 |
|
19 | #ifdef RCT_NEW_ARCH_ENABLED
|
20 | @synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED;
|
21 | #endif // RCT_NEW_ARCH_ENABLED
|
22 | @synthesize bridge = _bridge;
|
23 |
|
24 | - (dispatch_queue_t)methodQueue
|
25 | {
|
26 |
|
27 |
|
28 | return dispatch_get_main_queue();
|
29 | }
|
30 |
|
31 | - (NSDictionary *)constantsToExport
|
32 | {
|
33 | [self installHostObject];
|
34 | return @{};
|
35 | }
|
36 |
|
37 | + (BOOL)requiresMainQueueSetup
|
38 | {
|
39 | return NO;
|
40 | }
|
41 |
|
42 | - (RNSScreenStackView *)getScreenStackView:(NSNumber *)reactTag
|
43 | {
|
44 | RCTAssertMainQueue();
|
45 | RNSScreenStackView *view;
|
46 | #ifdef RCT_NEW_ARCH_ENABLED
|
47 | view = (RNSScreenStackView *)[self.viewRegistry_DEPRECATED viewForReactTag:reactTag];
|
48 | #else
|
49 | view = (RNSScreenStackView *)[self.bridge.uiManager viewForReactTag:reactTag];
|
50 | #endif // RCT_NEW_ARCH_ENABLED
|
51 | return view;
|
52 | }
|
53 |
|
54 | - (NSArray<NSNumber *> *)startTransition:(NSNumber *)stackTag
|
55 | {
|
56 | RCTAssertMainQueue();
|
57 | RNSScreenStackView *stackView = [self getStackView:stackTag];
|
58 | if (stackView == nil || isActiveTransition) {
|
59 | return @[ @(-1), @(-1) ];
|
60 | }
|
61 | NSArray<NSNumber *> *screenTags = @[ @(-1), @(-1) ];
|
62 | auto screens = stackView.reactViewController.childViewControllers;
|
63 | unsigned long screenCount = [screens count];
|
64 | if (screenCount > 1) {
|
65 | UIView *topScreen = screens[screenCount - 1].view;
|
66 | UIView *belowTopScreen = screens[screenCount - 2].view;
|
67 | belowTopScreen.transform = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
|
68 | isActiveTransition = true;
|
69 | #ifdef RCT_NEW_ARCH_ENABLED
|
70 | screenTags = @[ @(topScreen.tag), @(belowTopScreen.tag) ];
|
71 | #else
|
72 | screenTags = @[ topScreen.reactTag, belowTopScreen.reactTag ];
|
73 | #endif // RCT_NEW_ARCH_ENABLED
|
74 | [stackView startScreenTransition];
|
75 | }
|
76 | return screenTags;
|
77 | }
|
78 |
|
79 | - (bool)updateTransition:(NSNumber *)stackTag progress:(double)progress
|
80 | {
|
81 | RCTAssertMainQueue();
|
82 | RNSScreenStackView *stackView = [self getStackView:stackTag];
|
83 | if (stackView == nil || !isActiveTransition) {
|
84 | return false;
|
85 | }
|
86 | [stackView updateScreenTransition:progress];
|
87 | return true;
|
88 | }
|
89 |
|
90 | - (bool)finishTransition:(NSNumber *)stackTag canceled:(bool)canceled
|
91 | {
|
92 | RCTAssertMainQueue();
|
93 | RNSScreenStackView *stackView = [self getStackView:stackTag];
|
94 | if (stackView == nil || !isActiveTransition) {
|
95 | return false;
|
96 | }
|
97 | [stackView finishScreenTransition:canceled];
|
98 | if (!canceled) {
|
99 | stackView.disableSwipeBack = NO;
|
100 | }
|
101 | isActiveTransition = false;
|
102 | return true;
|
103 | }
|
104 |
|
105 | - (void)disableSwipeBackForTopScreen:(NSNumber *)stackTag
|
106 | {
|
107 | RCTAssertMainQueue();
|
108 | RNSScreenStackView *stackView = [self getStackView:stackTag];
|
109 | if (stackView == nil) {
|
110 | return;
|
111 | }
|
112 | stackView.disableSwipeBack = YES;
|
113 | }
|
114 |
|
115 | - (RNSScreenStackView *)getStackView:(NSNumber *)stackTag
|
116 | {
|
117 | RNSScreenStackView *view = [self getScreenStackView:stackTag];
|
118 | if (view != nil && ![view isKindOfClass:[RNSScreenStackView class]]) {
|
119 | RCTLogError(@"Invalid view type, expecting RNSScreenStackView, got: %@", view);
|
120 | return nil;
|
121 | }
|
122 | return view;
|
123 | }
|
124 |
|
125 | #ifdef RCT_NEW_ARCH_ENABLED
|
126 | - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
127 | (const facebook::react::ObjCTurboModule::InitParams &)params
|
128 | {
|
129 | [self installHostObject];
|
130 | return std::make_shared<facebook::react::NativeScreensModuleSpecJSI>(params);
|
131 | }
|
132 | #endif
|
133 |
|
134 | - (void)installHostObject
|
135 | {
|
136 | |
137 |
|
138 |
|
139 |
|
140 |
|
141 | RCTCxxBridge *cxxBridge = (RCTCxxBridge *)self.bridge;
|
142 | if (cxxBridge != nil) {
|
143 | auto jsiRuntime = (jsi::Runtime *)cxxBridge.runtime;
|
144 | if (jsiRuntime != nil) {
|
145 | auto &runtime = *jsiRuntime;
|
146 | __weak auto weakSelf = self;
|
147 |
|
148 | const auto &startTransition = [weakSelf](int stackTag) -> std::array<int, 2> {
|
149 | auto screensTags = [weakSelf startTransition:@(stackTag)];
|
150 | return {[screensTags[0] intValue], [screensTags[1] intValue]};
|
151 | };
|
152 | const auto &updateTransition = [weakSelf](int stackTag, double progress) {
|
153 | [weakSelf updateTransition:@(stackTag) progress:progress];
|
154 | };
|
155 | const auto &finishTransition = [weakSelf](int stackTag, bool canceled) {
|
156 | [weakSelf finishTransition:@(stackTag) canceled:canceled];
|
157 | };
|
158 | const auto &disableSwipeBackForTopScreen = [weakSelf](int stackTag) {
|
159 | [weakSelf disableSwipeBackForTopScreen:@(stackTag)];
|
160 | };
|
161 |
|
162 | auto rnScreensModule = std::make_shared<RNScreens::RNScreensTurboModule>(
|
163 | startTransition, updateTransition, finishTransition, disableSwipeBackForTopScreen);
|
164 | auto rnScreensModuleHostObject = jsi::Object::createFromHostObject(runtime, rnScreensModule);
|
165 | runtime.global().setProperty(
|
166 | runtime, RNScreens::RNScreensTurboModule::MODULE_NAME, std::move(rnScreensModuleHostObject));
|
167 | }
|
168 | }
|
169 | }
|
170 |
|
171 | @end
|
172 |
|
173 | NS_ASSUME_NONNULL_END
|