统一移动通知频道契约

将移动端 Android 本地通知频道提升到共享 HostBridge 契约

让 Expo 通知调度和测试复用共享频道标识

增加移动壳配置门禁防止通知频道回退到本地字面量

补充宿主壳方案文档和共享决策记录
This commit is contained in:
2026-06-19 14:37:02 +08:00
parent b6b1e21211
commit e51a65138a
8 changed files with 45 additions and 12 deletions
@@ -70,8 +70,8 @@
- 2026-06-18 桌面图片拖入接入主图槽位:`CreativeImageInputPanel` 在桌面壳声明 `file.imageDropped` 时订阅宿主拖入事件,只在拖入坐标命中当前主图卡片且未被上层元素遮挡时消费事件,避免窗口级拖入被多个创作面板同时接收;成功后仍转换为现有 `File` 上传回调。
- 2026-06-18 H5 背景音乐接入宿主生命周期:`useBackgroundMusic` 通过 `useHostLifecycleActive()` 消费 `subscribeHostAppLifecycle()` 的归一结果,宿主进入后台、inactive 或桌面窗口失焦时降低音量并暂停音频循环,同时 `suspend` WebAudio context;回到 `active + focused` 且用户原本开启音乐时再恢复播放,不改变用户音量设置。
- 2026-06-18 固定玩法音频接入宿主生命周期:前端新增 `useHostLifecycleActive()` 统一消费 `subscribeHostAppLifecycle()``useBackgroundMusic`、拼图运行态和抓大鹅运行态都只依赖该归一状态判断音频可播放性;宿主 inactive、background 或窗口失焦时暂停 `<audio>` / WebAudio,回到 `active + focused` 后仅在运行态仍在播放、音源存在且用户音乐音量大于 0 时恢复,不改变用户音量设置。
- 2026-06-18 本地通知能力:新增 `notification.showLocal` HostBridge capabilityH5 只能传必填 `title` 和可选 `body`,共享契约负责修剪、折叠普通空白、限制长度并拒绝控制字符;Expo 壳通过 `expo-notifications` 请求系统通知权限、创建 Android 本地 channel 并发送即时本地通知,Tauri 壳通过 Rust 侧 `tauri-plugin-notification` 发送系统通知且不开放插件 JS guest API。该能力不包含远程推送、token 注册、定时提醒或后台远程通知,权限拒绝、系统失败或宿主未声明时由 H5 视作失败并继续主流程。
- 2026-06-18 移动壳通知权限边界:Expo 移动壳的 Android 包配置必须阻断 `RECEIVE_BOOT_COMPLETED``SCHEDULE_EXACT_ALARM``USE_EXACT_ALARM`,只保留即时本地通知所需权限和前台展示 handler;移动壳源码不得调用 Expo push token、设备 push token、push token listener、通知响应跳转 listener、定时 / 周期通知 API 或 `seconds` / `repeats` / `timeInterval` / `date` / `calendar` / `daily` / `weekly` / `monthly` / `yearly` 触发字段。`Notifications.scheduleNotificationAsync` 只能保留 iOS / 默认 `trigger: null` 和 Android 固定 `channelId` 的即时通知结构;配置检查和 Expo public config smoke 会拒绝这些权限或远程 / 后台 / 定时通知流程被重新打开。
- 2026-06-18 本地通知能力:新增 `notification.showLocal` HostBridge capabilityH5 只能传必填 `title` 和可选 `body`,共享契约负责修剪、折叠普通空白、限制长度并拒绝控制字符;Expo 壳通过 `expo-notifications` 请求系统通知权限、创建 Android 本地 channel 并发送即时本地通知,Android channel id 由共享契约 `HOST_BRIDGE_MOBILE_LOCAL_NOTIFICATION_CHANNEL_ID` 固定,Tauri 壳通过 Rust 侧 `tauri-plugin-notification` 发送系统通知且不开放插件 JS guest API。该能力不包含远程推送、token 注册、定时提醒或后台远程通知,权限拒绝、系统失败或宿主未声明时由 H5 视作失败并继续主流程。
- 2026-06-18 移动壳通知权限边界:Expo 移动壳的 Android 包配置必须阻断 `RECEIVE_BOOT_COMPLETED``SCHEDULE_EXACT_ALARM``USE_EXACT_ALARM`,只保留即时本地通知所需权限和前台展示 handler;移动壳源码不得调用 Expo push token、设备 push token、push token listener、通知响应跳转 listener、定时 / 周期通知 API 或 `seconds` / `repeats` / `timeInterval` / `date` / `calendar` / `daily` / `weekly` / `monthly` / `yearly` 触发字段。`Notifications.scheduleNotificationAsync` 只能保留 iOS / 默认 `trigger: null` 和 Android 使用共享 channel id 的即时通知结构;配置检查和 Expo public config smoke 会拒绝这些权限或远程 / 后台 / 定时通知流程被重新打开。
- 2026-06-18 草稿生成完成 / 失败通知:平台壳层的 `markDraftReady` / `markDraftFailed` 统一收口会在原生壳声明 `notification.showLocal` 时请求即时本地通知;通知 payload 只包含生成完成 / 失败标题和草稿来源正文,按草稿来源去重,同一草稿重新进入生成中后才允许再次通知。该能力不替代现有完成 / 错误弹窗、作品架红点、队列概览或后端状态回读,通知失败不阻断主流程。根级原生壳门禁必须覆盖平台壳同步层通过真实 HostBridge transport 发出 `notification.showLocal`,避免只测模型文案。
- 2026-06-19 草稿生成 HostBridge 消费门禁:`PlatformEntryFlowShellImpl` 只负责派生草稿通知和未读数量,实际宿主同步经 `platformHostBridgeSync.ts` 调用 `showHostLocalNotification` / `setHostAppBadgeCount``npm run check:native-shells` 必须运行该同步层的真实 Tauri transport 测试,并继续覆盖通知模型、未读计数模型、音频导入和文档导入等 H5 HostBridge 消费测试。
- 2026-06-18 剪贴板读取能力:新增 `clipboard.readText` HostBridge capabilityH5 只能读取纯文本结果,契约限制返回文本最多 100000 字符;Expo 壳通过 `expo-clipboard` 读取系统剪贴板文本,Tauri 壳通过 Rust 侧 `tauri-plugin-clipboard-manager` 读取文本且不开放插件 JS guest API。该能力不读取图片、HTML、文件列表或剪贴板监听事件,宿主未声明或读取失败时由 H5 视作失败并保留原流程。