app scaffold

This commit is contained in:
Guangfei.Zhao
2026-08-17 15:29:55 +08:00
commit 681688dfae
301 changed files with 18414 additions and 0 deletions
+98
View File
@@ -0,0 +1,98 @@
/// 扫码能力的对外 API。来源:conti-docs/07-native-integration.md。
///
/// **调用方只允许 import 这个文件**,不允许直接 import `src/generated/` 里的
/// 生成代码(07 §使用规则)。调用方包括 `feature_scan` 和 `core_webview` 的
/// JSBridge——后者正是 01 里「`core_*` 允许依赖 `native_*`」这条例外存在的
/// 原因。
///
/// 本包按 01 的硬约束**不依赖仓库内任何其他包**(连 `core_foundation` 也不),
/// 所以这里抛的是包内自定义的 [NativeScanException];转成统一错误体系里的
/// `NativeException` 由调用方完成。
library;
import 'package:flutter/services.dart';
import 'src/generated/scan_api.g.dart';
export 'src/generated/scan_api.g.dart' show ScanMode, ScanOptions, ScanResult;
/// 扫码失败的错误码。
///
/// 取值与 12 的 `NativeException.code` 对齐,调用方可以直接透传。
abstract final class NativeScanErrorCode {
/// 用户主动取消。
///
/// 这不是异常流程,调用方通常应当静默返回,**不弹错误提示、不上报**。
static const String cancelled = 'CANCELLED';
/// 相机权限被拒绝。
static const String permissionDenied = 'PERMISSION_DENIED';
/// 能力暂时不可用(相机被占用、初始化失败等)。
static const String unavailable = 'UNAVAILABLE';
/// 当前平台没有实现。
///
/// 见 07 §「OHOS 后续演进」:**不允许静默返回空值或占位假数据**——
/// 静默返回会让"这个平台其实没实现"的问题一直藏到用户手里。
static const String unsupportedPlatform = 'UNSUPPORTED_PLATFORM';
/// 超时。
static const String timeout = 'TIMEOUT';
}
/// 扫码相关的异常。
class NativeScanException implements Exception {
/// [code] 取自 [NativeScanErrorCode]。
const NativeScanException(this.code, this.message);
/// 稳定错误码。
final String code;
/// 面向开发者的描述。**不要直接展示给用户**——文案由调用方按 12 的
/// `ErrorPresenter` 决定。
final String message;
/// 是否是用户主动取消。
bool get isCancelled => code == NativeScanErrorCode.cancelled;
@override
String toString() => 'NativeScanException($code): $message';
}
/// 扫码。
class NativeScan {
/// [api] 仅供测试注入;生产走默认实例。
NativeScan({ScanHostApi? api}) : _api = api ?? ScanHostApi();
final ScanHostApi _api;
/// 打开扫码页并等待一次结果。
///
/// 用户取消时抛 [NativeScanException]`code == CANCELLED`)而不是返回 null——
/// 「取消」和「扫到了空字符串」必须能区分开。
Future<ScanResult> startScan(ScanOptions options) async {
try {
return await _api.startScan(options);
} on PlatformException catch (e) {
// 原生异常类型不外泄(07 §使用规则)。
throw NativeScanException(e.code, e.message ?? '扫码失败');
} on MissingPluginException {
throw const NativeScanException(NativeScanErrorCode.unsupportedPlatform, '当前平台未实现扫码能力');
}
}
/// 当前平台是否支持指定识别类型。
///
/// 调用方应当先查这个再决定要不要显示入口,而不是等 [startScan] 抛错——
/// 车牌识别的技术路径尚未确定(07 待确认项),首版可能只有部分平台支持。
Future<bool> isModeSupported(ScanMode mode) async {
try {
return await _api.isModeSupported(mode);
} on PlatformException {
return false;
} on MissingPluginException {
return false;
}
}
}