From e0d519686bdfad341a04f76fa96957a66f3a2276 Mon Sep 17 00:00:00 2001 From: kdletters Date: Sat, 20 Jun 2026 14:22:45 +0800 Subject: [PATCH] =?UTF-8?q?=E9=94=81=E5=AE=9A=E7=A7=BB=E5=8A=A8=E5=A3=B3?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E6=8A=95=E9=80=92=E5=A4=B1=E8=B4=A5=E5=93=8D?= =?UTF-8?q?=E5=BA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移动壳通知通道创建失败返回稳定错误 移动壳通知调度失败返回稳定错误 移动壳配置检查补充通知投递失败边界反查 --- apps/mobile-shell/scripts/check-config.mjs | 4 ++ .../src/host-bridge/notifications.test.ts | 29 ++++++++++++++ .../src/host-bridge/notifications.ts | 39 +++++++++++-------- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/apps/mobile-shell/scripts/check-config.mjs b/apps/mobile-shell/scripts/check-config.mjs index f6831b93b..7787b1905 100644 --- a/apps/mobile-shell/scripts/check-config.mjs +++ b/apps/mobile-shell/scripts/check-config.mjs @@ -1952,6 +1952,7 @@ for (const notificationSnippet of [ 'normalizeHostBridgeLocalNotification(request.payload)', "invalidRequest('title is required')", "message: 'notification permission unavailable'", + "message: 'notification delivery unavailable'", 'showMobileLocalNotification(notification)', 'ok(request, await showMobileLocalNotification(notification))', 'HOST_BRIDGE_LOCAL_NOTIFICATION_DELIVERED_TO_SYSTEM_RESULT', @@ -1964,7 +1965,10 @@ for (const notificationSnippet of [ for (const snippet of [ 'rejects delivery when current permission lookup is unavailable', 'rejects delivery when permission request is unavailable', + 'maps Android channel setup failures to stable delivery errors', + 'maps native notification schedule failures to stable delivery errors', "message: 'notification permission unavailable'", + "message: 'notification delivery unavailable'", 'expect(Notifications.setNotificationChannelAsync).not.toHaveBeenCalled()', 'expect(Notifications.scheduleNotificationAsync).not.toHaveBeenCalled()', ]) { diff --git a/apps/mobile-shell/src/host-bridge/notifications.test.ts b/apps/mobile-shell/src/host-bridge/notifications.test.ts index 7c59dca6f..f004778ce 100644 --- a/apps/mobile-shell/src/host-bridge/notifications.test.ts +++ b/apps/mobile-shell/src/host-bridge/notifications.test.ts @@ -226,6 +226,35 @@ describe('mobile local notification helpers', () => { }); }); + test('maps Android channel setup failures to stable delivery errors', async () => { + setPlatformOS('android'); + vi.mocked(Notifications.setNotificationChannelAsync).mockRejectedValueOnce( + new Error('native channel failed'), + ); + + await expect( + showMobileLocalNotification({ title: '生成完成' }), + ).rejects.toMatchObject({ + code: 'host_error', + message: 'notification delivery unavailable', + }); + + expect(Notifications.scheduleNotificationAsync).not.toHaveBeenCalled(); + }); + + test('maps native notification schedule failures to stable delivery errors', async () => { + vi.mocked(Notifications.scheduleNotificationAsync).mockRejectedValueOnce( + new Error('native schedule failed'), + ); + + await expect( + showMobileLocalNotification({ title: '生成完成' }), + ).rejects.toMatchObject({ + code: 'host_error', + message: 'notification delivery unavailable', + }); + }); + test('normalizes HostBridge payload and wraps structured delivery result', async () => { const response = await showMobileHostBridgeLocalNotification( request({ diff --git a/apps/mobile-shell/src/host-bridge/notifications.ts b/apps/mobile-shell/src/host-bridge/notifications.ts index 6b6ed7526..4a0b1913e 100644 --- a/apps/mobile-shell/src/host-bridge/notifications.ts +++ b/apps/mobile-shell/src/host-bridge/notifications.ts @@ -74,23 +74,30 @@ export async function showMobileLocalNotification( notification: LocalNotificationPayload, ) { await ensureNotificationPermission(); - if (Platform.OS === 'android') { - await Notifications.setNotificationChannelAsync( - HOST_BRIDGE_MOBILE_LOCAL_NOTIFICATION_CHANNEL_ID, - { - name: 'Genarrative', - importance: Notifications.AndroidImportance.DEFAULT, - }, - ); - } + try { + if (Platform.OS === 'android') { + await Notifications.setNotificationChannelAsync( + HOST_BRIDGE_MOBILE_LOCAL_NOTIFICATION_CHANNEL_ID, + { + name: 'Genarrative', + importance: Notifications.AndroidImportance.DEFAULT, + }, + ); + } - await Notifications.scheduleNotificationAsync({ - content: notification, - trigger: - Platform.OS === 'android' - ? { channelId: HOST_BRIDGE_MOBILE_LOCAL_NOTIFICATION_CHANNEL_ID } - : null, - }); + await Notifications.scheduleNotificationAsync({ + content: notification, + trigger: + Platform.OS === 'android' + ? { channelId: HOST_BRIDGE_MOBILE_LOCAL_NOTIFICATION_CHANNEL_ID } + : null, + }); + } catch { + throw { + code: 'host_error', + message: 'notification delivery unavailable', + } satisfies HostBridgeError; + } return HOST_BRIDGE_LOCAL_NOTIFICATION_DELIVERED_TO_SYSTEM_RESULT; }