From 14436c63dfb9d286829dffed92fd5c164109d990 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Thu, 2 Sep 2021 18:33:56 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=A2=9E=E5=8A=A0=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/index.tsx | 8 +++-- shared/manager/socket.ts | 8 +++++ shared/redux/setup.ts | 6 ++++ shared/redux/store.ts | 1 + web/plugins/com.msgbyte.notify/manifest.json | 9 +++++ web/plugins/com.msgbyte.notify/package.json | 7 ++++ web/plugins/com.msgbyte.notify/src/index.ts | 36 ++++++++++++++++++++ web/plugins/com.msgbyte.notify/tsconfig.json | 11 ++++++ web/plugins/com.msgbyte.notify/yarn.lock | 4 +++ web/src/plugin/builtin.ts | 9 +++++ web/src/plugin/common/index.ts | 2 ++ web/src/plugin/common/reg.ts | 9 ++++- web/src/routes/Main/Provider.tsx | 2 ++ web/src/utils/global-state-helper.ts | 13 +++++++ 14 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 shared/manager/socket.ts create mode 100644 web/plugins/com.msgbyte.notify/manifest.json create mode 100644 web/plugins/com.msgbyte.notify/package.json create mode 100644 web/plugins/com.msgbyte.notify/src/index.ts create mode 100644 web/plugins/com.msgbyte.notify/tsconfig.json create mode 100644 web/plugins/com.msgbyte.notify/yarn.lock create mode 100644 web/src/utils/global-state-helper.ts diff --git a/shared/index.tsx b/shared/index.tsx index c3920c86..71422120 100644 --- a/shared/index.tsx +++ b/shared/index.tsx @@ -7,6 +7,7 @@ export type { AppSocket } from './api/socket'; // cache export { getCachedUserInfo, + getCachedConverseInfo, getCachedGroupInviteInfo, getCachedRegistryPlugins, } from './cache/cache'; @@ -47,9 +48,10 @@ export { useUpdateRef } from './hooks/useUpdateRef'; export { buildRegFn } from './manager/buildRegFn'; export { buildRegList } from './manager/buildRegList'; export { buildRegMap } from './manager/buildRegMap'; -export { getStorage, setStorage, useStorage } from './manager/storage'; -export { setTokenGetter, refreshTokenGetter } from './manager/request'; export { setServiceUrl } from './manager/service'; +export { setTokenGetter, refreshTokenGetter } from './manager/request'; +export { regSocketEventListener } from './manager/socket'; +export { getStorage, setStorage, useStorage } from './manager/storage'; export { showToasts, setToasts, @@ -105,7 +107,7 @@ export { userActions, groupActions } from './redux/slices'; export type { ChatConverseState } from './redux/slices/chat'; export { setupRedux } from './redux/setup'; export { createStore } from './redux/store'; -export type { AppStore, AppDispatch } from './redux/store'; +export type { AppStore, AppState, AppDispatch } from './redux/store'; // utils export { diff --git a/shared/manager/socket.ts b/shared/manager/socket.ts new file mode 100644 index 00000000..150796e8 --- /dev/null +++ b/shared/manager/socket.ts @@ -0,0 +1,8 @@ +import { buildRegList } from './buildRegList'; + +interface PluginSocketEventListener { + eventName: string; + eventFn: (...args: any[]) => void; +} +export const [socketEventListeners, regSocketEventListener] = + buildRegList(); diff --git a/shared/redux/setup.ts b/shared/redux/setup.ts index f96502f2..d792060b 100644 --- a/shared/redux/setup.ts +++ b/shared/redux/setup.ts @@ -5,6 +5,7 @@ import type { FriendRequest } from '../model/friend'; import { getCachedConverseInfo } from '../cache/cache'; import type { GroupInfo } from '../model/group'; import type { ChatMessage } from '../model/message'; +import { socketEventListeners } from '../manager/socket'; /** * 初始化 Redux 上下文 @@ -89,4 +90,9 @@ function listenNotify(socket: AppSocket, store: AppStore) { socket.listen<{ groupId: string }>('group.remove', ({ groupId }) => { store.dispatch(groupActions.removeGroup(groupId)); }); + + // 其他的额外的通知 + socketEventListeners.forEach(({ eventName, eventFn }) => { + socket.listen(eventName, eventFn); + }); } diff --git a/shared/redux/store.ts b/shared/redux/store.ts index c73bd058..eabca96f 100644 --- a/shared/redux/store.ts +++ b/shared/redux/store.ts @@ -12,4 +12,5 @@ export function createStore() { } export type AppStore = ReturnType; +export type AppState = ReturnType; export type AppDispatch = AppStore['dispatch']; diff --git a/web/plugins/com.msgbyte.notify/manifest.json b/web/plugins/com.msgbyte.notify/manifest.json new file mode 100644 index 00000000..897d3b38 --- /dev/null +++ b/web/plugins/com.msgbyte.notify/manifest.json @@ -0,0 +1,9 @@ +{ + "label": "消息通知插件", + "name": "com.msgbyte.notify", + "url": "/plugins/com.msgbyte.notify/index.js", + "version": "0.0.0", + "author": "msgbyte", + "description": "为应用增加通知的能力", + "requireRestart": true +} diff --git a/web/plugins/com.msgbyte.notify/package.json b/web/plugins/com.msgbyte.notify/package.json new file mode 100644 index 00000000..c09958fd --- /dev/null +++ b/web/plugins/com.msgbyte.notify/package.json @@ -0,0 +1,7 @@ +{ + "name": "@plugins/com.msgbyte.notify", + "main": "src/index.ts", + "version": "0.0.0", + "private": true, + "dependencies": {} +} diff --git a/web/plugins/com.msgbyte.notify/src/index.ts b/web/plugins/com.msgbyte.notify/src/index.ts new file mode 100644 index 00000000..b3b6863b --- /dev/null +++ b/web/plugins/com.msgbyte.notify/src/index.ts @@ -0,0 +1,36 @@ +import { + regSocketEventListener, + getGlobalState, + getCachedUserInfo, +} from '@capital/common'; + +if (Notification.permission === 'default') { + Notification.requestPermission(); +} + +regSocketEventListener({ + eventName: 'chat.message.add', + eventFn: (message) => { + const currentUserId = getGlobalState()?.user.info._id; + if (currentUserId !== message.author) { + // 创建通知 + + // TODO: 需要增加所在群组 + if (Notification.permission === 'granted') { + Promise.all([getCachedUserInfo(currentUserId)]).then(([userInfo]) => { + console.log(userInfo, message); + const nickname = userInfo?.nickname ?? ''; + const icon = userInfo?.avatar ?? undefined; + const content = message.content; + + new Notification(`来自 ${nickname}`, { + body: content, + icon, + tag: 'tailchat-message', + renotify: true, + }); + }); + } + } + }, +}); diff --git a/web/plugins/com.msgbyte.notify/tsconfig.json b/web/plugins/com.msgbyte.notify/tsconfig.json new file mode 100644 index 00000000..beb3c60f --- /dev/null +++ b/web/plugins/com.msgbyte.notify/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "rootDir": "./src", + "baseUrl": "./src", + "esModuleInterop": true, + "jsx": "react", + "paths": { + "@capital/*": ["../../../src/plugin/*"], + } + } +} diff --git a/web/plugins/com.msgbyte.notify/yarn.lock b/web/plugins/com.msgbyte.notify/yarn.lock new file mode 100644 index 00000000..fb57ccd1 --- /dev/null +++ b/web/plugins/com.msgbyte.notify/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + diff --git a/web/src/plugin/builtin.ts b/web/src/plugin/builtin.ts index 01e80786..24de8ac3 100644 --- a/web/src/plugin/builtin.ts +++ b/web/src/plugin/builtin.ts @@ -24,4 +24,13 @@ export const builtinPlugins: PluginManifest[] = [ description: 'BBCode 格式消息内容解析', requireRestart: true, }, + { + label: '消息通知插件', + name: 'com.msgbyte.notify', + url: '/plugins/com.msgbyte.notify/index.js', + version: '0.0.0', + author: 'msgbyte', + description: '为应用增加通知的能力', + requireRestart: true, + }, ]; diff --git a/web/src/plugin/common/index.ts b/web/src/plugin/common/index.ts index d97c8485..0d377b49 100644 --- a/web/src/plugin/common/index.ts +++ b/web/src/plugin/common/index.ts @@ -9,3 +9,5 @@ export { useCurrentGroupPanelInfo, } from '@/routes/Main/Content/Group/utils'; export { openModal, ModalWrapper, useModalContext } from '@/components/Modal'; +export { getGlobalState } from '@/utils/global-state-helper'; +export { getCachedUserInfo, getCachedConverseInfo } from 'tailchat-shared'; diff --git a/web/src/plugin/common/reg.ts b/web/src/plugin/common/reg.ts index ea096984..b2c3ca05 100644 --- a/web/src/plugin/common/reg.ts +++ b/web/src/plugin/common/reg.ts @@ -1,5 +1,10 @@ import type { ChatInputActionContextProps } from '@/components/ChatBox/ChatInputBox/context'; -import { buildRegFn, buildRegList, FastFormFieldMeta } from 'tailchat-shared'; +import { + buildRegFn, + buildRegList, + FastFormFieldMeta, + regSocketEventListener, +} from 'tailchat-shared'; /** * 注册群组面板 @@ -61,3 +66,5 @@ interface ChatInputAction { export type { ChatInputActionContextProps }; export const [chatInputActions, regChatInputAction] = buildRegList(); + +export { regSocketEventListener }; diff --git a/web/src/routes/Main/Provider.tsx b/web/src/routes/Main/Provider.tsx index 2d5dd7bc..d7cf71ea 100644 --- a/web/src/routes/Main/Provider.tsx +++ b/web/src/routes/Main/Provider.tsx @@ -15,6 +15,7 @@ import { getUserJWT } from '../../utils/jwt-helper'; import { useHistory } from 'react-router'; import { SidebarContextProvider } from './SidebarContext'; import { PortalHost } from '@/components/Portal'; +import { setGlobalStore } from '@/utils/global-state-helper'; /** * 应用状态管理hooks @@ -43,6 +44,7 @@ function useAppState() { // 创建Redux store const store = createStore(); store.dispatch(userActions.setUserInfo(userLoginInfo)); + setGlobalStore(store); // 创建 websocket 连接 const socket = await createSocket(userLoginInfo.token); diff --git a/web/src/utils/global-state-helper.ts b/web/src/utils/global-state-helper.ts new file mode 100644 index 00000000..7005dcf4 --- /dev/null +++ b/web/src/utils/global-state-helper.ts @@ -0,0 +1,13 @@ +import type { AppStore, AppState } from 'tailchat-shared'; + +let _store: AppStore; +export function setGlobalStore(store: AppStore) { + _store = store; +} + +export function getGlobalState(): AppState | null { + if (!_store) { + return null; + } + return _store.getState(); +}