@unif/react-native-hms-scan 0.6.1 → 1.0.0

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.
Files changed (168) hide show
  1. package/README.md +24 -72
  2. package/android/src/main/AndroidManifest.xml +0 -9
  3. package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanImage.kt +135 -0
  4. package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanModule.kt +163 -147
  5. package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanResultMapper.kt +17 -9
  6. package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanView.kt +57 -19
  7. package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanViewManager.kt +1 -1
  8. package/ios/HmsScanModule.mm +13 -37
  9. package/ios/HmsScanResultMapper.h +4 -3
  10. package/ios/HmsScanResultMapper.mm +31 -19
  11. package/ios/HmsScanView.h +1 -1
  12. package/ios/HmsScanView.mm +140 -25
  13. package/lib/module/HmsScanView/HmsScanView.js +66 -0
  14. package/lib/module/HmsScanView/HmsScanView.js.map +1 -0
  15. package/lib/module/HmsScanView/HmsScanView.web.js +26 -0
  16. package/lib/module/HmsScanView/HmsScanView.web.js.map +1 -0
  17. package/lib/module/HmsScanView/types.js +4 -0
  18. package/lib/module/HmsScanView/types.js.map +1 -0
  19. package/lib/module/HmsScanViewNativeComponent.ts +7 -5
  20. package/lib/module/NativeHmsScan.js +1 -1
  21. package/lib/module/NativeHmsScan.js.map +1 -1
  22. package/lib/module/ScanError.js +12 -0
  23. package/lib/module/ScanError.js.map +1 -0
  24. package/lib/module/Scanner/DeniedOverlay.js +1 -1
  25. package/lib/module/Scanner/DeniedOverlay.js.map +1 -1
  26. package/lib/module/Scanner/ResultFail.js +3 -2
  27. package/lib/module/Scanner/ResultFail.js.map +1 -1
  28. package/lib/module/Scanner/ResultFocus/ResultFocus.js +56 -0
  29. package/lib/module/Scanner/ResultFocus/ResultFocus.js.map +1 -0
  30. package/lib/module/Scanner/ResultFocus/styles.js +39 -0
  31. package/lib/module/Scanner/ResultFocus/styles.js.map +1 -0
  32. package/lib/module/Scanner/ResultFocus/types.js +4 -0
  33. package/lib/module/Scanner/ResultFocus/types.js.map +1 -0
  34. package/lib/module/Scanner/ScanHint.js +6 -3
  35. package/lib/module/Scanner/ScanHint.js.map +1 -1
  36. package/lib/module/Scanner/ScanToolbar.js +6 -3
  37. package/lib/module/Scanner/ScanToolbar.js.map +1 -1
  38. package/lib/module/Scanner/ScanTopBar.js +6 -3
  39. package/lib/module/Scanner/ScanTopBar.js.map +1 -1
  40. package/lib/module/Scanner/Scanner.js +9 -311
  41. package/lib/module/Scanner/Scanner.js.map +1 -1
  42. package/lib/module/Scanner/Scanner.web.js +29 -0
  43. package/lib/module/Scanner/Scanner.web.js.map +1 -0
  44. package/lib/module/Scanner/ScannerInner.js +310 -0
  45. package/lib/module/Scanner/ScannerInner.js.map +1 -0
  46. package/lib/module/Scanner/styles.js +11 -0
  47. package/lib/module/Scanner/styles.js.map +1 -0
  48. package/lib/module/Scanner/types.js +4 -0
  49. package/lib/module/Scanner/types.js.map +1 -0
  50. package/lib/module/constants.js +20 -0
  51. package/lib/module/constants.js.map +1 -0
  52. package/lib/module/decodeImage.js +29 -24
  53. package/lib/module/decodeImage.js.map +1 -1
  54. package/lib/module/decodeImage.web.js +7 -0
  55. package/lib/module/decodeImage.web.js.map +1 -0
  56. package/lib/module/errors.js +24 -0
  57. package/lib/module/errors.js.map +1 -0
  58. package/lib/module/format.js +53 -47
  59. package/lib/module/format.js.map +1 -1
  60. package/lib/module/index.js +5 -19
  61. package/lib/module/index.js.map +1 -1
  62. package/lib/module/index.web.js +8 -0
  63. package/lib/module/index.web.js.map +1 -0
  64. package/lib/module/mock.js +2 -23
  65. package/lib/module/mock.js.map +1 -1
  66. package/lib/module/permissions.js +24 -20
  67. package/lib/module/permissions.js.map +1 -1
  68. package/lib/module/permissions.web.js +10 -0
  69. package/lib/module/permissions.web.js.map +1 -0
  70. package/lib/module/types.js +1 -45
  71. package/lib/module/types.js.map +1 -1
  72. package/lib/typescript/src/HmsScanView/HmsScanView.d.ts +3 -0
  73. package/lib/typescript/src/HmsScanView/HmsScanView.d.ts.map +1 -0
  74. package/lib/typescript/src/HmsScanView/HmsScanView.web.d.ts +3 -0
  75. package/lib/typescript/src/HmsScanView/HmsScanView.web.d.ts.map +1 -0
  76. package/lib/typescript/src/HmsScanView/types.d.ts +12 -0
  77. package/lib/typescript/src/HmsScanView/types.d.ts.map +1 -0
  78. package/lib/typescript/src/HmsScanViewNativeComponent.d.ts +6 -4
  79. package/lib/typescript/src/HmsScanViewNativeComponent.d.ts.map +1 -1
  80. package/lib/typescript/src/NativeHmsScan.d.ts +3 -5
  81. package/lib/typescript/src/NativeHmsScan.d.ts.map +1 -1
  82. package/lib/typescript/src/ScanError.d.ts +7 -0
  83. package/lib/typescript/src/ScanError.d.ts.map +1 -0
  84. package/lib/typescript/src/Scanner/DeniedOverlay.d.ts.map +1 -1
  85. package/lib/typescript/src/Scanner/ResultFail.d.ts +2 -1
  86. package/lib/typescript/src/Scanner/ResultFail.d.ts.map +1 -1
  87. package/lib/typescript/src/Scanner/ResultFocus/ResultFocus.d.ts +4 -0
  88. package/lib/typescript/src/Scanner/ResultFocus/ResultFocus.d.ts.map +1 -0
  89. package/lib/typescript/src/Scanner/ResultFocus/styles.d.ts +36 -0
  90. package/lib/typescript/src/Scanner/ResultFocus/styles.d.ts.map +1 -0
  91. package/lib/typescript/src/Scanner/ResultFocus/types.d.ts +8 -0
  92. package/lib/typescript/src/Scanner/ResultFocus/types.d.ts.map +1 -0
  93. package/lib/typescript/src/Scanner/ScanHint.d.ts.map +1 -1
  94. package/lib/typescript/src/Scanner/ScanToolbar.d.ts.map +1 -1
  95. package/lib/typescript/src/Scanner/ScanTopBar.d.ts.map +1 -1
  96. package/lib/typescript/src/Scanner/Scanner.d.ts +2 -45
  97. package/lib/typescript/src/Scanner/Scanner.d.ts.map +1 -1
  98. package/lib/typescript/src/Scanner/Scanner.web.d.ts +3 -0
  99. package/lib/typescript/src/Scanner/Scanner.web.d.ts.map +1 -0
  100. package/lib/typescript/src/Scanner/ScannerInner.d.ts +3 -0
  101. package/lib/typescript/src/Scanner/ScannerInner.d.ts.map +1 -0
  102. package/lib/typescript/src/Scanner/styles.d.ts +7 -0
  103. package/lib/typescript/src/Scanner/styles.d.ts.map +1 -0
  104. package/lib/typescript/src/Scanner/types.d.ts +20 -0
  105. package/lib/typescript/src/Scanner/types.d.ts.map +1 -0
  106. package/lib/typescript/src/constants.d.ts +8 -0
  107. package/lib/typescript/src/constants.d.ts.map +1 -0
  108. package/lib/typescript/src/decodeImage.d.ts +2 -12
  109. package/lib/typescript/src/decodeImage.d.ts.map +1 -1
  110. package/lib/typescript/src/decodeImage.web.d.ts +3 -0
  111. package/lib/typescript/src/decodeImage.web.d.ts.map +1 -0
  112. package/lib/typescript/src/errors.d.ts +6 -0
  113. package/lib/typescript/src/errors.d.ts.map +1 -0
  114. package/lib/typescript/src/format.d.ts +15 -12
  115. package/lib/typescript/src/format.d.ts.map +1 -1
  116. package/lib/typescript/src/index.d.ts +6 -7
  117. package/lib/typescript/src/index.d.ts.map +1 -1
  118. package/lib/typescript/src/index.web.d.ts +9 -0
  119. package/lib/typescript/src/index.web.d.ts.map +1 -0
  120. package/lib/typescript/src/mock.d.ts +9 -8
  121. package/lib/typescript/src/mock.d.ts.map +1 -1
  122. package/lib/typescript/src/permissions.d.ts +4 -8
  123. package/lib/typescript/src/permissions.d.ts.map +1 -1
  124. package/lib/typescript/src/permissions.web.d.ts +4 -0
  125. package/lib/typescript/src/permissions.web.d.ts.map +1 -0
  126. package/lib/typescript/src/types.d.ts +31 -56
  127. package/lib/typescript/src/types.d.ts.map +1 -1
  128. package/package.json +9 -2
  129. package/src/HmsScanView/HmsScanView.tsx +67 -0
  130. package/src/HmsScanView/HmsScanView.web.tsx +22 -0
  131. package/src/HmsScanView/types.ts +17 -0
  132. package/src/HmsScanViewNativeComponent.ts +7 -5
  133. package/src/NativeHmsScan.ts +3 -5
  134. package/src/ScanError.ts +13 -0
  135. package/src/Scanner/DeniedOverlay.tsx +4 -2
  136. package/src/Scanner/ResultFail.tsx +23 -5
  137. package/src/Scanner/ResultFocus/ResultFocus.tsx +43 -0
  138. package/src/Scanner/ResultFocus/styles.ts +25 -0
  139. package/src/Scanner/ResultFocus/types.ts +8 -0
  140. package/src/Scanner/ScanHint.tsx +16 -11
  141. package/src/Scanner/ScanToolbar.tsx +35 -13
  142. package/src/Scanner/ScanTopBar.tsx +20 -12
  143. package/src/Scanner/Scanner.tsx +13 -436
  144. package/src/Scanner/Scanner.web.tsx +26 -0
  145. package/src/Scanner/ScannerInner.tsx +391 -0
  146. package/src/Scanner/styles.ts +6 -0
  147. package/src/Scanner/types.ts +36 -0
  148. package/src/constants.ts +55 -0
  149. package/src/decodeImage.ts +35 -29
  150. package/src/decodeImage.web.ts +8 -0
  151. package/src/errors.ts +26 -0
  152. package/src/format.ts +77 -76
  153. package/src/index.tsx +17 -32
  154. package/src/index.web.tsx +22 -0
  155. package/src/mock.ts +21 -29
  156. package/src/permissions.ts +33 -20
  157. package/src/permissions.web.ts +9 -0
  158. package/src/types.ts +38 -126
  159. package/lib/module/HmsScanView.js +0 -43
  160. package/lib/module/HmsScanView.js.map +0 -1
  161. package/lib/module/Scanner/ResultFocus.js +0 -171
  162. package/lib/module/Scanner/ResultFocus.js.map +0 -1
  163. package/lib/typescript/src/HmsScanView.d.ts +0 -33
  164. package/lib/typescript/src/HmsScanView.d.ts.map +0 -1
  165. package/lib/typescript/src/Scanner/ResultFocus.d.ts +0 -14
  166. package/lib/typescript/src/Scanner/ResultFocus.d.ts.map +0 -1
  167. package/src/HmsScanView.tsx +0 -87
  168. package/src/Scanner/ResultFocus.tsx +0 -122
@@ -20,6 +20,7 @@
20
20
  #import <ScanKitFrameWork/ScanKitFrameWork.h>
21
21
 
22
22
  using namespace facebook::react;
23
+ static void *HmsScanTorchObservation = &HmsScanTorchObservation;
23
24
 
24
25
  @interface HmsScanView () <CustomizedScanDelegate>
25
26
  @end
@@ -34,6 +35,12 @@ using namespace facebook::react;
34
35
  BOOL _appliedTorch;
35
36
  BOOL _hasAppliedOnce;
36
37
  BOOL _childAttached;
38
+ AVCaptureDevice *_torchDevice;
39
+ BOOL _observingTorch;
40
+ BOOL _awaitingTorchOff;
41
+ BOOL _hasTorchReport;
42
+ BOOL _lastTorchOn;
43
+ BOOL _lastTorchAvailable;
37
44
  }
38
45
 
39
46
  #pragma mark - Codegen wiring
@@ -54,7 +61,7 @@ using namespace facebook::react;
54
61
  _hasAppliedOnce = NO;
55
62
  _childAttached = NO;
56
63
 
57
- [self buildScanViewControllerWithCsv:_appliedFormatsCsv];
64
+ // Fabric supplies the initial props before mounting. Construct only that configuration.
58
65
  }
59
66
  return self;
60
67
  }
@@ -67,6 +74,11 @@ using namespace facebook::react;
67
74
  // change requires rebuilding the controller.
68
75
  [self teardownScanViewController];
69
76
 
77
+ _appliedFormatsCsv = csv ?: @"";
78
+ if ([HmsScanResultMapper unsupportedFormatInCsv:csv] != nil) {
79
+ [self emitScanErrorWithCode:@"E_UNSUPPORTED_FORMAT" message:@"iOS ScanKit 不支持请求的码制"];
80
+ return;
81
+ }
70
82
  unsigned int formatType = [HmsScanResultMapper scanFormatTypeFromCsv:csv];
71
83
  HmsScanOptions *options = [[HmsScanOptions alloc] initWithScanFormatType:formatType Photo:NO];
72
84
 
@@ -135,8 +147,23 @@ using namespace facebook::react;
135
147
  - (void)didMoveToWindow {
136
148
  [super didMoveToWindow];
137
149
  if (self.window != nil) {
150
+ _awaitingTorchOff = NO;
151
+ if ([HmsScanResultMapper unsupportedFormatInCsv:_appliedFormatsCsv] != nil) {
152
+ [self emitScanErrorWithCode:@"E_UNSUPPORTED_FORMAT" message:@"iOS ScanKit 不支持请求的码制"];
153
+ }
138
154
  [self attachChildViewController];
155
+ if (_scanVC != nil) {
156
+ [self startObservingTorch];
157
+ [self applyTorch:_appliedTorch];
158
+ }
139
159
  } else {
160
+ _awaitingTorchOff = YES;
161
+ [self applyTorch:NO];
162
+ // torchMode can change before torchActive. Keep observing until the device
163
+ // confirms shutdown, or until this view is recycled/deallocated.
164
+ if (!_torchDevice.isTorchActive) {
165
+ [self stopObservingTorch];
166
+ }
140
167
  [self detachChildViewController];
141
168
  }
142
169
  }
@@ -155,9 +182,10 @@ using namespace facebook::react;
155
182
  BOOL newTorch = newViewProps.torch;
156
183
 
157
184
  BOOL first = !_hasAppliedOnce;
185
+ BOOL rebuilt = first || ![newCsv isEqualToString:_appliedFormatsCsv];
158
186
 
159
187
  // formatsCsv change -> rebuild the controller (carry over continuous/paused).
160
- if (first || ![newCsv isEqualToString:_appliedFormatsCsv]) {
188
+ if (rebuilt) {
161
189
  _appliedContinuous = newContinuous;
162
190
  _appliedPaused = newPaused;
163
191
  [self buildScanViewControllerWithCsv:newCsv];
@@ -179,9 +207,11 @@ using namespace facebook::react;
179
207
  }
180
208
 
181
209
  // torch change (best-effort, see applyTorch:).
182
- if (first || newTorch != _appliedTorch) {
183
- _appliedTorch = newTorch;
184
- [self applyTorch:newTorch];
210
+ BOOL torchChanged = newTorch != _appliedTorch;
211
+ _appliedTorch = newTorch;
212
+ if (self.window != nil && _scanVC != nil && (rebuilt || torchChanged)) {
213
+ [self startObservingTorch];
214
+ [self applyTorch:_appliedTorch];
185
215
  }
186
216
 
187
217
  _hasAppliedOnce = YES;
@@ -191,20 +221,23 @@ using namespace facebook::react;
191
221
 
192
222
  #pragma mark - Torch (best-effort)
193
223
 
194
- // HUAWEI Scan Kit exposes NO public torch API on iOS — HmsCustomScanViewController
195
- // renders its own torch button and auto-detects low light. We therefore drive the
196
- // torch directly through AVFoundation as a best-effort convenience. This is NOT
197
- // guaranteed to stay in sync with HUAWEI's built-in torch button, and may be a
198
- // no-op if HUAWEI holds an exclusive lock on the capture device's configuration.
224
+ // ScanKit has no public torch command. Observe the same AVCaptureDevice we
225
+ // configure, including changes made by the SDK or system. A configuration lock
226
+ // failure still reports the device's real state.
199
227
  - (void)applyTorch:(BOOL)on {
200
228
  BOOL available = NO;
201
- BOOL torchOn = [self setTorchHardwareOn:on available:&available];
202
- [self emitTorchStatusAvailable:available on:torchOn];
229
+ BOOL commandFailed = NO;
230
+ BOOL torchOn = [self setTorchHardwareOn:on available:&available commandFailed:&commandFailed];
231
+ // A rejected command must acknowledge even an unchanged state so JS can retry.
232
+ // Accepted commands may update torchActive later; keep those observations deduplicated.
233
+ [self emitTorchStateAvailable:available on:torchOn force:commandFailed];
203
234
  }
204
235
 
205
236
  // 优先取「带手电的后置广角相机」(这通常就是华为扫码用的那颗);取不到再退回
206
237
  // 默认 video 设备。比已弃用的 defaultDeviceWithMediaType 更可能命中正确设备。
207
238
  - (AVCaptureDevice *)torchCaptureDevice {
239
+ if (_torchDevice != nil)
240
+ return _torchDevice;
208
241
  AVCaptureDeviceDiscoverySession *session =
209
242
  [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[ AVCaptureDeviceTypeBuiltInWideAngleCamera ]
210
243
  mediaType:AVMediaTypeVideo
@@ -217,32 +250,96 @@ using namespace facebook::react;
217
250
  return [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
218
251
  }
219
252
 
253
+ - (void)startObservingTorch {
254
+ if (_observingTorch)
255
+ return;
256
+ _torchDevice = [self torchCaptureDevice];
257
+ if (_torchDevice == nil)
258
+ return;
259
+ _observingTorch = YES;
260
+ [_torchDevice addObserver:self forKeyPath:@"torchActive" options:0 context:HmsScanTorchObservation];
261
+ [_torchDevice addObserver:self forKeyPath:@"torchAvailable" options:0 context:HmsScanTorchObservation];
262
+ }
263
+
264
+ - (void)stopObservingTorch {
265
+ if (_observingTorch) {
266
+ [_torchDevice removeObserver:self forKeyPath:@"torchActive" context:HmsScanTorchObservation];
267
+ [_torchDevice removeObserver:self forKeyPath:@"torchAvailable" context:HmsScanTorchObservation];
268
+ }
269
+ _observingTorch = NO;
270
+ _awaitingTorchOff = NO;
271
+ _torchDevice = nil;
272
+ }
273
+
274
+ - (void)observeValueForKeyPath:(NSString *)keyPath
275
+ ofObject:(id)object
276
+ change:(NSDictionary<NSKeyValueChangeKey, id> *)change
277
+ context:(void *)context {
278
+ if (context != HmsScanTorchObservation) {
279
+ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
280
+ return;
281
+ }
282
+ __weak HmsScanView *weakSelf = self;
283
+ void (^report)(void) = ^{
284
+ HmsScanView *view = weakSelf;
285
+ if (view == nil || !view->_observingTorch || view->_torchDevice != object)
286
+ return;
287
+ if (view.window == nil) {
288
+ if (view->_awaitingTorchOff) {
289
+ [view emitTorchStateAvailable:view->_torchDevice.hasTorch on:view->_torchDevice.isTorchActive force:NO];
290
+ if (!view->_torchDevice.isTorchActive)
291
+ [view stopObservingTorch];
292
+ }
293
+ return;
294
+ }
295
+ if ([keyPath isEqualToString:@"torchAvailable"] && view->_torchDevice.isTorchAvailable && view->_appliedTorch) {
296
+ [view applyTorch:YES];
297
+ } else {
298
+ [view emitTorchStateAvailable:view->_torchDevice.hasTorch on:view->_torchDevice.isTorchActive force:NO];
299
+ }
300
+ };
301
+ if ([NSThread isMainThread])
302
+ report();
303
+ else
304
+ dispatch_async(dispatch_get_main_queue(), report);
305
+ }
306
+
220
307
  // Mutates the capture device's torch. Returns the resulting on-state and writes
221
- // hardware availability into `available`. Does NOT emit any event (so it can be
222
- // reused on teardown/recycle without firing onTorchStatus on a stale emitter).
308
+ // hardware availability into `available` and rejection into `commandFailed`.
309
+ // Does NOT emit any event (so it can be reused on teardown/recycle without
310
+ // firing onTorchState on a stale emitter).
223
311
  //
224
312
  // best-effort:华为独占相机会话且无手电 API,这里直接操作设备硬件。可能因华为
225
313
  // 持有配置锁(lockForConfiguration 失败)或用了别的设备而不生效。DEBUG 日志会
226
314
  // 打印到底卡在哪一步,真机调试时看 Xcode console。
227
- - (BOOL)setTorchHardwareOn:(BOOL)on available:(BOOL *)available {
315
+ - (BOOL)setTorchHardwareOn:(BOOL)on available:(BOOL *)available commandFailed:(BOOL *)commandFailed {
228
316
  AVCaptureDevice *device = [self torchCaptureDevice];
229
317
  BOOL hasTorch = (device != nil && device.hasTorch);
230
318
  if (available != NULL) {
231
319
  *available = hasTorch;
232
320
  }
321
+ if (commandFailed != NULL) {
322
+ *commandFailed = NO;
323
+ }
233
324
  if (!hasTorch) {
325
+ if (commandFailed != NULL) {
326
+ *commandFailed = on;
327
+ }
234
328
  #if DEBUG
235
329
  NSLog(@"[HmsScanView] torch: 无带手电的相机设备 (device=%@)", device);
236
330
  #endif
237
331
  return NO;
238
332
  }
239
333
 
240
- BOOL torchOn = NO;
334
+ BOOL torchOn = device.isTorchActive;
241
335
  NSError *error = nil;
242
336
  if ([device lockForConfiguration:&error]) {
243
337
  if (on && device.isTorchAvailable && [device isTorchModeSupported:AVCaptureTorchModeOn]) {
244
338
  device.torchMode = AVCaptureTorchModeOn;
245
339
  } else {
340
+ if (commandFailed != NULL) {
341
+ *commandFailed = on;
342
+ }
246
343
  device.torchMode = AVCaptureTorchModeOff;
247
344
  }
248
345
  torchOn = device.isTorchActive; // 反映硬件真实状态,而非乐观假设
@@ -252,6 +349,9 @@ using namespace facebook::react;
252
349
  device.isTorchAvailable);
253
350
  #endif
254
351
  } else {
352
+ if (commandFailed != NULL) {
353
+ *commandFailed = YES;
354
+ }
255
355
  #if DEBUG
256
356
  NSLog(@"[HmsScanView] torch lockForConfiguration 失败(华为可能占用了设备配置锁): %@", error);
257
357
  #endif
@@ -264,14 +364,18 @@ using namespace facebook::react;
264
364
  // Called by HUAWEI on every decode (repeatedly in continuous mode). `resultDic`
265
365
  // is a single result dictionary; we wrap it into the contract's top-level array.
266
366
  - (void)customizedScanDelegateForResult:(NSDictionary *)resultDic {
267
- NSDictionary *mapped = [HmsScanResultMapper scanResultFromHuaweiDict:resultDic];
268
- if (mapped == nil) {
269
- // Decoded payload had no usable value; surface as a soft error event.
270
- [self emitScanErrorWithCode:@"E_NO_RESULT" message:@"扫码结果为空或无法解析"];
367
+ if (_appliedPaused || self.window == nil)
271
368
  return;
369
+ @try {
370
+ NSDictionary *mapped = [HmsScanResultMapper scanResultFromHuaweiDict:resultDic];
371
+ if (mapped == nil) {
372
+ [self emitScanErrorWithCode:@"E_INVALID_RESPONSE" message:@"扫码结果无法解析"];
373
+ return;
374
+ }
375
+ [self emitScanResultJson:[HmsScanResultMapper jsonStringFromScanResults:@[ mapped ]]];
376
+ } @catch (NSException *exception) {
377
+ [self emitScanErrorWithCode:@"E_INVALID_RESPONSE" message:exception.reason ?: @"扫码结果无法解析"];
272
378
  }
273
- NSString *json = [HmsScanResultMapper jsonStringFromScanResults:@[ mapped ]];
274
- [self emitScanResultJson:json];
275
379
  }
276
380
 
277
381
  #pragma mark - Event emitters
@@ -298,13 +402,21 @@ using namespace facebook::react;
298
402
  });
299
403
  }
300
404
 
301
- - (void)emitTorchStatusAvailable:(BOOL)available on:(BOOL)on {
405
+ - (void)emitTorchStateAvailable:(BOOL)available on:(BOOL)on force:(BOOL)force {
302
406
  if (!_eventEmitter) {
303
407
  return;
304
408
  }
409
+ if (!force && _hasTorchReport && available == _lastTorchAvailable && on == _lastTorchOn)
410
+ return;
411
+ _hasTorchReport = YES;
412
+ _lastTorchAvailable = available;
413
+ _lastTorchOn = on;
305
414
  std::static_pointer_cast<const HmsScanViewEventEmitter>(_eventEmitter)
306
- ->onTorchStatus(HmsScanViewEventEmitter::OnTorchStatus{
415
+ ->onTorchState(HmsScanViewEventEmitter::OnTorchState{
307
416
  .available = available ? true : false,
417
+ .hasAvailable = true,
418
+ .lowLight = false,
419
+ .hasLowLight = false,
308
420
  .on = on ? true : false,
309
421
  });
310
422
  }
@@ -314,17 +426,20 @@ using namespace facebook::react;
314
426
  - (void)prepareForRecycle {
315
427
  // Reset imperative state so a recycled view re-applies props cleanly.
316
428
  // Turn the torch off WITHOUT emitting (the emitter is being torn down).
317
- [self setTorchHardwareOn:NO available:NULL];
429
+ [self stopObservingTorch];
430
+ [self setTorchHardwareOn:NO available:NULL commandFailed:NULL];
318
431
  [self teardownScanViewController];
319
432
  _hasAppliedOnce = NO;
320
433
  _appliedFormatsCsv = @"";
321
434
  _appliedContinuous = YES;
322
435
  _appliedPaused = NO;
323
436
  _appliedTorch = NO;
437
+ _hasTorchReport = NO;
324
438
  [super prepareForRecycle];
325
439
  }
326
440
 
327
441
  - (void)dealloc {
442
+ [self stopObservingTorch];
328
443
  if (_scanVC != nil) {
329
444
  _scanVC.customizedScanDelegate = nil;
330
445
  }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+
3
+ import { useEffect, useRef } from 'react';
4
+ import { View } from 'react-native';
5
+ import NativeHmsScanView from '../HmsScanViewNativeComponent';
6
+ import { formatConfiguration, parseResultsJson } from "../format.js";
7
+ import { scanError } from "../errors.js";
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+ export function HmsScanView({
10
+ formats,
11
+ continuous = true,
12
+ paused = false,
13
+ torch = false,
14
+ onScanResult,
15
+ onScanError,
16
+ onTorchState,
17
+ ...viewProps
18
+ }) {
19
+ const config = formatConfiguration(formats);
20
+ const invalid = config.error;
21
+ const errorRef = useRef(onScanError);
22
+ errorRef.current = onScanError;
23
+ useEffect(() => {
24
+ if (invalid) errorRef.current?.(invalid);
25
+ }, [invalid?.message]);
26
+ if (invalid) return /*#__PURE__*/_jsx(View, {
27
+ ...viewProps
28
+ });
29
+ return /*#__PURE__*/_jsx(NativeHmsScanView, {
30
+ ...viewProps,
31
+ formatsCsv: config.csv,
32
+ continuous: continuous,
33
+ paused: paused,
34
+ torch: torch,
35
+ onScanResult: event => {
36
+ let results;
37
+ try {
38
+ results = parseResultsJson(event.nativeEvent.resultsJson);
39
+ } catch (error) {
40
+ onScanError?.(scanError(error, {
41
+ reason: 'invalid_response',
42
+ message: '扫码结果无法识别'
43
+ }));
44
+ return;
45
+ }
46
+ onScanResult?.(results);
47
+ },
48
+ onScanError: event => onScanError?.(scanError(event.nativeEvent, {
49
+ reason: 'unavailable',
50
+ message: '扫码相机不可用'
51
+ })),
52
+ onTorchState: event => {
53
+ const state = event.nativeEvent;
54
+ onTorchState?.({
55
+ on: state.on,
56
+ ...(state.hasAvailable ? {
57
+ available: state.available
58
+ } : {}),
59
+ ...(state.hasLowLight ? {
60
+ lowLight: state.lowLight
61
+ } : {})
62
+ });
63
+ }
64
+ });
65
+ }
66
+ //# sourceMappingURL=HmsScanView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useEffect","useRef","View","NativeHmsScanView","formatConfiguration","parseResultsJson","scanError","jsx","_jsx","HmsScanView","formats","continuous","paused","torch","onScanResult","onScanError","onTorchState","viewProps","config","invalid","error","errorRef","current","message","formatsCsv","csv","event","results","nativeEvent","resultsJson","reason","state","on","hasAvailable","available","hasLowLight","lowLight"],"sourceRoot":"../../../src","sources":["HmsScanView/HmsScanView.tsx"],"mappings":";;AAAA,SAASA,SAAS,EAAEC,MAAM,QAAQ,OAAO;AACzC,SAASC,IAAI,QAAQ,cAAc;AACnC,OAAOC,iBAAiB,MAAM,+BAA+B;AAC7D,SAASC,mBAAmB,EAAEC,gBAAgB,QAAQ,cAAW;AACjE,SAASC,SAAS,QAAQ,cAAW;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAItC,OAAO,SAASC,WAAWA,CAAC;EAC1BC,OAAO;EACPC,UAAU,GAAG,IAAI;EACjBC,MAAM,GAAG,KAAK;EACdC,KAAK,GAAG,KAAK;EACbC,YAAY;EACZC,WAAW;EACXC,YAAY;EACZ,GAAGC;AACa,CAAC,EAAE;EACnB,MAAMC,MAAM,GAAGd,mBAAmB,CAACM,OAAO,CAAC;EAC3C,MAAMS,OAAO,GAAGD,MAAM,CAACE,KAAK;EAC5B,MAAMC,QAAQ,GAAGpB,MAAM,CAACc,WAAW,CAAC;EACpCM,QAAQ,CAACC,OAAO,GAAGP,WAAW;EAC9Bf,SAAS,CAAC,MAAM;IACd,IAAImB,OAAO,EAAEE,QAAQ,CAACC,OAAO,GAAGH,OAAO,CAAC;EAC1C,CAAC,EAAE,CAACA,OAAO,EAAEI,OAAO,CAAC,CAAC;EACtB,IAAIJ,OAAO,EAAE,oBAAOX,IAAA,CAACN,IAAI;IAAA,GAAKe;EAAS,CAAG,CAAC;EAC3C,oBACET,IAAA,CAACL,iBAAiB;IAAA,GACZc,SAAS;IACbO,UAAU,EAAEN,MAAM,CAACO,GAAI;IACvBd,UAAU,EAAEA,UAAW;IACvBC,MAAM,EAAEA,MAAO;IACfC,KAAK,EAAEA,KAAM;IACbC,YAAY,EAAGY,KAAK,IAAK;MACvB,IAAIC,OAA8B;MAClC,IAAI;QACFA,OAAO,GAAGtB,gBAAgB,CAACqB,KAAK,CAACE,WAAW,CAACC,WAAW,CAAC;MAC3D,CAAC,CAAC,OAAOT,KAAK,EAAE;QACdL,WAAW,GACTT,SAAS,CAACc,KAAK,EAAE;UACfU,MAAM,EAAE,kBAAkB;UAC1BP,OAAO,EAAE;QACX,CAAC,CACH,CAAC;QACD;MACF;MACAT,YAAY,GAAGa,OAAO,CAAC;IACzB,CAAE;IACFZ,WAAW,EAAGW,KAAK,IACjBX,WAAW,GACTT,SAAS,CAACoB,KAAK,CAACE,WAAW,EAAE;MAC3BE,MAAM,EAAE,aAAa;MACrBP,OAAO,EAAE;IACX,CAAC,CACH,CACD;IACDP,YAAY,EAAGU,KAAK,IAAK;MACvB,MAAMK,KAAK,GAAGL,KAAK,CAACE,WAAW;MAC/BZ,YAAY,GAAG;QACbgB,EAAE,EAAED,KAAK,CAACC,EAAE;QACZ,IAAID,KAAK,CAACE,YAAY,GAAG;UAAEC,SAAS,EAAEH,KAAK,CAACG;QAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7D,IAAIH,KAAK,CAACI,WAAW,GAAG;UAAEC,QAAQ,EAAEL,KAAK,CAACK;QAAS,CAAC,GAAG,CAAC,CAAC;MAC3D,CAAC,CAAC;IACJ;EAAE,CACH,CAAC;AAEN","ignoreList":[]}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ import { useEffect, useRef } from 'react';
4
+ import { View } from 'react-native';
5
+ import { unsupportedScanError } from "../errors.js";
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ export function HmsScanView({
8
+ onScanError,
9
+ formats: _formats,
10
+ paused: _paused,
11
+ torch: _torch,
12
+ continuous: _continuous,
13
+ onScanResult: _onScanResult,
14
+ onTorchState: _onTorchState,
15
+ ...props
16
+ }) {
17
+ const callback = useRef(onScanError);
18
+ callback.current = onScanError;
19
+ useEffect(() => {
20
+ callback.current?.(unsupportedScanError());
21
+ }, []);
22
+ return /*#__PURE__*/_jsx(View, {
23
+ ...props
24
+ });
25
+ }
26
+ //# sourceMappingURL=HmsScanView.web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useEffect","useRef","View","unsupportedScanError","jsx","_jsx","HmsScanView","onScanError","formats","_formats","paused","_paused","torch","_torch","continuous","_continuous","onScanResult","_onScanResult","onTorchState","_onTorchState","props","callback","current"],"sourceRoot":"../../../src","sources":["HmsScanView/HmsScanView.web.tsx"],"mappings":";;AAAA,SAASA,SAAS,EAAEC,MAAM,QAAQ,OAAO;AACzC,SAASC,IAAI,QAAQ,cAAc;AACnC,SAASC,oBAAoB,QAAQ,cAAW;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAGjD,OAAO,SAASC,WAAWA,CAAC;EAC1BC,WAAW;EACXC,OAAO,EAAEC,QAAQ;EACjBC,MAAM,EAAEC,OAAO;EACfC,KAAK,EAAEC,MAAM;EACbC,UAAU,EAAEC,WAAW;EACvBC,YAAY,EAAEC,aAAa;EAC3BC,YAAY,EAAEC,aAAa;EAC3B,GAAGC;AACa,CAAC,EAAE;EACnB,MAAMC,QAAQ,GAAGpB,MAAM,CAACM,WAAW,CAAC;EACpCc,QAAQ,CAACC,OAAO,GAAGf,WAAW;EAC9BP,SAAS,CAAC,MAAM;IACdqB,QAAQ,CAACC,OAAO,GAAGnB,oBAAoB,CAAC,CAAC,CAAC;EAC5C,CAAC,EAAE,EAAE,CAAC;EACN,oBAAOE,IAAA,CAACH,IAAI;IAAA,GAAKkB;EAAK,CAAG,CAAC;AAC5B","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../src","sources":["HmsScanView/types.ts"],"mappings":"","ignoreList":[]}
@@ -7,7 +7,7 @@ import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNati
7
7
 
8
8
  // RN codegen Fabric 组件规范(注册名 "HmsScanView")。
9
9
  // 事件 payload 都用基础类型 / 单字符串,绕开 codegen 对复杂事件结构的限制:
10
- // 扫码结果以 JSON 字符串回传(由 src/HmsScanView.tsx 解析成 ScanResult[])。
10
+ // 扫码结果以 JSON 字符串回传(由 HmsScanView/HmsScanView.tsx 解析成 ScanResult[])。
11
11
 
12
12
  type ScanResultEvent = Readonly<{
13
13
  /** JSON 编码的 ScanResult[]。 */
@@ -19,15 +19,17 @@ type ScanErrorEvent = Readonly<{
19
19
  message: string;
20
20
  }>;
21
21
 
22
- type TorchStatusEvent = Readonly<{
23
- /** 环境是否暗到建议显示手电按钮(Android OnLightVisibleCallBack)。 */
22
+ type TorchStateEvent = Readonly<{
24
23
  available: boolean;
24
+ hasAvailable: boolean;
25
+ lowLight: boolean;
26
+ hasLowLight: boolean;
25
27
  /** 手电当前是否点亮。 */
26
28
  on: boolean;
27
29
  }>;
28
30
 
29
31
  export interface NativeProps extends ViewProps {
30
- /** 限定码制(逗号分隔的 BarcodeFormat),空串 = 全部。 */
32
+ /** 限定码制(逗号分隔的 ScanFormat),空串 = 全部。 */
31
33
  formatsCsv?: WithDefault<string, ''>;
32
34
  /** 连续扫码(命中后继续,不自动停)。 */
33
35
  continuous?: WithDefault<boolean, true>;
@@ -38,7 +40,7 @@ export interface NativeProps extends ViewProps {
38
40
 
39
41
  onScanResult?: DirectEventHandler<ScanResultEvent>;
40
42
  onScanError?: DirectEventHandler<ScanErrorEvent>;
41
- onTorchStatus?: DirectEventHandler<TorchStatusEvent>;
43
+ onTorchState?: DirectEventHandler<TorchStateEvent>;
42
44
  }
43
45
 
44
46
  export default codegenNativeComponent<NativeProps>('HmsScanView');
@@ -7,5 +7,5 @@ import { TurboModuleRegistry } from 'react-native';
7
7
  // decodeImage 返回 JSON 编码的 ScanResult[](由 src/format.ts 解析回强类型),
8
8
  // 权限状态返回字符串(由 src/permissions.ts 归一)。
9
9
 
10
- export default TurboModuleRegistry.getEnforcing('HmsScan');
10
+ export default TurboModuleRegistry.get('HmsScan');
11
11
  //# sourceMappingURL=NativeHmsScan.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeHmsScan.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;;AAElD;AACA;AACA;AACA;;AAmBA,eAAeA,mBAAmB,CAACC,YAAY,CAAO,SAAS,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["TurboModuleRegistry","get"],"sourceRoot":"../../src","sources":["NativeHmsScan.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;;AAElD;AACA;AACA;AACA;;AAiBA,eAAeA,mBAAmB,CAACC,GAAG,CAAO,SAAS,CAAC","ignoreList":[]}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ export class ScanError extends Error {
4
+ constructor(error) {
5
+ super(error.message);
6
+ this.name = 'ScanError';
7
+ this.reason = error.reason;
8
+ this.sourceCode = error.sourceCode;
9
+ Object.setPrototypeOf(this, ScanError.prototype);
10
+ }
11
+ }
12
+ //# sourceMappingURL=ScanError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["ScanError","Error","constructor","error","message","name","reason","sourceCode","Object","setPrototypeOf","prototype"],"sourceRoot":"../../src","sources":["ScanError.ts"],"mappings":";;AAEA,OAAO,MAAMA,SAAS,SAASC,KAAK,CAAwB;EAG1DC,WAAWA,CAACC,KAA4B,EAAE;IACxC,KAAK,CAACA,KAAK,CAACC,OAAO,CAAC;IACpB,IAAI,CAACC,IAAI,GAAG,WAAW;IACvB,IAAI,CAACC,MAAM,GAAGH,KAAK,CAACG,MAAM;IAC1B,IAAI,CAACC,UAAU,GAAGJ,KAAK,CAACI,UAAU;IAClCC,MAAM,CAACC,cAAc,CAAC,IAAI,EAAET,SAAS,CAACU,SAAS,CAAC;EAClD;AACF","ignoreList":[]}
@@ -14,7 +14,7 @@ export function DeniedOverlay({
14
14
  children: [/*#__PURE__*/_jsx(Empty, {
15
15
  icon: "permission-denied",
16
16
  title: "\u9700\u8981\u76F8\u673A\u6743\u9650",
17
- desc: "\u5F00\u542F\u76F8\u673A\u540E\uFF0C\u624D\u80FD\u626B\u63CF\u5546\u54C1\u6761\u7801\u4E0E\u95E8\u5E97\u4E8C\u7EF4\u7801\u3002\u8BF7\u524D\u5F80\u7CFB\u7EDF\u8BBE\u7F6E\u6388\u6743\u3002"
17
+ desc: "\u5F00\u542F\u76F8\u673A\u540E\uFF0C\u624D\u80FD\u626B\u63CF\u6761\u7801\u4E0E\u4E8C\u7EF4\u7801\u3002\u8BF7\u524D\u5F80\u7CFB\u7EDF\u8BBE\u7F6E\u6388\u6743\u3002"
18
18
  }), /*#__PURE__*/_jsxs(View, {
19
19
  style: styles.row,
20
20
  children: [onClose && /*#__PURE__*/_jsx(Button, {
@@ -1 +1 @@
1
- {"version":3,"names":["StyleSheet","View","Button","Empty","useThemedStyles","r","jsx","_jsx","jsxs","_jsxs","DeniedOverlay","onClose","onSettings","s","makeStyles","style","overlay","children","icon","title","desc","styles","row","label","variant","block","onPress","leftIcon","create","flexDirection","columnGap","marginTop","c","position","top","left","right","bottom","zIndex","backgroundColor","background","alignItems","justifyContent","paddingHorizontal","rowGap"],"sourceRoot":"../../../src","sources":["Scanner/DeniedOverlay.tsx"],"mappings":";;AAAA,SAASA,UAAU,EAAEC,IAAI,QAAQ,cAAc;AAC/C,SACEC,MAAM,EACNC,KAAK,EACLC,eAAe,EACfC,CAAC,QAEI,2BAA2B;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAOnC;AACA,OAAO,SAASC,aAAaA,CAAC;EAAEC,OAAO;EAAEC;AAA+B,CAAC,EAAE;EACzE,MAAMC,CAAC,GAAGT,eAAe,CAACU,UAAU,CAAC;EACrC,oBACEL,KAAA,CAACR,IAAI;IAACc,KAAK,EAAEF,CAAC,CAACG,OAAQ;IAAAC,QAAA,gBACrBV,IAAA,CAACJ,KAAK;MACJe,IAAI,EAAC,mBAAmB;MACxBC,KAAK,EAAC,sCAAQ;MACdC,IAAI,EAAC;IAAiC,CACvC,CAAC,eAGFX,KAAA,CAACR,IAAI;MAACc,KAAK,EAAEM,MAAM,CAACC,GAAI;MAAAL,QAAA,GACrBN,OAAO,iBAAIJ,IAAA,CAACL,MAAM;QAACqB,KAAK,EAAC,cAAI;QAACC,OAAO,EAAC,OAAO;QAACC,KAAK;QAACC,OAAO,EAAEf;MAAQ,CAAE,CAAC,eACzEJ,IAAA,CAACL,MAAM;QACLqB,KAAK,EAAC,gCAAO;QACbC,OAAO,EAAC,SAAS;QACjBG,QAAQ,EAAC,UAAU;QACnBF,KAAK;QACLC,OAAO,EAAEd;MAAW,CACrB,CAAC;IAAA,CACE,CAAC;EAAA,CACH,CAAC;AAEX;AAEA,MAAMS,MAAM,GAAGrB,UAAU,CAAC4B,MAAM,CAAC;EAC/BN,GAAG,EAAE;IAAEO,aAAa,EAAE,KAAK;IAAEC,SAAS,EAAEzB,CAAC,CAAC,EAAE,CAAC;IAAE0B,SAAS,EAAE1B,CAAC,CAAC,CAAC;EAAE;AACjE,CAAC,CAAC;AAEF,MAAMS,UAAU,GAAIkB,CAAc,IAChChC,UAAU,CAAC4B,MAAM,CAAC;EAChBZ,OAAO,EAAE;IACPiB,QAAQ,EAAE,UAAU;IACpBC,GAAG,EAAE,CAAC;IACNC,IAAI,EAAE,CAAC;IACPC,KAAK,EAAE,CAAC;IACRC,MAAM,EAAE,CAAC;IACTC,MAAM,EAAE,EAAE;IACVC,eAAe,EAAEP,CAAC,CAACQ,UAAU;IAC7BC,UAAU,EAAE,QAAQ;IACpBC,cAAc,EAAE,QAAQ;IACxBC,iBAAiB,EAAEtC,CAAC,CAAC,EAAE,CAAC;IACxBuC,MAAM,EAAEvC,CAAC,CAAC,CAAC;EACb;AACF,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["StyleSheet","View","Button","Empty","useThemedStyles","r","jsx","_jsx","jsxs","_jsxs","DeniedOverlay","onClose","onSettings","s","makeStyles","style","overlay","children","icon","title","desc","styles","row","label","variant","block","onPress","leftIcon","create","flexDirection","columnGap","marginTop","c","position","top","left","right","bottom","zIndex","backgroundColor","background","alignItems","justifyContent","paddingHorizontal","rowGap"],"sourceRoot":"../../../src","sources":["Scanner/DeniedOverlay.tsx"],"mappings":";;AAAA,SAASA,UAAU,EAAEC,IAAI,QAAQ,cAAc;AAC/C,SACEC,MAAM,EACNC,KAAK,EACLC,eAAe,EACfC,CAAC,QAEI,2BAA2B;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAOnC;AACA,OAAO,SAASC,aAAaA,CAAC;EAAEC,OAAO;EAAEC;AAA+B,CAAC,EAAE;EACzE,MAAMC,CAAC,GAAGT,eAAe,CAACU,UAAU,CAAC;EACrC,oBACEL,KAAA,CAACR,IAAI;IAACc,KAAK,EAAEF,CAAC,CAACG,OAAQ;IAAAC,QAAA,gBACrBV,IAAA,CAACJ,KAAK;MACJe,IAAI,EAAC,mBAAmB;MACxBC,KAAK,EAAC,sCAAQ;MACdC,IAAI,EAAC;IAA6B,CACnC,CAAC,eAGFX,KAAA,CAACR,IAAI;MAACc,KAAK,EAAEM,MAAM,CAACC,GAAI;MAAAL,QAAA,GACrBN,OAAO,iBACNJ,IAAA,CAACL,MAAM;QAACqB,KAAK,EAAC,cAAI;QAACC,OAAO,EAAC,OAAO;QAACC,KAAK;QAACC,OAAO,EAAEf;MAAQ,CAAE,CAC7D,eACDJ,IAAA,CAACL,MAAM;QACLqB,KAAK,EAAC,gCAAO;QACbC,OAAO,EAAC,SAAS;QACjBG,QAAQ,EAAC,UAAU;QACnBF,KAAK;QACLC,OAAO,EAAEd;MAAW,CACrB,CAAC;IAAA,CACE,CAAC;EAAA,CACH,CAAC;AAEX;AAEA,MAAMS,MAAM,GAAGrB,UAAU,CAAC4B,MAAM,CAAC;EAC/BN,GAAG,EAAE;IAAEO,aAAa,EAAE,KAAK;IAAEC,SAAS,EAAEzB,CAAC,CAAC,EAAE,CAAC;IAAE0B,SAAS,EAAE1B,CAAC,CAAC,CAAC;EAAE;AACjE,CAAC,CAAC;AAEF,MAAMS,UAAU,GAAIkB,CAAc,IAChChC,UAAU,CAAC4B,MAAM,CAAC;EAChBZ,OAAO,EAAE;IACPiB,QAAQ,EAAE,UAAU;IACpBC,GAAG,EAAE,CAAC;IACNC,IAAI,EAAE,CAAC;IACPC,KAAK,EAAE,CAAC;IACRC,MAAM,EAAE,CAAC;IACTC,MAAM,EAAE,EAAE;IACVC,eAAe,EAAEP,CAAC,CAACQ,UAAU;IAC7BC,UAAU,EAAE,QAAQ;IACpBC,cAAc,EAAE,QAAQ;IACxBC,iBAAiB,EAAEtC,CAAC,CAAC,EAAE,CAAC;IACxBuC,MAAM,EAAEvC,CAAC,CAAC,CAAC;EACb;AACF,CAAC,CAAC","ignoreList":[]}
@@ -8,6 +8,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
8
  // 聚焦款不加背景遮罩,与浮层确认卡保持一致。
9
9
  export function ResultFail({
10
10
  bottomInset,
11
+ failed,
11
12
  onRescan
12
13
  }) {
13
14
  const s = useThemedStyles(makeStyles);
@@ -36,8 +37,8 @@ export function ResultFail({
36
37
  }],
37
38
  children: [/*#__PURE__*/_jsx(Empty, {
38
39
  icon: "error-alert",
39
- title: "\u672A\u8BC6\u522B\u5230\u6761\u7801",
40
- desc: "\u8BF7\u5C06\u6761\u7801\u5B8C\u6574\u7F6E\u4E8E\u6846\u5185\u3001\u4FDD\u6301\u5E73\u6574\u5E76\u5BF9\u51C6\u5149\u7EBF\u540E\u91CD\u8BD5\u3002"
40
+ title: failed ? '图片识别失败' : '未识别到条码',
41
+ desc: failed ? '无法读取或解码图片,请重试。' : '请将条码完整置于框内、保持平整并对准光线后重试。'
41
42
  }), /*#__PURE__*/_jsx(Button, {
42
43
  label: "\u91CD\u626B",
43
44
  variant: "primary",
@@ -1 +1 @@
1
- {"version":3,"names":["useEffect","useRef","Animated","StyleSheet","View","Button","Empty","useThemedStyles","r","jsx","_jsx","jsxs","_jsxs","ResultFail","bottomInset","onRescan","s","makeStyles","anim","Value","current","timing","toValue","duration","useNativeDriver","start","style","sheet","transform","translateY","interpolate","inputRange","outputRange","children","grabber","styles","inner","paddingBottom","icon","title","desc","label","variant","block","onPress","create","paddingHorizontal","paddingTop","rowGap","c","shadow","position","left","right","bottom","zIndex","backgroundColor","surface","borderTopLeftRadius","borderTopRightRadius","floating","width","height","borderRadius","surfaceContainerHighest","alignSelf"],"sourceRoot":"../../../src","sources":["Scanner/ResultFail.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useEffect","useRef","Animated","StyleSheet","View","Button","Empty","useThemedStyles","r","jsx","_jsx","jsxs","_jsxs","ResultFail","bottomInset","failed","onRescan","s","makeStyles","anim","Value","current","timing","toValue","duration","useNativeDriver","start","style","sheet","transform","translateY","interpolate","inputRange","outputRange","children","grabber","styles","inner","paddingBottom","icon","title","desc","label","variant","block","onPress","create","paddingHorizontal","paddingTop","rowGap","c","shadow","position","left","right","bottom","zIndex","backgroundColor","surface","borderTopLeftRadius","borderTopRightRadius","floating","width","height","borderRadius","surfaceContainerHighest","alignSelf"],"sourceRoot":"../../../src","sources":["Scanner/ResultFail.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ import { ScrollView, Text, View } from 'react-native';
4
+ import { Button, Card, useColors, useThemedStyles, r } from '@unif/react-native-design';
5
+ import { styles, makeStyles } from "./styles.js";
6
+
7
+ /** A raw result is selected here; interpreting it belongs to the consumer. */
8
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
+ export function ResultFocus({
10
+ result,
11
+ bottomInset,
12
+ onRescan,
13
+ onConfirm
14
+ }) {
15
+ const colors = useColors();
16
+ const themed = useThemedStyles(makeStyles);
17
+ return /*#__PURE__*/_jsx(View, {
18
+ style: [styles.wrap, {
19
+ bottom: bottomInset + r(18)
20
+ }],
21
+ children: /*#__PURE__*/_jsxs(Card, {
22
+ borderColor: colors.primary,
23
+ borderWidth: 2,
24
+ borderRadius: r(16),
25
+ padding: r(14),
26
+ children: [/*#__PURE__*/_jsx(Text, {
27
+ style: themed.badge,
28
+ children: "\u5DF2\u8BC6\u522B"
29
+ }), /*#__PURE__*/_jsx(Text, {
30
+ style: themed.format,
31
+ children: result.format
32
+ }), /*#__PURE__*/_jsx(ScrollView, {
33
+ style: styles.content,
34
+ children: /*#__PURE__*/_jsx(Text, {
35
+ selectable: true,
36
+ style: themed.value,
37
+ children: result.value
38
+ })
39
+ }), /*#__PURE__*/_jsxs(View, {
40
+ style: styles.actions,
41
+ children: [/*#__PURE__*/_jsx(Button, {
42
+ label: "\u91CD\u626B",
43
+ variant: "secondary",
44
+ block: true,
45
+ onPress: onRescan
46
+ }), /*#__PURE__*/_jsx(Button, {
47
+ label: "\u9009\u7528",
48
+ variant: "primary",
49
+ block: true,
50
+ onPress: onConfirm
51
+ })]
52
+ })]
53
+ })
54
+ });
55
+ }
56
+ //# sourceMappingURL=ResultFocus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["ScrollView","Text","View","Button","Card","useColors","useThemedStyles","r","styles","makeStyles","jsx","_jsx","jsxs","_jsxs","ResultFocus","result","bottomInset","onRescan","onConfirm","colors","themed","style","wrap","bottom","children","borderColor","primary","borderWidth","borderRadius","padding","badge","format","content","selectable","value","actions","label","variant","block","onPress"],"sourceRoot":"../../../../src","sources":["Scanner/ResultFocus/ResultFocus.tsx"],"mappings":";;AAAA,SAASA,UAAU,EAAEC,IAAI,EAAEC,IAAI,QAAQ,cAAc;AACrD,SACEC,MAAM,EACNC,IAAI,EACJC,SAAS,EACTC,eAAe,EACfC,CAAC,QACI,2BAA2B;AAElC,SAASC,MAAM,EAAEC,UAAU,QAAQ,aAAU;;AAE7C;AAAA,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AACA,OAAO,SAASC,WAAWA,CAAC;EAC1BC,MAAM;EACNC,WAAW;EACXC,QAAQ;EACRC;AACgB,CAAC,EAAE;EACnB,MAAMC,MAAM,GAAGd,SAAS,CAAC,CAAC;EAC1B,MAAMe,MAAM,GAAGd,eAAe,CAACG,UAAU,CAAC;EAC1C,oBACEE,IAAA,CAACT,IAAI;IAACmB,KAAK,EAAE,CAACb,MAAM,CAACc,IAAI,EAAE;MAAEC,MAAM,EAAEP,WAAW,GAAGT,CAAC,CAAC,EAAE;IAAE,CAAC,CAAE;IAAAiB,QAAA,eAC1DX,KAAA,CAACT,IAAI;MACHqB,WAAW,EAAEN,MAAM,CAACO,OAAQ;MAC5BC,WAAW,EAAE,CAAE;MACfC,YAAY,EAAErB,CAAC,CAAC,EAAE,CAAE;MACpBsB,OAAO,EAAEtB,CAAC,CAAC,EAAE,CAAE;MAAAiB,QAAA,gBAEfb,IAAA,CAACV,IAAI;QAACoB,KAAK,EAAED,MAAM,CAACU,KAAM;QAAAN,QAAA,EAAC;MAAG,CAAM,CAAC,eACrCb,IAAA,CAACV,IAAI;QAACoB,KAAK,EAAED,MAAM,CAACW,MAAO;QAAAP,QAAA,EAAET,MAAM,CAACgB;MAAM,CAAO,CAAC,eAClDpB,IAAA,CAACX,UAAU;QAACqB,KAAK,EAAEb,MAAM,CAACwB,OAAQ;QAAAR,QAAA,eAChCb,IAAA,CAACV,IAAI;UAACgC,UAAU;UAACZ,KAAK,EAAED,MAAM,CAACc,KAAM;UAAAV,QAAA,EAClCT,MAAM,CAACmB;QAAK,CACT;MAAC,CACG,CAAC,eACbrB,KAAA,CAACX,IAAI;QAACmB,KAAK,EAAEb,MAAM,CAAC2B,OAAQ;QAAAX,QAAA,gBAC1Bb,IAAA,CAACR,MAAM;UAACiC,KAAK,EAAC,cAAI;UAACC,OAAO,EAAC,WAAW;UAACC,KAAK;UAACC,OAAO,EAAEtB;QAAS,CAAE,CAAC,eAClEN,IAAA,CAACR,MAAM;UAACiC,KAAK,EAAC,cAAI;UAACC,OAAO,EAAC,SAAS;UAACC,KAAK;UAACC,OAAO,EAAErB;QAAU,CAAE,CAAC;MAAA,CAC7D,CAAC;IAAA,CACH;EAAC,CACH,CAAC;AAEX","ignoreList":[]}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ import { StyleSheet } from 'react-native';
4
+ import { r, rf, fw, fontMono } from '@unif/react-native-design';
5
+ export const styles = StyleSheet.create({
6
+ wrap: {
7
+ position: 'absolute',
8
+ left: r(16),
9
+ right: r(16),
10
+ zIndex: 50
11
+ },
12
+ content: {
13
+ maxHeight: r(220),
14
+ marginVertical: r(14)
15
+ },
16
+ actions: {
17
+ flexDirection: 'row',
18
+ columnGap: r(10)
19
+ }
20
+ });
21
+ export const makeStyles = colors => StyleSheet.create({
22
+ badge: {
23
+ fontSize: rf(13),
24
+ fontWeight: fw.semi,
25
+ color: colors.foreground
26
+ },
27
+ format: {
28
+ fontSize: rf(12),
29
+ color: colors.foregroundMuted,
30
+ fontFamily: fontMono,
31
+ marginTop: r(4)
32
+ },
33
+ value: {
34
+ fontSize: rf(16),
35
+ lineHeight: rf(21),
36
+ color: colors.foreground
37
+ }
38
+ });
39
+ //# sourceMappingURL=styles.js.map