diff --git a/client/mobile/src/lib/inject/message-handler.ts b/client/mobile/src/lib/inject/message-handler.ts index 9d8e07e6..16bb2f3e 100644 --- a/client/mobile/src/lib/inject/message-handler.ts +++ b/client/mobile/src/lib/inject/message-handler.ts @@ -1,6 +1,7 @@ import type WebView from 'react-native-webview'; import { generateInstallPluginScript } from '.'; import { useUIStore } from '../../store/ui'; +import { showNotification } from '../notifications'; export function handleTailchatMessage( type: string, @@ -19,4 +20,14 @@ export function handleTailchatMessage( useUIStore.getState().setColorScheme(payload); return; } + + if (type === 'showNotification') { + showNotification({ + title: payload.title, + body: payload.body, + icon: payload.icon, + }); + + return; + } } diff --git a/client/mobile/src/lib/notifications/index.ts b/client/mobile/src/lib/notifications/index.ts index e20b42df..d6ca3c89 100644 --- a/client/mobile/src/lib/notifications/index.ts +++ b/client/mobile/src/lib/notifications/index.ts @@ -3,6 +3,7 @@ import notifee, { EventType } from '@notifee/react-native'; interface NotificationInfo { title: string; body: string; + icon?: string; } // Create a channel (required for Android) @@ -19,8 +20,9 @@ async function createDefaultChannel() { * 显示本地通知 */ export async function showNotification(info: NotificationInfo) { - // Request permissions (required for iOS) - await notifee.requestPermission(); + console.log('call showNotification', info); + + await notifee.requestPermission(); // Request permissions (required for iOS) const channelId = await createDefaultChannel(); @@ -30,6 +32,8 @@ export async function showNotification(info: NotificationInfo) { body: info.body, android: { channelId, + // largeIcon: info.icon ?? undefined, + // smallIcon: info.icon ?? undefined, // pressAction is needed if you want the notification to open the app when pressed pressAction: { id: 'default', diff --git a/client/web/plugins/com.msgbyte.env.rn/src/index.tsx b/client/web/plugins/com.msgbyte.env.rn/src/index.tsx index 7d2fbd99..f3435f86 100644 --- a/client/web/plugins/com.msgbyte.env.rn/src/index.tsx +++ b/client/web/plugins/com.msgbyte.env.rn/src/index.tsx @@ -1,16 +1,73 @@ -import { sharedEvent } from '@capital/common'; +import { + getGlobalState, + sharedEvent, + getCachedUserInfo, + getCachedBaseGroupInfo, +} from '@capital/common'; +import { Translate } from './translate'; const PLUGIN_NAME = 'ReactNative支持'; console.log(`Plugin ${PLUGIN_NAME} is loaded`); -sharedEvent.on('loadColorScheme', (colorScheme: string) => { - window.postMessage( - { - _isTailchat: true, - type: 'loadColorScheme', - payload: colorScheme, +/** + * 转发事件 + */ +function forwardSharedEvent( + eventName: string, + processPayload?: (payload: any) => Promise<{ type: string; payload: any }> +) { + if (!(window as any).ReactNativeWebView) { + return; + } + + sharedEvent.on(eventName, async (payload: any) => { + let type = eventName; + if (processPayload) { + const res = await processPayload(payload); + payload = res.payload; + type = res.type; + } + + (window as any).ReactNativeWebView.postMessage( + JSON.stringify({ + _isTailchat: true, + type, + payload, + }) + ); + }); +} + +forwardSharedEvent('loadColorScheme'); +forwardSharedEvent('receiveUnmutedMessage', async (payload) => { + const message = payload; + const currentUserId = getGlobalState()?.user.info._id; + + if (currentUserId === message.author) { + // 忽略本人消息 + return; + } + + const [userInfo, scopeName] = await Promise.all([ + getCachedUserInfo(message.author), + message.groupId + ? getCachedBaseGroupInfo(message.groupId).then((d) => d.name) + : Promise.resolve(Translate.dm), + ]); + const nickname = userInfo?.nickname ?? ''; + const icon = userInfo?.avatar ?? undefined; + const content = message.content; + + const title = `${Translate.from} [${scopeName}] ${nickname}`; + const body = content; + + return { + type: 'showNotification', + payload: { + title, + body, + icon, }, - '*' - ); + }; }); diff --git a/client/web/plugins/com.msgbyte.env.rn/src/translate.ts b/client/web/plugins/com.msgbyte.env.rn/src/translate.ts new file mode 100644 index 00000000..19985334 --- /dev/null +++ b/client/web/plugins/com.msgbyte.env.rn/src/translate.ts @@ -0,0 +1,12 @@ +import { localTrans } from '@capital/common'; + +export const Translate = { + from: localTrans({ + 'zh-CN': '来自', + 'en-US': 'From', + }), + dm: localTrans({ + 'zh-CN': '私信', + 'en-US': 'DM', + }), +};