From e533ffcff90e863ee46a1ed928e657ac1ec237fe Mon Sep 17 00:00:00 2001 From: LodyAI Date: Wed, 7 Oct 2026 18:39:45 +0800 Subject: [PATCH] fix(stage-tamagotchi-kirie): connect Android QR scanner --- apps/stage-pocket/src/App.vue | 3 +- .../connection/server-channel-qr-scanner.vue | 3 +- .../host-context/android-barcode-scanner.ts | 18 ++++++ .../host-context/android-permissions.ts | 3 +- .../pages/settings/connection/index.vue | 10 ++- .../connection/server-channel-qr-scanner.vue | 61 +++++++++++++++++++ .../src-web/src/shared/eventa/index.ts | 14 +++++ .../src/libs/host-websocket-bridge.ts | 26 +++++--- .../src/libs}/server-channel-qr-probe.ts | 2 +- 9 files changed, 120 insertions(+), 20 deletions(-) create mode 100644 apps/stage-tamagotchi-kirie/src-web/src/renderer/host-context/android-barcode-scanner.ts create mode 100644 apps/stage-tamagotchi-kirie/src-web/src/renderer/pages/settings/connection/server-channel-qr-scanner.vue rename apps/stage-pocket/src/modules/websocket-bridge.ts => packages/stage-ui/src/libs/host-websocket-bridge.ts (90%) rename {apps/stage-pocket/src/modules => packages/stage-ui/src/libs}/server-channel-qr-probe.ts (94%) diff --git a/apps/stage-pocket/src/App.vue b/apps/stage-pocket/src/App.vue index 1a190adfe3..38adad25d4 100644 --- a/apps/stage-pocket/src/App.vue +++ b/apps/stage-pocket/src/App.vue @@ -1,6 +1,7 @@ + + diff --git a/apps/stage-tamagotchi-kirie/src-web/src/shared/eventa/index.ts b/apps/stage-tamagotchi-kirie/src-web/src/shared/eventa/index.ts index 9bec32d8c7..10541cf6f1 100644 --- a/apps/stage-tamagotchi-kirie/src-web/src/shared/eventa/index.ts +++ b/apps/stage-tamagotchi-kirie/src-web/src/shared/eventa/index.ts @@ -95,6 +95,20 @@ export const airiAndroidPermissionEventIds = { request: 'eventa:invoke:airi:android:permission:request', } as const +export interface AiriAndroidBarcodeScanPayload { + scanInstructions: string +} + +export interface AiriAndroidBarcodeScanResult { + ScanResult?: string + error?: string + format?: number +} + +export const airiAndroidBarcodeEventIds = { + scan: 'eventa:invoke:airi:android:barcode:scan', +} as const + export const electronStartTrackMousePosition = defineInvokeEventa('eventa:invoke:electron:start-tracking-mouse-position') export const electronStartDraggingWindow = defineInvokeEventa('eventa:invoke:electron:start-dragging-window') diff --git a/apps/stage-pocket/src/modules/websocket-bridge.ts b/packages/stage-ui/src/libs/host-websocket-bridge.ts similarity index 90% rename from apps/stage-pocket/src/modules/websocket-bridge.ts rename to packages/stage-ui/src/libs/host-websocket-bridge.ts index ae7a6480b8..3a390febd1 100644 --- a/apps/stage-pocket/src/modules/websocket-bridge.ts +++ b/packages/stage-ui/src/libs/host-websocket-bridge.ts @@ -13,24 +13,29 @@ type HostBridgeEvent | { kind: 'error', id: string, message: string } | { kind: 'close', id: string, code?: number, reason?: string } +interface WebkitHostBridge { + messageHandlers?: { + airiHostBridge?: { + postMessage: (payload: string) => void + } + } +} + declare global { interface Window { AiriHostBridge?: { postMessage: (payload: string) => void } - webkit?: { - messageHandlers?: { - airiHostBridge?: { - postMessage: (payload: string) => void - } - } - } __airiHostBridge?: { onNativeMessage?: (payload: string) => void } } } +function getWebkitHostBridge() { + return (window as unknown as { webkit?: WebkitHostBridge }).webkit?.messageHandlers?.airiHostBridge +} + const connections = new Map() function postBridgeMessage(command: HostBridgeCommand) { @@ -39,8 +44,9 @@ function postBridgeMessage(command: HostBridgeCommand) { return } - if (window.webkit?.messageHandlers?.airiHostBridge) { - window.webkit.messageHandlers.airiHostBridge.postMessage(JSON.stringify(command)) + const webkitHostBridge = getWebkitHostBridge() + if (webkitHostBridge) { + webkitHostBridge.postMessage(JSON.stringify(command)) return } @@ -149,7 +155,7 @@ function createCloseBeforeOpenError(event: Extract | undefined { - if (!window.AiriHostBridge && !window.webkit?.messageHandlers?.airiHostBridge) { + if (!window.AiriHostBridge && !getWebkitHostBridge()) { return undefined } diff --git a/apps/stage-pocket/src/modules/server-channel-qr-probe.ts b/packages/stage-ui/src/libs/server-channel-qr-probe.ts similarity index 94% rename from apps/stage-pocket/src/modules/server-channel-qr-probe.ts rename to packages/stage-ui/src/libs/server-channel-qr-probe.ts index e78da1804d..2bf8365171 100644 --- a/apps/stage-pocket/src/modules/server-channel-qr-probe.ts +++ b/packages/stage-ui/src/libs/server-channel-qr-probe.ts @@ -3,7 +3,7 @@ import type { ServerChannelQrPayload } from '@proj-airi/stage-shared/server-chan import { errorMessageFrom } from '@moeru/std' import { Client, createTextProtocolConnector, WebSocketEventSource } from '@proj-airi/server-sdk' -import { getHostWebSocketConnector } from './websocket-bridge' +import { getHostWebSocketConnector } from './host-websocket-bridge' export async function probeServerChannelQrPayload(payload: ServerChannelQrPayload) { if (!payload.urls.some(url => getHostWebSocketConnector(url))) {