c42afe86a6
将 Expo 本地通知成功响应包装收口到 notifications 模块 让移动 dispatch 只委托本地通知请求 同步移动壳配置门禁和共享记忆
87 lines
2.3 KiB
TypeScript
87 lines
2.3 KiB
TypeScript
import * as Notifications from 'expo-notifications';
|
|
import { Platform } from 'react-native';
|
|
|
|
import {
|
|
HOST_BRIDGE_MOBILE_LOCAL_NOTIFICATION_CHANNEL_ID,
|
|
type HostBridgeError,
|
|
type HostBridgeRequest,
|
|
type LocalNotificationPayload,
|
|
normalizeHostBridgeLocalNotification,
|
|
} from '../../../../packages/shared/src/contracts/hostBridge';
|
|
import { invalidRequest, ok } from './protocol';
|
|
|
|
Notifications.setNotificationHandler({
|
|
handleNotification: async () => ({
|
|
shouldShowBanner: true,
|
|
shouldShowList: true,
|
|
shouldPlaySound: false,
|
|
shouldSetBadge: false,
|
|
}),
|
|
});
|
|
|
|
function hasNotificationPermission(
|
|
permission: Awaited<ReturnType<typeof Notifications.getPermissionsAsync>>,
|
|
) {
|
|
return (
|
|
permission.granted ||
|
|
permission.ios?.status === Notifications.IosAuthorizationStatus.PROVISIONAL
|
|
);
|
|
}
|
|
|
|
async function ensureNotificationPermission() {
|
|
const currentPermission = await Notifications.getPermissionsAsync();
|
|
if (hasNotificationPermission(currentPermission)) {
|
|
return;
|
|
}
|
|
|
|
const requestedPermission = await Notifications.requestPermissionsAsync({
|
|
ios: {
|
|
allowAlert: true,
|
|
allowBadge: false,
|
|
allowSound: false,
|
|
},
|
|
});
|
|
if (!hasNotificationPermission(requestedPermission)) {
|
|
throw {
|
|
code: 'host_error',
|
|
message: 'notification permission denied',
|
|
} satisfies HostBridgeError;
|
|
}
|
|
}
|
|
|
|
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,
|
|
},
|
|
);
|
|
}
|
|
|
|
await Notifications.scheduleNotificationAsync({
|
|
content: notification,
|
|
trigger:
|
|
Platform.OS === 'android'
|
|
? { channelId: HOST_BRIDGE_MOBILE_LOCAL_NOTIFICATION_CHANNEL_ID }
|
|
: null,
|
|
});
|
|
return true;
|
|
}
|
|
|
|
export async function showMobileHostBridgeLocalNotification(
|
|
request: HostBridgeRequest,
|
|
) {
|
|
const notification = normalizeHostBridgeLocalNotification(request.payload);
|
|
if (!notification) {
|
|
throw invalidRequest('title is required');
|
|
}
|
|
|
|
await showMobileLocalNotification(notification);
|
|
return ok(request, true);
|
|
}
|