优化
This commit is contained in:
BIN
client/web/plugins/com.msgbyte.notify/assets/sounds_bing.mp3
Normal file
BIN
client/web/plugins/com.msgbyte.notify/assets/sounds_bing.mp3
Normal file
Binary file not shown.
11
client/web/plugins/com.msgbyte.notify/manifest.json
Normal file
11
client/web/plugins/com.msgbyte.notify/manifest.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"label": "Message notification plugin",
|
||||
"label.zh-CN": "消息通知插件",
|
||||
"name": "com.msgbyte.notify",
|
||||
"url": "/plugins/com.msgbyte.notify/index.js",
|
||||
"version": "0.0.0",
|
||||
"author": "msgbyte",
|
||||
"description": "Ability to add notifications to apps",
|
||||
"description.zh-CN": "为应用增加通知的能力",
|
||||
"requireRestart": true
|
||||
}
|
||||
13
client/web/plugins/com.msgbyte.notify/package.json
Normal file
13
client/web/plugins/com.msgbyte.notify/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "@plugins/com.msgbyte.notify",
|
||||
"main": "src/index.tsx",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21",
|
||||
"tinycon": "^0.6.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/tinycon": "^0.6.3"
|
||||
}
|
||||
}
|
||||
45
client/web/plugins/com.msgbyte.notify/src/bubble.ts
Normal file
45
client/web/plugins/com.msgbyte.notify/src/bubble.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import tinycon from 'tinycon';
|
||||
|
||||
/**
|
||||
* 设置小红点
|
||||
* @param num 小红点数
|
||||
*/
|
||||
let bubbleNum = 0;
|
||||
export function setBubble(num: number) {
|
||||
bubbleNum = num;
|
||||
if (num < 0) {
|
||||
num = 0;
|
||||
}
|
||||
tinycon.setBubble(num >= 100 ? 99 : num);
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加小红点数量
|
||||
*/
|
||||
export function incBubble() {
|
||||
setBubble(bubbleNum + 1);
|
||||
}
|
||||
|
||||
const hiddenProperty =
|
||||
'hidden' in document
|
||||
? 'hidden'
|
||||
: 'webkitHidden' in document
|
||||
? 'webkitHidden'
|
||||
: 'mozHidden' in document
|
||||
? 'mozHidden'
|
||||
: null;
|
||||
const visibilityChangeEvent = hiddenProperty?.replace(
|
||||
/hidden/i,
|
||||
'visibilitychange'
|
||||
);
|
||||
const onVisibilityChange = function () {
|
||||
if (!document[hiddenProperty ?? '']) {
|
||||
// 显示标签页时清空
|
||||
tinycon.setBubble(0);
|
||||
} else {
|
||||
// 隐藏标签页
|
||||
}
|
||||
};
|
||||
if (typeof visibilityChangeEvent === 'string') {
|
||||
document.addEventListener(visibilityChangeEvent, onVisibilityChange);
|
||||
}
|
||||
3
client/web/plugins/com.msgbyte.notify/src/const.ts
Normal file
3
client/web/plugins/com.msgbyte.notify/src/const.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const PLUGIN_NAME = 'com.msgbyte.notify';
|
||||
|
||||
export const PLUGIN_SYSTEM_SETTINGS_DISABLED_SOUND = `${PLUGIN_NAME}.disabledSound`;
|
||||
21
client/web/plugins/com.msgbyte.notify/src/index.tsx
Normal file
21
client/web/plugins/com.msgbyte.notify/src/index.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { regPluginSettings, showToasts } from '@capital/common';
|
||||
import { initNotify } from './notify';
|
||||
import { Translate } from './translate';
|
||||
import { PLUGIN_SYSTEM_SETTINGS_DISABLED_SOUND } from './const';
|
||||
|
||||
if ('Notification' in window) {
|
||||
initNotify();
|
||||
} else {
|
||||
if ((window as Window).innerWidth >= 768) {
|
||||
// if not mobile
|
||||
showToasts(Translate.nosupport, 'warning');
|
||||
}
|
||||
console.warn(Translate.nosupport);
|
||||
}
|
||||
|
||||
regPluginSettings({
|
||||
name: PLUGIN_SYSTEM_SETTINGS_DISABLED_SOUND,
|
||||
label: Translate.disabledSound,
|
||||
position: 'system',
|
||||
type: 'boolean',
|
||||
});
|
||||
150
client/web/plugins/com.msgbyte.notify/src/notify.ts
Normal file
150
client/web/plugins/com.msgbyte.notify/src/notify.ts
Normal file
@@ -0,0 +1,150 @@
|
||||
import {
|
||||
getGlobalState,
|
||||
getCachedUserInfo,
|
||||
getCachedBaseGroupInfo,
|
||||
getServiceWorkerRegistration,
|
||||
navigate,
|
||||
sharedEvent,
|
||||
getCachedUserSettings,
|
||||
getMessageTextDecorators,
|
||||
} from '@capital/common';
|
||||
import { Translate } from './translate';
|
||||
import { incBubble, setBubble } from './bubble';
|
||||
import _get from 'lodash/get';
|
||||
import { PLUGIN_SYSTEM_SETTINGS_DISABLED_SOUND } from './const';
|
||||
|
||||
const TAG = 'tailchat-message';
|
||||
|
||||
export function initNotify() {
|
||||
if (Notification.permission === 'default') {
|
||||
Notification.requestPermission();
|
||||
}
|
||||
|
||||
const registration: ServiceWorkerRegistration | null =
|
||||
getServiceWorkerRegistration();
|
||||
if (registration) {
|
||||
registration.addEventListener('notificationclick', (e: any) => {
|
||||
const tag = e.notification.tag;
|
||||
const data = e.notification.data;
|
||||
|
||||
handleMessageNotifyClick(tag, data);
|
||||
});
|
||||
}
|
||||
|
||||
let isBlur = false;
|
||||
window.addEventListener('focus', () => {
|
||||
setBubble(0); // 点击时清空
|
||||
isBlur = false;
|
||||
});
|
||||
window.addEventListener('blur', () => (isBlur = true));
|
||||
|
||||
sharedEvent.on('receiveUnmutedMessage', (message) => {
|
||||
const currentUserId = getGlobalState()?.user.info._id;
|
||||
|
||||
if (currentUserId === message.author) {
|
||||
// 忽略本人消息
|
||||
return;
|
||||
}
|
||||
|
||||
const hidden = window.document.hidden ?? false;
|
||||
if (hidden || isBlur) {
|
||||
// 如果当前不是活跃窗口或处于隐藏状态,则创建通知
|
||||
|
||||
if (Notification.permission === 'granted') {
|
||||
// TODO: 需要增加显示所在群组
|
||||
Promise.all([
|
||||
getCachedUserInfo(message.author),
|
||||
message.groupId
|
||||
? getCachedBaseGroupInfo(message.groupId).then((d) => d.name)
|
||||
: Promise.resolve(Translate.dm),
|
||||
]).then(([userInfo, scopeName]) => {
|
||||
const nickname = userInfo?.nickname ?? '';
|
||||
const icon = userInfo?.avatar ?? undefined;
|
||||
const content = getMessageTextDecorators().serialize(message.content); // 只显示无富文本形式的消息
|
||||
|
||||
const title = `${Translate.from} [${scopeName}] ${nickname}`;
|
||||
const options: NotificationOptions = {
|
||||
body: content,
|
||||
icon,
|
||||
tag: TAG,
|
||||
renotify: true,
|
||||
data: message,
|
||||
silent: true, // 因为有提示音了,所以禁音默认音
|
||||
};
|
||||
|
||||
if (registration && registration.showNotification) {
|
||||
registration.showNotification(title, options);
|
||||
} else {
|
||||
// fallback
|
||||
const notification = new Notification(title, options);
|
||||
notification.onclick = (e: any) => {
|
||||
const tag = e.target.tag;
|
||||
const data = e.target.data;
|
||||
|
||||
handleMessageNotifyClick(tag, data);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
incBubble();
|
||||
}
|
||||
|
||||
tryPlayNotificationSound(); // 不管当前是不是处于活跃状态,都发出提示音
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击通知栏事件
|
||||
*/
|
||||
function handleMessageNotifyClick(tag, data) {
|
||||
if (tag === 'tailchat-message') {
|
||||
const message = data;
|
||||
|
||||
window.focus();
|
||||
const { converseId, groupId } = message ?? {};
|
||||
if (!converseId) {
|
||||
console.warn('[notify] Not found converseId');
|
||||
return;
|
||||
}
|
||||
if (groupId) {
|
||||
// 群组消息
|
||||
navigate(`/main/group/${groupId}/${converseId}`);
|
||||
} else {
|
||||
// 私信会话
|
||||
navigate(`/main/personal/converse/${converseId}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let userSettings = null;
|
||||
sharedEvent.on('loginSuccess', () => {
|
||||
getCachedUserSettings().then((settings) => {
|
||||
if (userSettings === null) {
|
||||
userSettings = settings;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
sharedEvent.on('userSettingsUpdate', (settings) => {
|
||||
userSettings = settings;
|
||||
});
|
||||
|
||||
/**
|
||||
* 尝试播放通知声音
|
||||
*/
|
||||
async function tryPlayNotificationSound() {
|
||||
if (_get(userSettings, PLUGIN_SYSTEM_SETTINGS_DISABLED_SOUND) === true) {
|
||||
// 消息提示音被禁用
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const audio = new Audio(
|
||||
'/plugins/com.msgbyte.notify/assets/sounds_bing.mp3'
|
||||
);
|
||||
await audio.play();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
21
client/web/plugins/com.msgbyte.notify/src/translate.ts
Normal file
21
client/web/plugins/com.msgbyte.notify/src/translate.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { localTrans } from '@capital/common';
|
||||
|
||||
export const Translate = {
|
||||
nosupport: localTrans({
|
||||
'zh-CN': '当前浏览器不支持 Notification',
|
||||
'en-US': 'This browser not support Notification',
|
||||
}),
|
||||
slient: localTrans({ 'zh-CN': '免打扰', 'en-US': 'Slient' }),
|
||||
from: localTrans({
|
||||
'zh-CN': '来自',
|
||||
'en-US': 'From',
|
||||
}),
|
||||
dm: localTrans({
|
||||
'zh-CN': '私信',
|
||||
'en-US': 'DM',
|
||||
}),
|
||||
disabledSound: localTrans({
|
||||
'zh-CN': '禁用消息通知提示音',
|
||||
'en-US': 'Disable message notification sound',
|
||||
}),
|
||||
};
|
||||
9
client/web/plugins/com.msgbyte.notify/tsconfig.json
Normal file
9
client/web/plugins/com.msgbyte.notify/tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react",
|
||||
"paths": {
|
||||
"@capital/*": ["../../src/plugin/*"],
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user