收口原生角标边界

将 Expo 应用角标设置收口到 badge 模块

将 Tauri 任务栏角标设置收口到 badge 模块

同步原生壳结构门禁和架构文档清单
This commit is contained in:
2026-06-19 21:45:04 +08:00
parent af6aea3de2
commit b92b9bbc29
11 changed files with 182 additions and 105 deletions
@@ -0,0 +1,30 @@
import { Platform, PushNotificationIOS } from 'react-native';
import {
HOST_BRIDGE_BADGE_COUNT_MAX,
type HostBridgeError,
normalizeHostBridgeBadgeCount,
type SetBadgeCountPayload,
} from '../../../../packages/shared/src/contracts/hostBridge';
import { invalidRequest } from './protocol';
export function setMobileAppBadgeCount(payload: unknown) {
if (Platform.OS !== 'ios') {
throw {
code: 'unsupported_capability',
message: 'app badge count is only supported on iOS mobile shell',
} satisfies HostBridgeError;
}
const count = normalizeHostBridgeBadgeCount(
(payload as SetBadgeCountPayload | undefined)?.count,
);
if (count === null) {
throw invalidRequest(
`count must be an integer between 0 and ${HOST_BRIDGE_BADGE_COUNT_MAX}`,
);
}
PushNotificationIOS.setApplicationIconBadgeNumber(count);
return true;
}
+3 -30
View File
@@ -1,24 +1,17 @@
import * as Linking from 'expo-linking';
import {
Appearance,
Platform,
PushNotificationIOS,
} from 'react-native';
import { Appearance, Platform } from 'react-native';
import {
type ClipboardWriteTextPayload,
type HapticsImpactPayload,
HOST_BRIDGE_BADGE_COUNT_MAX,
HOST_BRIDGE_VERSION,
type HostBridgeError,
type HostBridgeRequest,
type NavigateNativePagePayload,
normalizeHostBridgeBadgeCount,
normalizeHostBridgeColorScheme,
normalizeHostBridgeExternalUrlPayload,
normalizeHostBridgeLocalNotification,
type OpenExternalUrlPayload,
type SetBadgeCountPayload,
} from '../../../../packages/shared/src/contracts/hostBridge';
import {
openMobileShellExternalNavigation,
@@ -53,6 +46,7 @@ import {
writeMobileClipboardText,
} from './clipboard';
import { runMobileHapticsImpact } from './haptics';
import { setMobileAppBadgeCount } from './badge';
let currentShareTarget: unknown = null;
let navigation: MobileHostBridgeNavigation | null = null;
@@ -105,27 +99,6 @@ async function runHaptics(payload: unknown) {
return true;
}
function setBadgeCount(payload: unknown) {
if (Platform.OS !== 'ios') {
throw {
code: 'unsupported_capability',
message: 'app badge count is only supported on iOS mobile shell',
} satisfies HostBridgeError;
}
const count = normalizeHostBridgeBadgeCount(
(payload as SetBadgeCountPayload | undefined)?.count,
);
if (count === null) {
throw invalidRequest(
`count must be an integer between 0 and ${HOST_BRIDGE_BADGE_COUNT_MAX}`,
);
}
PushNotificationIOS.setApplicationIconBadgeNumber(count);
return true;
}
async function showLocalNotification(payload: unknown) {
const notification = normalizeHostBridgeLocalNotification(payload);
if (!notification) {
@@ -230,7 +203,7 @@ export async function dispatchMobileHostBridgeRequest(
case 'notification.showLocal':
return ok(request, await showLocalNotification(request.payload));
case 'app.setBadgeCount':
return ok(request, setBadgeCount(request.payload));
return ok(request, setMobileAppBadgeCount(request.payload));
case 'share.open':
return ok(request, await openShare(request.payload, currentShareTarget));
case 'share.setTarget':