@unif/react-native-hms-scan 0.1.0 → 0.2.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.
- package/README.md +13 -114
- package/ReactNativeHmsScan.podspec +14 -6
- package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanModule.kt +38 -28
- package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanResultMapper.kt +64 -58
- package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanView.kt +54 -26
- package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanViewManager.kt +21 -12
- package/android/src/main/java/com/unif/reactnativehmsscan/ReactNativeHmsScanPackage.kt +17 -21
- package/ios/HmsScanModule.mm +26 -40
- package/ios/HmsScanResultMapper.mm +97 -83
- package/ios/HmsScanView.mm +23 -40
- package/lib/module/index.js +2 -2
- package/package.json +32 -6
- package/src/index.tsx +2 -2
package/ios/HmsScanView.mm
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#import "HmsScanResultMapper.h"
|
|
8
8
|
|
|
9
9
|
#import <React/RCTConversions.h>
|
|
10
|
+
#import <React/UIView+React.h>
|
|
10
11
|
|
|
11
12
|
#import <react/renderer/components/ReactNativeHmsScanSpec/ComponentDescriptors.h>
|
|
12
13
|
#import <react/renderer/components/ReactNativeHmsScanSpec/EventEmitters.h>
|
|
@@ -37,21 +38,19 @@ using namespace facebook::react;
|
|
|
37
38
|
|
|
38
39
|
#pragma mark - Codegen wiring
|
|
39
40
|
|
|
40
|
-
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
41
|
-
{
|
|
41
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider {
|
|
42
42
|
return concreteComponentDescriptorProvider<HmsScanViewComponentDescriptor>();
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
- (instancetype)initWithFrame:(CGRect)frame
|
|
46
|
-
{
|
|
45
|
+
- (instancetype)initWithFrame:(CGRect)frame {
|
|
47
46
|
if (self = [super initWithFrame:frame]) {
|
|
48
47
|
static const auto defaultProps = std::make_shared<const HmsScanViewProps>();
|
|
49
48
|
_props = defaultProps;
|
|
50
49
|
|
|
51
|
-
_appliedContinuous = YES;
|
|
50
|
+
_appliedContinuous = YES; // matches WithDefault<boolean, true>
|
|
52
51
|
_appliedPaused = NO;
|
|
53
52
|
_appliedTorch = NO;
|
|
54
|
-
_appliedFormatsCsv = @"";
|
|
53
|
+
_appliedFormatsCsv = @""; // matches WithDefault<string, ''> (= all formats)
|
|
55
54
|
_hasAppliedOnce = NO;
|
|
56
55
|
_childAttached = NO;
|
|
57
56
|
|
|
@@ -62,20 +61,17 @@ using namespace facebook::react;
|
|
|
62
61
|
|
|
63
62
|
#pragma mark - Scan view controller lifecycle
|
|
64
63
|
|
|
65
|
-
- (void)buildScanViewControllerWithCsv:(NSString *)csv
|
|
66
|
-
{
|
|
64
|
+
- (void)buildScanViewControllerWithCsv:(NSString *)csv {
|
|
67
65
|
// (Re)create the VC. HmsCustomScanViewController takes its format set at init
|
|
68
66
|
// via HmsScanOptions and exposes no setter to change it later, so a formatsCsv
|
|
69
67
|
// change requires rebuilding the controller.
|
|
70
68
|
[self teardownScanViewController];
|
|
71
69
|
|
|
72
70
|
unsigned int formatType = [HmsScanResultMapper scanFormatTypeFromCsv:csv];
|
|
73
|
-
HmsScanOptions *options =
|
|
74
|
-
[[HmsScanOptions alloc] initWithScanFormatType:formatType Photo:NO];
|
|
71
|
+
HmsScanOptions *options = [[HmsScanOptions alloc] initWithScanFormatType:formatType Photo:NO];
|
|
75
72
|
|
|
76
|
-
HmsCustomScanViewController *vc =
|
|
77
|
-
|
|
78
|
-
vc.backButtonHidden = YES; // we render our own chrome from JS
|
|
73
|
+
HmsCustomScanViewController *vc = [[HmsCustomScanViewController alloc] initCustomizedScanWithFormatType:options];
|
|
74
|
+
vc.backButtonHidden = YES; // we render our own chrome from JS
|
|
79
75
|
vc.customizedScanDelegate = self;
|
|
80
76
|
vc.continuouslyScan = _appliedContinuous;
|
|
81
77
|
|
|
@@ -101,8 +97,7 @@ using namespace facebook::react;
|
|
|
101
97
|
}
|
|
102
98
|
}
|
|
103
99
|
|
|
104
|
-
- (void)teardownScanViewController
|
|
105
|
-
{
|
|
100
|
+
- (void)teardownScanViewController {
|
|
106
101
|
if (_scanVC == nil) {
|
|
107
102
|
return;
|
|
108
103
|
}
|
|
@@ -114,14 +109,13 @@ using namespace facebook::react;
|
|
|
114
109
|
_scanVC = nil;
|
|
115
110
|
}
|
|
116
111
|
|
|
117
|
-
- (void)attachChildViewController
|
|
118
|
-
{
|
|
112
|
+
- (void)attachChildViewController {
|
|
119
113
|
if (_scanVC == nil || _childAttached) {
|
|
120
114
|
return;
|
|
121
115
|
}
|
|
122
116
|
UIViewController *parent = [self reactViewController];
|
|
123
117
|
if (parent == nil) {
|
|
124
|
-
return;
|
|
118
|
+
return; // try again on next didMoveToWindow
|
|
125
119
|
}
|
|
126
120
|
[parent addChildViewController:_scanVC];
|
|
127
121
|
// The view is already in our hierarchy (set as contentView); just notify.
|
|
@@ -129,8 +123,7 @@ using namespace facebook::react;
|
|
|
129
123
|
_childAttached = YES;
|
|
130
124
|
}
|
|
131
125
|
|
|
132
|
-
- (void)detachChildViewController
|
|
133
|
-
{
|
|
126
|
+
- (void)detachChildViewController {
|
|
134
127
|
if (_scanVC == nil || !_childAttached) {
|
|
135
128
|
return;
|
|
136
129
|
}
|
|
@@ -139,8 +132,7 @@ using namespace facebook::react;
|
|
|
139
132
|
_childAttached = NO;
|
|
140
133
|
}
|
|
141
134
|
|
|
142
|
-
- (void)didMoveToWindow
|
|
143
|
-
{
|
|
135
|
+
- (void)didMoveToWindow {
|
|
144
136
|
[super didMoveToWindow];
|
|
145
137
|
if (self.window != nil) {
|
|
146
138
|
[self attachChildViewController];
|
|
@@ -151,8 +143,7 @@ using namespace facebook::react;
|
|
|
151
143
|
|
|
152
144
|
#pragma mark - Props
|
|
153
145
|
|
|
154
|
-
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
|
155
|
-
{
|
|
146
|
+
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps {
|
|
156
147
|
const auto &newViewProps = *std::static_pointer_cast<HmsScanViewProps const>(props);
|
|
157
148
|
|
|
158
149
|
NSString *newCsv = [NSString stringWithUTF8String:newViewProps.formatsCsv.c_str()];
|
|
@@ -205,8 +196,7 @@ using namespace facebook::react;
|
|
|
205
196
|
// torch directly through AVFoundation as a best-effort convenience. This is NOT
|
|
206
197
|
// guaranteed to stay in sync with HUAWEI's built-in torch button, and may be a
|
|
207
198
|
// no-op if HUAWEI holds an exclusive lock on the capture device's configuration.
|
|
208
|
-
- (void)applyTorch:(BOOL)on
|
|
209
|
-
{
|
|
199
|
+
- (void)applyTorch:(BOOL)on {
|
|
210
200
|
BOOL available = NO;
|
|
211
201
|
BOOL torchOn = [self setTorchHardwareOn:on available:&available];
|
|
212
202
|
[self emitTorchStatusAvailable:available on:torchOn];
|
|
@@ -215,8 +205,7 @@ using namespace facebook::react;
|
|
|
215
205
|
// Mutates the capture device's torch. Returns the resulting on-state and writes
|
|
216
206
|
// hardware availability into `available`. Does NOT emit any event (so it can be
|
|
217
207
|
// reused on teardown/recycle without firing onTorchStatus on a stale emitter).
|
|
218
|
-
- (BOOL)setTorchHardwareOn:(BOOL)on available:(BOOL *)available
|
|
219
|
-
{
|
|
208
|
+
- (BOOL)setTorchHardwareOn:(BOOL)on available:(BOOL *)available {
|
|
220
209
|
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
|
221
210
|
BOOL isAvailable = (device != nil && device.hasTorch && device.isTorchAvailable);
|
|
222
211
|
if (available != NULL) {
|
|
@@ -246,8 +235,7 @@ using namespace facebook::react;
|
|
|
246
235
|
|
|
247
236
|
// Called by HUAWEI on every decode (repeatedly in continuous mode). `resultDic`
|
|
248
237
|
// is a single result dictionary; we wrap it into the contract's top-level array.
|
|
249
|
-
- (void)customizedScanDelegateForResult:(NSDictionary *)resultDic
|
|
250
|
-
{
|
|
238
|
+
- (void)customizedScanDelegateForResult:(NSDictionary *)resultDic {
|
|
251
239
|
NSDictionary *mapped = [HmsScanResultMapper scanResultFromHuaweiDict:resultDic];
|
|
252
240
|
if (mapped == nil) {
|
|
253
241
|
// Decoded payload had no usable value; surface as a soft error event.
|
|
@@ -260,8 +248,7 @@ using namespace facebook::react;
|
|
|
260
248
|
|
|
261
249
|
#pragma mark - Event emitters
|
|
262
250
|
|
|
263
|
-
- (void)emitScanResultJson:(NSString *)json
|
|
264
|
-
{
|
|
251
|
+
- (void)emitScanResultJson:(NSString *)json {
|
|
265
252
|
if (!_eventEmitter) {
|
|
266
253
|
return;
|
|
267
254
|
}
|
|
@@ -272,8 +259,7 @@ using namespace facebook::react;
|
|
|
272
259
|
});
|
|
273
260
|
}
|
|
274
261
|
|
|
275
|
-
- (void)emitScanErrorWithCode:(NSString *)code message:(NSString *)message
|
|
276
|
-
{
|
|
262
|
+
- (void)emitScanErrorWithCode:(NSString *)code message:(NSString *)message {
|
|
277
263
|
if (!_eventEmitter) {
|
|
278
264
|
return;
|
|
279
265
|
}
|
|
@@ -284,8 +270,7 @@ using namespace facebook::react;
|
|
|
284
270
|
});
|
|
285
271
|
}
|
|
286
272
|
|
|
287
|
-
- (void)emitTorchStatusAvailable:(BOOL)available on:(BOOL)on
|
|
288
|
-
{
|
|
273
|
+
- (void)emitTorchStatusAvailable:(BOOL)available on:(BOOL)on {
|
|
289
274
|
if (!_eventEmitter) {
|
|
290
275
|
return;
|
|
291
276
|
}
|
|
@@ -298,8 +283,7 @@ using namespace facebook::react;
|
|
|
298
283
|
|
|
299
284
|
#pragma mark - Cleanup
|
|
300
285
|
|
|
301
|
-
- (void)prepareForRecycle
|
|
302
|
-
{
|
|
286
|
+
- (void)prepareForRecycle {
|
|
303
287
|
// Reset imperative state so a recycled view re-applies props cleanly.
|
|
304
288
|
// Turn the torch off WITHOUT emitting (the emitter is being torn down).
|
|
305
289
|
[self setTorchHardwareOn:NO available:NULL];
|
|
@@ -312,8 +296,7 @@ using namespace facebook::react;
|
|
|
312
296
|
[super prepareForRecycle];
|
|
313
297
|
}
|
|
314
298
|
|
|
315
|
-
- (void)dealloc
|
|
316
|
-
{
|
|
299
|
+
- (void)dealloc {
|
|
317
300
|
if (_scanVC != nil) {
|
|
318
301
|
_scanVC.customizedScanDelegate = nil;
|
|
319
302
|
}
|
package/lib/module/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
// @unif/react-native-hms-scan —— 华为 HMS 统一扫码服务 RN bridge
|
|
4
|
-
// 能力:定制视图扫码(底层 <HmsScanView> + 成品 <Scanner> 扫一扫页)+ 图片识别(decodeImage
|
|
3
|
+
// @unif/react-native-hms-scan —— 华为 HMS 统一扫码服务 RN bridge(Fabric 新架构)
|
|
4
|
+
// 能力:定制视图扫码(底层 <HmsScanView> + 成品 <Scanner> 扫一扫页)+ 图片识别(decodeImage)+ 相机权限。
|
|
5
5
|
|
|
6
6
|
// ── 类型与常量 ──
|
|
7
7
|
export { ALL_BARCODE_FORMATS, HmsScanError } from "./types.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unif/react-native-hms-scan",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "华为 HMS 统一扫码服务 React Native bridge:定制视图扫码 + 图片识别 (Scan SDK-Plus / ScanKitFrameWork,@unif 私有)",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"bugs": {
|
|
65
65
|
"url": "https://github.com/unif-design/react-native-hms-scan/issues"
|
|
66
66
|
},
|
|
67
|
-
"homepage": "https://
|
|
67
|
+
"homepage": "https://unif-design.github.io/react-native-hms-scan/",
|
|
68
68
|
"publishConfig": {
|
|
69
69
|
"registry": "https://registry.npmjs.org/"
|
|
70
70
|
},
|
|
@@ -72,9 +72,10 @@
|
|
|
72
72
|
"@commitlint/config-conventional": "^20.5.0",
|
|
73
73
|
"@eslint/js": "^9.39.0",
|
|
74
74
|
"@gorhom/bottom-sheet": "^5.2.14",
|
|
75
|
-
"@react-native/babel-preset": "0.85.
|
|
75
|
+
"@react-native/babel-preset": "0.85.3",
|
|
76
76
|
"@react-native/eslint-config": "0.85.0",
|
|
77
|
-
"@react-native/jest-preset": "0.85.
|
|
77
|
+
"@react-native/jest-preset": "0.85.3",
|
|
78
|
+
"@release-it/conventional-changelog": "^11.0.0",
|
|
78
79
|
"@sbaiahmed1/react-native-blur": "^4.6.2",
|
|
79
80
|
"@testing-library/react-native": "^13.3.3",
|
|
80
81
|
"@types/jest": "^29.5.0",
|
|
@@ -89,7 +90,7 @@
|
|
|
89
90
|
"jest": "^29.7.0",
|
|
90
91
|
"prettier": "^3.8.1",
|
|
91
92
|
"react": "19.2.3",
|
|
92
|
-
"react-native": "0.85.
|
|
93
|
+
"react-native": "0.85.3",
|
|
93
94
|
"react-native-builder-bob": "^0.41.0",
|
|
94
95
|
"react-native-gesture-handler": "^2.21.0",
|
|
95
96
|
"react-native-reanimated": "^4.0.0",
|
|
@@ -98,6 +99,8 @@
|
|
|
98
99
|
"react-native-svg": "^15.15.5",
|
|
99
100
|
"react-native-worklets": "*",
|
|
100
101
|
"react-test-renderer": "19.2.3",
|
|
102
|
+
"release-it": "^20.0.1",
|
|
103
|
+
"turbo": "^2.8.21",
|
|
101
104
|
"typescript": "^6.0.2",
|
|
102
105
|
"typescript-eslint": "^8.20.0"
|
|
103
106
|
},
|
|
@@ -115,7 +118,8 @@
|
|
|
115
118
|
"react-native-worklets": "*"
|
|
116
119
|
},
|
|
117
120
|
"workspaces": [
|
|
118
|
-
"example"
|
|
121
|
+
"example",
|
|
122
|
+
"website"
|
|
119
123
|
],
|
|
120
124
|
"packageManager": "yarn@4.11.0",
|
|
121
125
|
"codegenConfig": {
|
|
@@ -144,6 +148,28 @@
|
|
|
144
148
|
]
|
|
145
149
|
]
|
|
146
150
|
},
|
|
151
|
+
"release-it": {
|
|
152
|
+
"git": {
|
|
153
|
+
"commitMessage": "chore: release ${version} [skip ci]",
|
|
154
|
+
"tagName": "v${version}",
|
|
155
|
+
"requireCommits": true
|
|
156
|
+
},
|
|
157
|
+
"npm": {
|
|
158
|
+
"publish": true,
|
|
159
|
+
"skipChecks": true
|
|
160
|
+
},
|
|
161
|
+
"github": {
|
|
162
|
+
"release": true
|
|
163
|
+
},
|
|
164
|
+
"plugins": {
|
|
165
|
+
"@release-it/conventional-changelog": {
|
|
166
|
+
"preset": {
|
|
167
|
+
"name": "angular"
|
|
168
|
+
},
|
|
169
|
+
"infile": "CHANGELOG.md"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
147
173
|
"commitlint": {
|
|
148
174
|
"extends": [
|
|
149
175
|
"@commitlint/config-conventional"
|
package/src/index.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// @unif/react-native-hms-scan —— 华为 HMS 统一扫码服务 RN bridge
|
|
2
|
-
// 能力:定制视图扫码(底层 <HmsScanView> + 成品 <Scanner> 扫一扫页)+ 图片识别(decodeImage
|
|
1
|
+
// @unif/react-native-hms-scan —— 华为 HMS 统一扫码服务 RN bridge(Fabric 新架构)
|
|
2
|
+
// 能力:定制视图扫码(底层 <HmsScanView> + 成品 <Scanner> 扫一扫页)+ 图片识别(decodeImage)+ 相机权限。
|
|
3
3
|
|
|
4
4
|
// ── 类型与常量 ──
|
|
5
5
|
export {
|