@unif/react-native-hms-scan 0.6.2 → 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.
- package/README.md +3 -2
- package/android/src/main/AndroidManifest.xml +0 -9
- package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanImage.kt +135 -0
- package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanModule.kt +163 -147
- package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanResultMapper.kt +17 -9
- package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanView.kt +57 -19
- package/android/src/main/java/com/unif/reactnativehmsscan/HmsScanViewManager.kt +1 -1
- package/ios/HmsScanModule.mm +13 -37
- package/ios/HmsScanResultMapper.h +4 -3
- package/ios/HmsScanResultMapper.mm +31 -19
- package/ios/HmsScanView.h +1 -1
- package/ios/HmsScanView.mm +140 -25
- package/lib/module/HmsScanView/HmsScanView.js +66 -0
- package/lib/module/HmsScanView/HmsScanView.js.map +1 -0
- package/lib/module/HmsScanView/HmsScanView.web.js +26 -0
- package/lib/module/HmsScanView/HmsScanView.web.js.map +1 -0
- package/lib/module/HmsScanView/types.js +4 -0
- package/lib/module/HmsScanView/types.js.map +1 -0
- package/lib/module/HmsScanViewNativeComponent.ts +7 -5
- package/lib/module/NativeHmsScan.js +1 -1
- package/lib/module/NativeHmsScan.js.map +1 -1
- package/lib/module/ScanError.js +12 -0
- package/lib/module/ScanError.js.map +1 -0
- package/lib/module/Scanner/DeniedOverlay.js +1 -1
- package/lib/module/Scanner/DeniedOverlay.js.map +1 -1
- package/lib/module/Scanner/ResultFail.js +3 -2
- package/lib/module/Scanner/ResultFail.js.map +1 -1
- package/lib/module/Scanner/ResultFocus/ResultFocus.js +56 -0
- package/lib/module/Scanner/ResultFocus/ResultFocus.js.map +1 -0
- package/lib/module/Scanner/ResultFocus/styles.js +39 -0
- package/lib/module/Scanner/ResultFocus/styles.js.map +1 -0
- package/lib/module/Scanner/ResultFocus/types.js +4 -0
- package/lib/module/Scanner/ResultFocus/types.js.map +1 -0
- package/lib/module/Scanner/Scanner.js +11 -310
- package/lib/module/Scanner/Scanner.js.map +1 -1
- package/lib/module/Scanner/Scanner.web.js +29 -0
- package/lib/module/Scanner/Scanner.web.js.map +1 -0
- package/lib/module/Scanner/ScannerInner.js +310 -0
- package/lib/module/Scanner/ScannerInner.js.map +1 -0
- package/lib/module/Scanner/styles.js +11 -0
- package/lib/module/Scanner/styles.js.map +1 -0
- package/lib/module/Scanner/types.js +4 -0
- package/lib/module/Scanner/types.js.map +1 -0
- package/lib/module/constants.js +20 -0
- package/lib/module/constants.js.map +1 -0
- package/lib/module/decodeImage.js +29 -24
- package/lib/module/decodeImage.js.map +1 -1
- package/lib/module/decodeImage.web.js +7 -0
- package/lib/module/decodeImage.web.js.map +1 -0
- package/lib/module/errors.js +24 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/format.js +53 -47
- package/lib/module/format.js.map +1 -1
- package/lib/module/index.js +5 -19
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +8 -0
- package/lib/module/index.web.js.map +1 -0
- package/lib/module/mock.js +2 -23
- package/lib/module/mock.js.map +1 -1
- package/lib/module/permissions.js +24 -20
- package/lib/module/permissions.js.map +1 -1
- package/lib/module/permissions.web.js +10 -0
- package/lib/module/permissions.web.js.map +1 -0
- package/lib/module/types.js +1 -45
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/src/HmsScanView/HmsScanView.d.ts +3 -0
- package/lib/typescript/src/HmsScanView/HmsScanView.d.ts.map +1 -0
- package/lib/typescript/src/HmsScanView/HmsScanView.web.d.ts +3 -0
- package/lib/typescript/src/HmsScanView/HmsScanView.web.d.ts.map +1 -0
- package/lib/typescript/src/HmsScanView/types.d.ts +12 -0
- package/lib/typescript/src/HmsScanView/types.d.ts.map +1 -0
- package/lib/typescript/src/HmsScanViewNativeComponent.d.ts +6 -4
- package/lib/typescript/src/HmsScanViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/NativeHmsScan.d.ts +3 -5
- package/lib/typescript/src/NativeHmsScan.d.ts.map +1 -1
- package/lib/typescript/src/ScanError.d.ts +7 -0
- package/lib/typescript/src/ScanError.d.ts.map +1 -0
- package/lib/typescript/src/Scanner/DeniedOverlay.d.ts.map +1 -1
- package/lib/typescript/src/Scanner/ResultFail.d.ts +2 -1
- package/lib/typescript/src/Scanner/ResultFail.d.ts.map +1 -1
- package/lib/typescript/src/Scanner/ResultFocus/ResultFocus.d.ts +4 -0
- package/lib/typescript/src/Scanner/ResultFocus/ResultFocus.d.ts.map +1 -0
- package/lib/typescript/src/Scanner/ResultFocus/styles.d.ts +36 -0
- package/lib/typescript/src/Scanner/ResultFocus/styles.d.ts.map +1 -0
- package/lib/typescript/src/Scanner/ResultFocus/types.d.ts +8 -0
- package/lib/typescript/src/Scanner/ResultFocus/types.d.ts.map +1 -0
- package/lib/typescript/src/Scanner/Scanner.d.ts +2 -45
- package/lib/typescript/src/Scanner/Scanner.d.ts.map +1 -1
- package/lib/typescript/src/Scanner/Scanner.web.d.ts +3 -0
- package/lib/typescript/src/Scanner/Scanner.web.d.ts.map +1 -0
- package/lib/typescript/src/Scanner/ScannerInner.d.ts +3 -0
- package/lib/typescript/src/Scanner/ScannerInner.d.ts.map +1 -0
- package/lib/typescript/src/Scanner/styles.d.ts +7 -0
- package/lib/typescript/src/Scanner/styles.d.ts.map +1 -0
- package/lib/typescript/src/Scanner/types.d.ts +20 -0
- package/lib/typescript/src/Scanner/types.d.ts.map +1 -0
- package/lib/typescript/src/constants.d.ts +8 -0
- package/lib/typescript/src/constants.d.ts.map +1 -0
- package/lib/typescript/src/decodeImage.d.ts +2 -12
- package/lib/typescript/src/decodeImage.d.ts.map +1 -1
- package/lib/typescript/src/decodeImage.web.d.ts +3 -0
- package/lib/typescript/src/decodeImage.web.d.ts.map +1 -0
- package/lib/typescript/src/errors.d.ts +6 -0
- package/lib/typescript/src/errors.d.ts.map +1 -0
- package/lib/typescript/src/format.d.ts +15 -12
- package/lib/typescript/src/format.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +6 -7
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +9 -0
- package/lib/typescript/src/index.web.d.ts.map +1 -0
- package/lib/typescript/src/mock.d.ts +9 -8
- package/lib/typescript/src/mock.d.ts.map +1 -1
- package/lib/typescript/src/permissions.d.ts +4 -8
- package/lib/typescript/src/permissions.d.ts.map +1 -1
- package/lib/typescript/src/permissions.web.d.ts +4 -0
- package/lib/typescript/src/permissions.web.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +31 -56
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +8 -1
- package/src/HmsScanView/HmsScanView.tsx +67 -0
- package/src/HmsScanView/HmsScanView.web.tsx +22 -0
- package/src/HmsScanView/types.ts +17 -0
- package/src/HmsScanViewNativeComponent.ts +7 -5
- package/src/NativeHmsScan.ts +3 -5
- package/src/ScanError.ts +13 -0
- package/src/Scanner/DeniedOverlay.tsx +4 -2
- package/src/Scanner/ResultFail.tsx +23 -5
- package/src/Scanner/ResultFocus/ResultFocus.tsx +43 -0
- package/src/Scanner/ResultFocus/styles.ts +25 -0
- package/src/Scanner/ResultFocus/types.ts +8 -0
- package/src/Scanner/Scanner.tsx +14 -432
- package/src/Scanner/Scanner.web.tsx +26 -0
- package/src/Scanner/ScannerInner.tsx +391 -0
- package/src/Scanner/styles.ts +6 -0
- package/src/Scanner/types.ts +36 -0
- package/src/constants.ts +55 -0
- package/src/decodeImage.ts +35 -29
- package/src/decodeImage.web.ts +8 -0
- package/src/errors.ts +26 -0
- package/src/format.ts +77 -76
- package/src/index.tsx +17 -32
- package/src/index.web.tsx +22 -0
- package/src/mock.ts +21 -29
- package/src/permissions.ts +33 -20
- package/src/permissions.web.ts +9 -0
- package/src/types.ts +38 -126
- package/lib/module/HmsScanView.js +0 -43
- package/lib/module/HmsScanView.js.map +0 -1
- package/lib/module/Scanner/ResultFocus.js +0 -171
- package/lib/module/Scanner/ResultFocus.js.map +0 -1
- package/lib/typescript/src/HmsScanView.d.ts +0 -33
- package/lib/typescript/src/HmsScanView.d.ts.map +0 -1
- package/lib/typescript/src/Scanner/ResultFocus.d.ts +0 -14
- package/lib/typescript/src/Scanner/ResultFocus.d.ts.map +0 -1
- package/src/HmsScanView.tsx +0 -87
- package/src/Scanner/ResultFocus.tsx +0 -122
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
* 从本地图片解码条码 / 二维码(华为 Bitmap 模式)。
|
|
4
|
-
*
|
|
5
|
-
* @param uri 本地图片。iOS 支持 file://、绝对路径、data:;Android 支持
|
|
6
|
-
* file://、绝对路径、content://、android.resource://。
|
|
7
|
-
* 两端都不下载远程 URL,也不支持 ph:// / assets-library://。
|
|
8
|
-
* @param options 可选;formats 限定码制,不传 = 全部。
|
|
9
|
-
* @returns 命中的结果数组(可能为空)。
|
|
10
|
-
* @throws HmsScanError 图片加载失败 / 读权限缺失等。
|
|
11
|
-
*/
|
|
12
|
-
export declare function decodeImage(uri: string, options?: DecodeImageOptions): Promise<ScanResult[]>;
|
|
1
|
+
import type { DecodeScanImageInput, ScanResult } from './types';
|
|
2
|
+
export declare function decodeImage(input: Readonly<DecodeScanImageInput>): Promise<readonly ScanResult[]>;
|
|
13
3
|
//# sourceMappingURL=decodeImage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decodeImage.d.ts","sourceRoot":"","sources":["../../../src/decodeImage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"decodeImage.d.ts","sourceRoot":"","sources":["../../../src/decodeImage.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEhE,wBAAsB,WAAW,CAC/B,KAAK,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GACpC,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAkChC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decodeImage.web.d.ts","sourceRoot":"","sources":["../../../src/decodeImage.web.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEhE,wBAAsB,WAAW,CAC/B,MAAM,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GACrC,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CAEhC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ScanError } from './ScanError';
|
|
2
|
+
import type { ScanFailure } from './types';
|
|
3
|
+
/** Native boundary normalization; Scanner only uses this for its external picker. */
|
|
4
|
+
export declare function scanError(error: unknown, fallback: Readonly<ScanFailure>): ScanError;
|
|
5
|
+
export declare function unsupportedScanError(): ScanError;
|
|
6
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,KAAK,EAAqB,WAAW,EAAE,MAAM,SAAS,CAAC;AAE9D,qFAAqF;AACrF,wBAAgB,SAAS,CACvB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,GAC9B,SAAS,CAUX;AAED,wBAAgB,oBAAoB,IAAI,SAAS,CAKhD"}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare function coerceFormat(value: unknown):
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export declare function
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { ScanError } from './ScanError';
|
|
2
|
+
import type { RequestedScanFormat, ScanContentType, ScanFormat, ScanResult } from './types';
|
|
3
|
+
export declare function coerceFormat(value: unknown): ScanFormat;
|
|
4
|
+
export declare function coerceContentType(value: unknown): ScanContentType | undefined;
|
|
5
|
+
/** Empty means no extra filter. Order and duplicates do not change the filter. */
|
|
6
|
+
export declare function formatsToCsv(value?: readonly RequestedScanFormat[]): string;
|
|
7
|
+
export declare function formatConfiguration(value?: readonly RequestedScanFormat[]): {
|
|
8
|
+
csv: string;
|
|
9
|
+
error: undefined;
|
|
10
|
+
} | {
|
|
11
|
+
csv: string;
|
|
12
|
+
error: ScanError;
|
|
13
|
+
};
|
|
14
|
+
/** Malformed bridge data is distinct from a successfully decoded empty batch. */
|
|
15
|
+
export declare function parseResultsJson(json: unknown): readonly ScanResult[];
|
|
13
16
|
//# sourceMappingURL=format.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/format.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/format.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,UAAU,EAEV,UAAU,EACX,MAAM,SAAS,CAAC;AACjB,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAIvD;AACD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAI7E;AACD,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,SAAS,mBAAmB,EAAE,GAAG,MAAM,CAiB3E;AACD,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE,SAAS,mBAAmB,EAAE;;;;;WAIpC,SAAS;EAE9C;AAqBD,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,UAAU,EAAE,CA2BrE"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export type { HmsScanViewProps, TorchStatus } from './HmsScanView';
|
|
1
|
+
export { ScanError } from './ScanError';
|
|
2
|
+
export type { ScanFormat, RequestedScanFormat, ScanContentType, ScanPoint, ScanResult, ScanFailure, DecodeScanImageInput, ScanCameraPermission, ScanTorchState, ScannerImage, } from './types';
|
|
3
|
+
export { HmsScanView } from './HmsScanView/HmsScanView';
|
|
4
|
+
export type { HmsScanViewProps } from './HmsScanView/types';
|
|
6
5
|
export { decodeImage } from './decodeImage';
|
|
7
|
-
export { getCameraPermissionStatus, requestCameraPermission } from './permissions';
|
|
6
|
+
export { getCameraPermissionStatus, requestCameraPermission, } from './permissions';
|
|
8
7
|
export { Scanner } from './Scanner/Scanner';
|
|
9
|
-
export type { ScannerProps } from './Scanner/
|
|
8
|
+
export type { ScannerProps } from './Scanner/types';
|
|
10
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EACL,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { ScanError } from './ScanError';
|
|
2
|
+
export type { ScanFormat, RequestedScanFormat, ScanContentType, ScanPoint, ScanResult, ScanFailure, DecodeScanImageInput, ScanCameraPermission, ScanTorchState, ScannerImage, } from './types';
|
|
3
|
+
export { HmsScanView } from './HmsScanView/HmsScanView.web';
|
|
4
|
+
export type { HmsScanViewProps } from './HmsScanView/types';
|
|
5
|
+
export { decodeImage } from './decodeImage.web';
|
|
6
|
+
export { getCameraPermissionStatus, requestCameraPermission, } from './permissions.web';
|
|
7
|
+
export { Scanner } from './Scanner/Scanner.web';
|
|
8
|
+
export type { ScannerProps } from './Scanner/types';
|
|
9
|
+
//# sourceMappingURL=index.web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../../src/index.web.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { FC } from 'react';
|
|
2
|
-
import type {
|
|
3
|
-
import type { HmsScanViewProps } from './HmsScanView';
|
|
4
|
-
import type { ScannerProps } from './Scanner/
|
|
5
|
-
export
|
|
6
|
-
export {
|
|
7
|
-
export
|
|
8
|
-
export declare const
|
|
9
|
-
export declare const
|
|
2
|
+
import type { DecodeScanImageInput, ScanCameraPermission, ScanResult } from './types';
|
|
3
|
+
import type { HmsScanViewProps } from './HmsScanView/types';
|
|
4
|
+
import type { ScannerProps } from './Scanner/types';
|
|
5
|
+
export { ScanError } from './ScanError';
|
|
6
|
+
export type { ScanFormat, RequestedScanFormat, ScanContentType, ScanPoint, ScanResult, ScanFailure, DecodeScanImageInput, ScanCameraPermission, ScanTorchState, ScannerImage, } from './types';
|
|
7
|
+
export type { HmsScanViewProps, ScannerProps };
|
|
8
|
+
export declare const decodeImage: jest.Mock<Promise<readonly ScanResult[]>, [_input: Readonly<DecodeScanImageInput>], any>;
|
|
9
|
+
export declare const getCameraPermissionStatus: jest.Mock<Promise<ScanCameraPermission>, [], any>;
|
|
10
|
+
export declare const requestCameraPermission: jest.Mock<Promise<ScanCameraPermission>, [], any>;
|
|
10
11
|
export declare const HmsScanView: FC<HmsScanViewProps>;
|
|
11
12
|
export declare const Scanner: FC<ScannerProps>;
|
|
12
13
|
//# sourceMappingURL=mock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../../src/mock.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../../src/mock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,UAAU,EACX,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,CAAC;AAC/C,eAAO,MAAM,WAAW,0FAGvB,CAAC;AACF,eAAO,MAAM,yBAAyB,mDAErC,CAAC;AACF,eAAO,MAAM,uBAAuB,mDAEnC,CAAC;AACF,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAAc,CAAC;AAC5D,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC,YAAY,CAAc,CAAC"}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
/**
|
|
3
|
-
export declare function getCameraPermissionStatus(): Promise<
|
|
4
|
-
|
|
5
|
-
* 发起相机权限请求(必要时弹系统授权框),返回请求后的状态。
|
|
6
|
-
* 若用户已永久拒绝(blocked),需引导去系统设置开启。
|
|
7
|
-
*/
|
|
8
|
-
export declare function requestCameraPermission(): Promise<CameraPermissionStatus>;
|
|
1
|
+
import type { ScanCameraPermission } from './types';
|
|
2
|
+
/** Reads the actual status without presenting a system permission prompt. */
|
|
3
|
+
export declare function getCameraPermissionStatus(): Promise<ScanCameraPermission>;
|
|
4
|
+
export declare function requestCameraPermission(): Promise<ScanCameraPermission>;
|
|
9
5
|
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../src/permissions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../../src/permissions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AA8BpD,6EAA6E;AAC7E,wBAAgB,yBAAyB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAEzE;AACD,wBAAgB,uBAAuB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAEvE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.web.d.ts","sourceRoot":"","sources":["../../../src/permissions.web.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpD,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAE/E;AACD,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAE7E"}
|
|
@@ -1,67 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
export type
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
* 码内容语义类型(尽力归一)。
|
|
7
|
-
* Android 来自 HmsScan.getScanTypeForm(),iOS 来自 sceneType(精度有限,未知归 OTHER)。
|
|
8
|
-
*/
|
|
9
|
-
export type BarcodeContentType = 'TEXT' | 'URL' | 'EMAIL' | 'PHONE' | 'SMS' | 'WIFI' | 'CONTACT' | 'EVENT' | 'LOCATION' | 'DRIVER' | 'ISBN' | 'ARTICLE' | 'OTHER';
|
|
10
|
-
/** 取景框/解码命中的角点(图像坐标系,单位 px)。 */
|
|
11
|
-
export interface ScanCornerPoint {
|
|
1
|
+
import type { SCAN_FORMATS, SCAN_CONTENT_TYPES } from './constants';
|
|
2
|
+
export type ScanFormat = (typeof SCAN_FORMATS)[number];
|
|
3
|
+
export type RequestedScanFormat = Exclude<ScanFormat, 'UNKNOWN'>;
|
|
4
|
+
export type ScanContentType = (typeof SCAN_CONTENT_TYPES)[number];
|
|
5
|
+
export interface ScanPoint {
|
|
12
6
|
x: number;
|
|
13
7
|
y: number;
|
|
14
8
|
}
|
|
15
|
-
/** 一次扫码/解码命中的结果。 */
|
|
16
9
|
export interface ScanResult {
|
|
17
|
-
/**
|
|
10
|
+
/** Unmodified decoded text. */
|
|
18
11
|
value: string;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
/** 条码四角点(可能缺省)。 */
|
|
24
|
-
cornerPoints?: ScanCornerPoint[];
|
|
12
|
+
format: ScanFormat;
|
|
13
|
+
contentType?: ScanContentType;
|
|
14
|
+
/** Coordinates in the recognition image, not screen coordinates. */
|
|
15
|
+
cornerPoints?: readonly ScanPoint[];
|
|
25
16
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
/** 限定识别码制;不传 = 全部。 */
|
|
29
|
-
formats?: readonly BarcodeFormat[];
|
|
30
|
-
}
|
|
31
|
-
/** `<HmsScanView>` / `<Scanner>` 通过回调上报的普通错误对象。 */
|
|
32
|
-
export interface ScanError {
|
|
33
|
-
code: string;
|
|
17
|
+
export interface ScanFailure {
|
|
18
|
+
reason: 'invalid_input' | 'permission_denied' | 'image_unavailable' | 'decode_failed' | 'invalid_response' | 'unavailable' | 'unsupported';
|
|
34
19
|
message: string;
|
|
20
|
+
sourceCode?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface DecodeScanImageInput {
|
|
23
|
+
/** A readable local file URI, borrowed until this operation settles. */
|
|
24
|
+
uri: string;
|
|
25
|
+
formats?: readonly RequestedScanFormat[];
|
|
26
|
+
}
|
|
27
|
+
export type ScanCameraPermission = 'granted' | 'denied' | 'blocked' | 'undetermined';
|
|
28
|
+
export interface ScanTorchState {
|
|
29
|
+
on: boolean;
|
|
30
|
+
available?: boolean;
|
|
31
|
+
lowLight?: boolean;
|
|
35
32
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export type HmsScanErrorCode = 'E_NO_CAMERA_PERMISSION' | 'E_NO_READ_PERMISSION' | 'E_CAMERA_INIT' | 'E_DECODE_FAILED' | 'E_IMAGE_LOAD_FAILED' | 'E_NO_RESULT' | 'E_UNKNOWN';
|
|
40
|
-
/** 库统一抛出的错误类型。 */
|
|
41
|
-
export declare class HmsScanError extends Error {
|
|
42
|
-
readonly code: HmsScanErrorCode;
|
|
43
|
-
constructor(code: HmsScanErrorCode, message?: string);
|
|
33
|
+
export interface ScannerImage {
|
|
34
|
+
uri: string;
|
|
35
|
+
onSourceReleased?(): void;
|
|
44
36
|
}
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
export interface ScanProduct {
|
|
50
|
-
/** 商品名(必填)。 */
|
|
51
|
-
name: string;
|
|
52
|
-
/** 品牌(如 "统一")。 */
|
|
53
|
-
brand?: string;
|
|
54
|
-
/** 字母牌字符;缺省时取 brand 或 name 的首字。 */
|
|
55
|
-
brandChar?: string;
|
|
56
|
-
/** 条码;缺省时取扫到的 value。 */
|
|
57
|
-
barcode?: string;
|
|
58
|
-
/** 规格(如 "500ml × 15 瓶/箱")。 */
|
|
59
|
-
spec?: string;
|
|
60
|
-
/** 库存短描述(如 "充足")。 */
|
|
61
|
-
stockShort?: string;
|
|
62
|
-
/** 价格展示串(如 "¥5.50")。 */
|
|
63
|
-
price?: string;
|
|
64
|
-
/** 价格下方副标题,默认 "建议零售"。 */
|
|
65
|
-
priceCaption?: string;
|
|
37
|
+
/** Native rejection payload; internal to the capability boundary. */
|
|
38
|
+
export interface NativeScanFailure {
|
|
39
|
+
code?: unknown;
|
|
40
|
+
message?: unknown;
|
|
66
41
|
}
|
|
67
42
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEpE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AACvD,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AAEjE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AACD,MAAM,WAAW,UAAU;IACzB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,oEAAoE;IACpE,YAAY,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CACrC;AACD,MAAM,WAAW,WAAW;IAC1B,MAAM,EACF,eAAe,GACf,mBAAmB,GACnB,mBAAmB,GACnB,eAAe,GACf,kBAAkB,GAClB,aAAa,GACb,aAAa,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,WAAW,oBAAoB;IACnC,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;CAC1C;AACD,MAAM,MAAM,oBAAoB,GAC5B,SAAS,GACT,QAAQ,GACR,SAAS,GACT,cAAc,CAAC;AACnB,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AACD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,IAAI,IAAI,CAAC;CAC3B;AAED,qEAAqE;AACrE,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unif/react-native-hms-scan",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Unif React Native 扫码:实时预览、二维码、条码和本地图片识别",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
|
+
"browser": {
|
|
10
|
+
"source": "./src/index.web.tsx",
|
|
11
|
+
"types": "./lib/typescript/src/index.web.d.ts",
|
|
12
|
+
"default": "./lib/module/index.web.js"
|
|
13
|
+
},
|
|
9
14
|
"source": "./src/index.tsx",
|
|
10
15
|
"types": "./lib/typescript/src/index.d.ts",
|
|
11
16
|
"default": "./lib/module/index.js"
|
|
@@ -41,6 +46,8 @@
|
|
|
41
46
|
"prepare": "bob build",
|
|
42
47
|
"typecheck": "tsc",
|
|
43
48
|
"test": "yarn verify:integration-contracts && yarn verify:android-integration && yarn verify:ios-integration && jest",
|
|
49
|
+
"test:native:android": "python3 scripts/test-android-native.py",
|
|
50
|
+
"test:native:ios": "bash scripts/test-ios-native.sh",
|
|
44
51
|
"verify:integration-contracts": "node --test scripts/__tests__/integration-contract.test.mjs",
|
|
45
52
|
"verify:android-integration": "node scripts/verify-android-integration.mjs",
|
|
46
53
|
"verify:ios-integration": "node scripts/verify-ios-integration.mjs",
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import NativeHmsScanView from '../HmsScanViewNativeComponent';
|
|
4
|
+
import { formatConfiguration, parseResultsJson } from '../format';
|
|
5
|
+
import { scanError } from '../errors';
|
|
6
|
+
import type { ScanResult } from '../types';
|
|
7
|
+
import type { HmsScanViewProps } from './types';
|
|
8
|
+
|
|
9
|
+
export function HmsScanView({
|
|
10
|
+
formats,
|
|
11
|
+
continuous = true,
|
|
12
|
+
paused = false,
|
|
13
|
+
torch = false,
|
|
14
|
+
onScanResult,
|
|
15
|
+
onScanError,
|
|
16
|
+
onTorchState,
|
|
17
|
+
...viewProps
|
|
18
|
+
}: HmsScanViewProps) {
|
|
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 <View {...viewProps} />;
|
|
27
|
+
return (
|
|
28
|
+
<NativeHmsScanView
|
|
29
|
+
{...viewProps}
|
|
30
|
+
formatsCsv={config.csv}
|
|
31
|
+
continuous={continuous}
|
|
32
|
+
paused={paused}
|
|
33
|
+
torch={torch}
|
|
34
|
+
onScanResult={(event) => {
|
|
35
|
+
let results: readonly ScanResult[];
|
|
36
|
+
try {
|
|
37
|
+
results = parseResultsJson(event.nativeEvent.resultsJson);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
onScanError?.(
|
|
40
|
+
scanError(error, {
|
|
41
|
+
reason: 'invalid_response',
|
|
42
|
+
message: '扫码结果无法识别',
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
onScanResult?.(results);
|
|
48
|
+
}}
|
|
49
|
+
onScanError={(event) =>
|
|
50
|
+
onScanError?.(
|
|
51
|
+
scanError(event.nativeEvent, {
|
|
52
|
+
reason: 'unavailable',
|
|
53
|
+
message: '扫码相机不可用',
|
|
54
|
+
})
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
onTorchState={(event) => {
|
|
58
|
+
const state = event.nativeEvent;
|
|
59
|
+
onTorchState?.({
|
|
60
|
+
on: state.on,
|
|
61
|
+
...(state.hasAvailable ? { available: state.available } : {}),
|
|
62
|
+
...(state.hasLowLight ? { lowLight: state.lowLight } : {}),
|
|
63
|
+
});
|
|
64
|
+
}}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import { unsupportedScanError } from '../errors';
|
|
4
|
+
import type { HmsScanViewProps } from './types';
|
|
5
|
+
|
|
6
|
+
export function HmsScanView({
|
|
7
|
+
onScanError,
|
|
8
|
+
formats: _formats,
|
|
9
|
+
paused: _paused,
|
|
10
|
+
torch: _torch,
|
|
11
|
+
continuous: _continuous,
|
|
12
|
+
onScanResult: _onScanResult,
|
|
13
|
+
onTorchState: _onTorchState,
|
|
14
|
+
...props
|
|
15
|
+
}: HmsScanViewProps) {
|
|
16
|
+
const callback = useRef(onScanError);
|
|
17
|
+
callback.current = onScanError;
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
callback.current?.(unsupportedScanError());
|
|
20
|
+
}, []);
|
|
21
|
+
return <View {...props} />;
|
|
22
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ViewProps } from 'react-native';
|
|
2
|
+
import type {
|
|
3
|
+
RequestedScanFormat,
|
|
4
|
+
ScanFailure,
|
|
5
|
+
ScanResult,
|
|
6
|
+
ScanTorchState,
|
|
7
|
+
} from '../types';
|
|
8
|
+
|
|
9
|
+
export interface HmsScanViewProps extends ViewProps {
|
|
10
|
+
formats?: readonly RequestedScanFormat[];
|
|
11
|
+
continuous?: boolean;
|
|
12
|
+
paused?: boolean;
|
|
13
|
+
torch?: boolean;
|
|
14
|
+
onScanResult?(results: readonly ScanResult[]): void;
|
|
15
|
+
onScanError?(error: Readonly<ScanFailure>): void;
|
|
16
|
+
onTorchState?(state: Readonly<ScanTorchState>): void;
|
|
17
|
+
}
|
|
@@ -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 字符串回传(由
|
|
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
|
|
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
|
-
/** 限定码制(逗号分隔的
|
|
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
|
-
|
|
43
|
+
onTorchState?: DirectEventHandler<TorchStateEvent>;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
export default codegenNativeComponent<NativeProps>('HmsScanView');
|
package/src/NativeHmsScan.ts
CHANGED
|
@@ -8,10 +8,8 @@ import { TurboModuleRegistry } from 'react-native';
|
|
|
8
8
|
export interface Spec extends TurboModule {
|
|
9
9
|
/**
|
|
10
10
|
* 解码本地图片里的条码 / 二维码。
|
|
11
|
-
* @param uri
|
|
12
|
-
*
|
|
13
|
-
* 两端都不下载远程 URL,也不支持 ph:// / assets-library://。
|
|
14
|
-
* @param formatsCsv 限定码制(逗号分隔的 BarcodeFormat),空串 = 全部。
|
|
11
|
+
* @param uri 本地图片 file URI,由公共能力边界校验。
|
|
12
|
+
* @param formatsCsv 限定码制(逗号分隔的 ScanFormat),空串 = 全部。
|
|
15
13
|
* @returns JSON 编码的 ScanResult[](可能为空数组)。
|
|
16
14
|
*/
|
|
17
15
|
decodeImage(uri: string, formatsCsv: string): Promise<string>;
|
|
@@ -23,4 +21,4 @@ export interface Spec extends TurboModule {
|
|
|
23
21
|
requestCameraPermission(): Promise<string>;
|
|
24
22
|
}
|
|
25
23
|
|
|
26
|
-
export default TurboModuleRegistry.
|
|
24
|
+
export default TurboModuleRegistry.get<Spec>('HmsScan');
|
package/src/ScanError.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ScanFailure } from './types';
|
|
2
|
+
|
|
3
|
+
export class ScanError extends Error implements ScanFailure {
|
|
4
|
+
readonly reason: ScanFailure['reason'];
|
|
5
|
+
readonly sourceCode?: string;
|
|
6
|
+
constructor(error: Readonly<ScanFailure>) {
|
|
7
|
+
super(error.message);
|
|
8
|
+
this.name = 'ScanError';
|
|
9
|
+
this.reason = error.reason;
|
|
10
|
+
this.sourceCode = error.sourceCode;
|
|
11
|
+
Object.setPrototypeOf(this, ScanError.prototype);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -20,12 +20,14 @@ export function DeniedOverlay({ onClose, onSettings }: DeniedOverlayProps) {
|
|
|
20
20
|
<Empty
|
|
21
21
|
icon="permission-denied"
|
|
22
22
|
title="需要相机权限"
|
|
23
|
-
desc="
|
|
23
|
+
desc="开启相机后,才能扫描条码与二维码。请前往系统设置授权。"
|
|
24
24
|
/>
|
|
25
25
|
{/* block(flexGrow:1)而非 flex:1:ButtonBase 非 block 时硬编码 flexGrow:0,
|
|
26
26
|
会压过 style 里的 flex:1 → 按钮塌成 padding 宽、label 被裁(同 ResultFocus)。 */}
|
|
27
27
|
<View style={styles.row}>
|
|
28
|
-
{onClose &&
|
|
28
|
+
{onClose && (
|
|
29
|
+
<Button label="取消" variant="ghost" block onPress={onClose} />
|
|
30
|
+
)}
|
|
29
31
|
<Button
|
|
30
32
|
label="去设置开启"
|
|
31
33
|
variant="primary"
|
|
@@ -11,32 +11,50 @@ import {
|
|
|
11
11
|
|
|
12
12
|
interface ResultFailProps {
|
|
13
13
|
bottomInset: number;
|
|
14
|
+
failed?: boolean;
|
|
14
15
|
/** 重扫:回到取景重新扫描。(退出扫码页是外层工具栏「返回」的事。) */
|
|
15
16
|
onRescan: () => void;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
// 未识别失败的底部弹层:design 的 Empty(error-alert)+ Button(重扫)。
|
|
19
20
|
// 聚焦款不加背景遮罩,与浮层确认卡保持一致。
|
|
20
|
-
export function ResultFail({ bottomInset, onRescan }: ResultFailProps) {
|
|
21
|
+
export function ResultFail({ bottomInset, failed, onRescan }: ResultFailProps) {
|
|
21
22
|
const s = useThemedStyles(makeStyles);
|
|
22
23
|
const anim = useRef(new Animated.Value(0)).current;
|
|
23
24
|
useEffect(() => {
|
|
24
|
-
Animated.timing(anim, {
|
|
25
|
+
Animated.timing(anim, {
|
|
26
|
+
toValue: 1,
|
|
27
|
+
duration: 320,
|
|
28
|
+
useNativeDriver: true,
|
|
29
|
+
}).start();
|
|
25
30
|
}, [anim]);
|
|
26
31
|
|
|
27
32
|
return (
|
|
28
33
|
<Animated.View
|
|
29
34
|
style={[
|
|
30
35
|
s.sheet,
|
|
31
|
-
{
|
|
36
|
+
{
|
|
37
|
+
transform: [
|
|
38
|
+
{
|
|
39
|
+
translateY: anim.interpolate({
|
|
40
|
+
inputRange: [0, 1],
|
|
41
|
+
outputRange: [r(320), 0],
|
|
42
|
+
}),
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
},
|
|
32
46
|
]}
|
|
33
47
|
>
|
|
34
48
|
<View style={s.grabber} />
|
|
35
49
|
<View style={[styles.inner, { paddingBottom: bottomInset + r(14) }]}>
|
|
36
50
|
<Empty
|
|
37
51
|
icon="error-alert"
|
|
38
|
-
title=
|
|
39
|
-
desc=
|
|
52
|
+
title={failed ? '图片识别失败' : '未识别到条码'}
|
|
53
|
+
desc={
|
|
54
|
+
failed
|
|
55
|
+
? '无法读取或解码图片,请重试。'
|
|
56
|
+
: '请将条码完整置于框内、保持平整并对准光线后重试。'
|
|
57
|
+
}
|
|
40
58
|
/>
|
|
41
59
|
<Button label="重扫" variant="primary" block onPress={onRescan} />
|
|
42
60
|
</View>
|