@onekeyfe/react-native-background-thread 1.1.48 → 1.1.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/backgroundthread/BackgroundThreadManager.kt +39 -0
- package/android/src/main/java/com/backgroundthread/BackgroundThreadModule.kt +11 -0
- package/ios/BackgroundRunnerReactNativeDelegate.h +7 -0
- package/ios/BackgroundRunnerReactNativeDelegate.mm +28 -0
- package/ios/BackgroundThread.h +4 -0
- package/ios/BackgroundThread.mm +16 -0
- package/ios/BackgroundThreadManager.h +8 -0
- package/ios/BackgroundThreadManager.mm +36 -0
- package/lib/module/NativeBackgroundThread.js.map +1 -1
- package/lib/typescript/src/NativeBackgroundThread.d.ts +1 -0
- package/lib/typescript/src/NativeBackgroundThread.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/NativeBackgroundThread.ts +4 -0
|
@@ -242,6 +242,45 @@ class BackgroundThreadManager private constructor() {
|
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
+
// ── Segment Registration (Phase 2.5 spike) ─────────────────────────────
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Register a HBC segment in the background runtime.
|
|
249
|
+
* Uses CatalystInstance.registerSegment() on the background ReactContext.
|
|
250
|
+
*
|
|
251
|
+
* @param segmentId The segment ID to register
|
|
252
|
+
* @param path Absolute file path to the .seg.hbc file
|
|
253
|
+
* @throws IllegalStateException if background runtime is not started
|
|
254
|
+
* @throws IllegalArgumentException if segment file does not exist
|
|
255
|
+
*/
|
|
256
|
+
fun registerSegmentInBackground(segmentId: Int, path: String) {
|
|
257
|
+
if (!isStarted) {
|
|
258
|
+
throw IllegalStateException("Background runtime not started")
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
val file = File(path)
|
|
262
|
+
if (!file.exists()) {
|
|
263
|
+
throw IllegalArgumentException("Segment file not found: $path")
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
val context = bgReactHost?.currentReactContext
|
|
267
|
+
?: throw IllegalStateException("Background ReactContext not available")
|
|
268
|
+
|
|
269
|
+
context.runOnJSQueueThread {
|
|
270
|
+
try {
|
|
271
|
+
if (context.hasCatalystInstance()) {
|
|
272
|
+
context.catalystInstance.registerSegment(segmentId, path)
|
|
273
|
+
BTLogger.info("Segment registered in background runtime: id=$segmentId, path=$path")
|
|
274
|
+
} else {
|
|
275
|
+
BTLogger.error("Background CatalystInstance not available for segment registration")
|
|
276
|
+
}
|
|
277
|
+
} catch (e: Exception) {
|
|
278
|
+
BTLogger.error("Failed to register segment in background runtime: ${e.message}")
|
|
279
|
+
throw e
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
245
284
|
// ── Lifecycle ───────────────────────────────────────────────────────────
|
|
246
285
|
|
|
247
286
|
val isBackgroundStarted: Boolean get() = isStarted
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.backgroundthread
|
|
2
2
|
|
|
3
|
+
import com.facebook.react.bridge.Promise
|
|
3
4
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
5
|
import com.facebook.react.module.annotations.ReactModule
|
|
5
6
|
|
|
@@ -26,4 +27,14 @@ class BackgroundThreadModule(reactContext: ReactApplicationContext) :
|
|
|
26
27
|
override fun startBackgroundRunnerWithEntryURL(entryURL: String) {
|
|
27
28
|
BackgroundThreadManager.getInstance().startBackgroundRunnerWithEntryURL(reactApplicationContext, entryURL)
|
|
28
29
|
}
|
|
30
|
+
|
|
31
|
+
override fun loadSegmentInBackground(segmentId: Double, path: String, promise: Promise) {
|
|
32
|
+
try {
|
|
33
|
+
BackgroundThreadManager.getInstance()
|
|
34
|
+
.registerSegmentInBackground(segmentId.toInt(), path)
|
|
35
|
+
promise.resolve(null)
|
|
36
|
+
} catch (e: Exception) {
|
|
37
|
+
promise.reject("BG_SEGMENT_LOAD_ERROR", e.message, e)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
29
40
|
}
|
|
@@ -31,6 +31,13 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
31
31
|
*/
|
|
32
32
|
- (instancetype)init;
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Register a HBC segment in the background runtime (Phase 2.5 spike).
|
|
36
|
+
* Uses RCTInstance's registerSegmentWithId:path: API.
|
|
37
|
+
* Must be called after hostDidStart: has completed.
|
|
38
|
+
*/
|
|
39
|
+
- (BOOL)registerSegmentWithId:(NSNumber *)segmentId path:(NSString *)path;
|
|
40
|
+
|
|
34
41
|
@end
|
|
35
42
|
|
|
36
43
|
NS_ASSUME_NONNULL_END
|
|
@@ -222,6 +222,34 @@ static NSURL *resolveBundleSourceURL(NSString *jsBundleSourceNS)
|
|
|
222
222
|
}];
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
+
#pragma mark - Segment Registration (Phase 2.5 spike)
|
|
226
|
+
|
|
227
|
+
- (BOOL)registerSegmentWithId:(NSNumber *)segmentId path:(NSString *)path
|
|
228
|
+
{
|
|
229
|
+
if (!_rctInstance) {
|
|
230
|
+
[BTLogger error:@"Cannot register segment: background RCTInstance not available"];
|
|
231
|
+
return NO;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
@try {
|
|
235
|
+
SEL sel = NSSelectorFromString(@"registerSegmentWithId:path:");
|
|
236
|
+
if ([_rctInstance respondsToSelector:sel]) {
|
|
237
|
+
#pragma clang diagnostic push
|
|
238
|
+
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
|
239
|
+
[_rctInstance performSelector:sel withObject:segmentId withObject:path];
|
|
240
|
+
#pragma clang diagnostic pop
|
|
241
|
+
[BTLogger info:[NSString stringWithFormat:@"Segment registered in background runtime: id=%@, path=%@", segmentId, path]];
|
|
242
|
+
return YES;
|
|
243
|
+
} else {
|
|
244
|
+
[BTLogger error:@"RCTInstance does not respond to registerSegmentWithId:path:"];
|
|
245
|
+
return NO;
|
|
246
|
+
}
|
|
247
|
+
} @catch (NSException *exception) {
|
|
248
|
+
[BTLogger error:[NSString stringWithFormat:@"Failed to register segment: %@", exception.reason]];
|
|
249
|
+
return NO;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
225
253
|
#pragma mark - RCTTurboModuleManagerDelegate
|
|
226
254
|
|
|
227
255
|
- (id<RCTModuleProvider>)getModuleProvider:(const char *)name
|
package/ios/BackgroundThread.h
CHANGED
|
@@ -5,5 +5,9 @@
|
|
|
5
5
|
- (void)startBackgroundRunner;
|
|
6
6
|
- (void)startBackgroundRunnerWithEntryURL:(NSString *)entryURL;
|
|
7
7
|
- (void)installSharedBridge;
|
|
8
|
+
- (void)loadSegmentInBackground:(double)segmentId
|
|
9
|
+
path:(NSString *)path
|
|
10
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
11
|
+
reject:(RCTPromiseRejectBlock)reject;
|
|
8
12
|
|
|
9
13
|
@end
|
package/ios/BackgroundThread.mm
CHANGED
|
@@ -29,6 +29,22 @@
|
|
|
29
29
|
[BTLogger info:@"installSharedBridge called (no-op on iOS, installed from AppDelegate)"];
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
- (void)loadSegmentInBackground:(double)segmentId
|
|
33
|
+
path:(NSString *)path
|
|
34
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
35
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
36
|
+
BackgroundThreadManager *manager = [BackgroundThreadManager sharedInstance];
|
|
37
|
+
[manager registerSegmentInBackground:@((int)segmentId)
|
|
38
|
+
path:path
|
|
39
|
+
completion:^(NSError * _Nullable error) {
|
|
40
|
+
if (error) {
|
|
41
|
+
reject(@"BG_SEGMENT_LOAD_ERROR", error.localizedDescription, error);
|
|
42
|
+
} else {
|
|
43
|
+
resolve(nil);
|
|
44
|
+
}
|
|
45
|
+
}];
|
|
46
|
+
}
|
|
47
|
+
|
|
32
48
|
+ (NSString *)moduleName
|
|
33
49
|
{
|
|
34
50
|
return @"BackgroundThread";
|
|
@@ -26,6 +26,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
26
26
|
/// Check if background runner is started
|
|
27
27
|
@property (nonatomic, readonly) BOOL isStarted;
|
|
28
28
|
|
|
29
|
+
/// Register a HBC segment in the background runtime (Phase 2.5 spike)
|
|
30
|
+
/// @param segmentId The segment ID to register
|
|
31
|
+
/// @param path Absolute file path to the .seg.hbc file
|
|
32
|
+
/// @param completion Callback with nil error on success, or NSError on failure
|
|
33
|
+
- (void)registerSegmentInBackground:(NSNumber *)segmentId
|
|
34
|
+
path:(NSString *)path
|
|
35
|
+
completion:(void (^)(NSError * _Nullable error))completion;
|
|
36
|
+
|
|
29
37
|
@end
|
|
30
38
|
|
|
31
39
|
NS_ASSUME_NONNULL_END
|
|
@@ -115,4 +115,40 @@ static NSString *const MODULE_DEBUG_URL = @"http://localhost:8082/apps/mobile/ba
|
|
|
115
115
|
});
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
#pragma mark - Segment Registration (Phase 2.5 spike)
|
|
119
|
+
|
|
120
|
+
- (void)registerSegmentInBackground:(NSNumber *)segmentId
|
|
121
|
+
path:(NSString *)path
|
|
122
|
+
completion:(void (^)(NSError * _Nullable error))completion
|
|
123
|
+
{
|
|
124
|
+
if (!self.isStarted || !self.reactNativeFactoryDelegate) {
|
|
125
|
+
NSError *error = [NSError errorWithDomain:@"BackgroundThread"
|
|
126
|
+
code:1
|
|
127
|
+
userInfo:@{NSLocalizedDescriptionKey: @"Background runtime not started"}];
|
|
128
|
+
if (completion) completion(error);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Verify the file exists
|
|
133
|
+
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
|
|
134
|
+
NSError *error = [NSError errorWithDomain:@"BackgroundThread"
|
|
135
|
+
code:2
|
|
136
|
+
userInfo:@{NSLocalizedDescriptionKey:
|
|
137
|
+
[NSString stringWithFormat:@"Segment file not found: %@", path]}];
|
|
138
|
+
if (completion) completion(error);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
BOOL success = [self.reactNativeFactoryDelegate registerSegmentWithId:segmentId path:path];
|
|
143
|
+
if (success) {
|
|
144
|
+
if (completion) completion(nil);
|
|
145
|
+
} else {
|
|
146
|
+
NSError *error = [NSError errorWithDomain:@"BackgroundThread"
|
|
147
|
+
code:3
|
|
148
|
+
userInfo:@{NSLocalizedDescriptionKey:
|
|
149
|
+
@"Failed to register segment in background runtime"}];
|
|
150
|
+
if (completion) completion(error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
118
154
|
@end
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeBackgroundThread.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAAQ,cAAc;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeBackgroundThread.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAAQ,cAAc;AAYlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,kBAAkB,CAAC","ignoreList":[]}
|
|
@@ -2,6 +2,7 @@ import type { TurboModule } from 'react-native';
|
|
|
2
2
|
export interface Spec extends TurboModule {
|
|
3
3
|
startBackgroundRunnerWithEntryURL(entryURL: string): void;
|
|
4
4
|
installSharedBridge(): void;
|
|
5
|
+
loadSegmentInBackground(segmentId: number, path: string): Promise<void>;
|
|
5
6
|
}
|
|
6
7
|
declare const _default: Spec;
|
|
7
8
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeBackgroundThread.d.ts","sourceRoot":"","sources":["../../../src/NativeBackgroundThread.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,iCAAiC,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,mBAAmB,IAAI,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"NativeBackgroundThread.d.ts","sourceRoot":"","sources":["../../../src/NativeBackgroundThread.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,iCAAiC,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D,mBAAmB,IAAI,IAAI,CAAC;IAC5B,uBAAuB,CACrB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;;AAED,wBAA0E"}
|
package/package.json
CHANGED
|
@@ -4,6 +4,10 @@ import type { TurboModule } from 'react-native';
|
|
|
4
4
|
export interface Spec extends TurboModule {
|
|
5
5
|
startBackgroundRunnerWithEntryURL(entryURL: string): void;
|
|
6
6
|
installSharedBridge(): void;
|
|
7
|
+
loadSegmentInBackground(
|
|
8
|
+
segmentId: number,
|
|
9
|
+
path: string,
|
|
10
|
+
): Promise<void>;
|
|
7
11
|
}
|
|
8
12
|
|
|
9
13
|
export default TurboModuleRegistry.getEnforcing<Spec>('BackgroundThread');
|