接入移动端原生扫码能力

新增 scanner.scanQrCode HostBridge 契约与二维码结果归一。

接入 Expo Camera 扫码 overlay 并保留 H5 浏览器扫码回退。

让 Tauri 白名单识别扫码 method 但不声明桌面扫码能力。

同步原生壳门禁、Expo 权限检查、方案文档和共享决策记录。
This commit is contained in:
2026-06-19 05:13:21 +08:00
parent a471e69455
commit e4b9cbf09d
26 changed files with 758 additions and 28 deletions
+8 -3
View File
@@ -1080,7 +1080,11 @@ const desktopCapabilities = extractDesktopCapabilities(
const desktopHandledMethods = extractDesktopHandledMethods(
desktopHostBridgeDispatchSource,
);
const sdkBackedCapabilities = ['auth.requestLogin', 'payment.request'];
const hostBridgeAcceptedUnsupportedMethods = [
'auth.requestLogin',
'payment.request',
'scanner.scanQrCode',
];
if (desktopHostBridgeProtocol !== sharedHostBridgeProtocol) {
throw new Error(
`desktop shell HostBridge protocol drifted: expected ${sharedHostBridgeProtocol} but got ${desktopHostBridgeProtocol}`,
@@ -1200,7 +1204,7 @@ assertSameList(
'desktop shell HostBridge capability profile',
);
for (const capability of sdkBackedCapabilities) {
for (const capability of ['auth.requestLogin', 'payment.request']) {
if (desktopCapabilities.includes(capability)) {
throw new Error(
`desktop shell must not declare ${capability} until a real SDK/channel flow is implemented`,
@@ -1221,7 +1225,8 @@ if (missingDesktopMethodHandlers.length > 0) {
const undeclaredDesktopMethodHandlers = desktopHandledMethods.filter(
(method) =>
!desktopCapabilities.includes(method) && !sdkBackedCapabilities.includes(method),
!desktopCapabilities.includes(method) &&
!hostBridgeAcceptedUnsupportedMethods.includes(method),
);
if (undeclaredDesktopMethodHandlers.length > 0) {
throw new Error(
@@ -636,7 +636,7 @@ mod tests {
#[test]
fn unsupported_method_is_explicit() {
for method in ["auth.requestLogin", "payment.request"] {
for method in ["auth.requestLogin", "payment.request", "scanner.scanQrCode"] {
let response = resolve_host_bridge_request(request(method));
assert!(!response.ok);
@@ -5,7 +5,7 @@ use std::sync::{Arc, Condvar, Mutex};
pub(crate) const HOST_BRIDGE_PROTOCOL: &str = "GenarrativeHostBridge";
pub(crate) const HOST_BRIDGE_VERSION: u8 = 1;
pub(crate) const HOST_BRIDGE_METHODS: [&str; 23] = [
pub(crate) const HOST_BRIDGE_METHODS: [&str; 24] = [
"host.getRuntime",
"appearance.getColorScheme",
"auth.requestLogin",
@@ -25,6 +25,7 @@ pub(crate) const HOST_BRIDGE_METHODS: [&str; 23] = [
"file.exportImage",
"file.importImage",
"file.captureImage",
"scanner.scanQrCode",
"file.importAudio",
"file.exportAudio",
"haptics.impact",