From 87fc6522fb204e9196e34ce62c0ddccfed0b5e57 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 21 Jun 2018 11:35:28 +0900 Subject: [PATCH] Improve ServiceWorker notification --- .../common/scripts/compose-notification.ts | 62 ++++++++++-------- src/client/app/desktop/script.ts | 36 +++------- src/publishers/notify.ts | 10 ++- src/services/note/create.ts | 65 +++++++------------ src/services/note/reaction/create.ts | 11 +--- 5 files changed, 77 insertions(+), 107 deletions(-) diff --git a/src/client/app/common/scripts/compose-notification.ts b/src/client/app/common/scripts/compose-notification.ts index cc28f75998..2e58649ac2 100644 --- a/src/client/app/common/scripts/compose-notification.ts +++ b/src/client/app/common/scripts/compose-notification.ts @@ -20,34 +20,6 @@ export default function(type, data): Notification { icon: data.url + '?thumbnail&size=64' }; - case 'mention': - return { - title: `${getUserName(data.user)}さんから:`, - body: getNoteSummary(data), - icon: data.user.avatarUrl + '?thumbnail&size=64' - }; - - case 'reply': - return { - title: `${getUserName(data.user)}さんから返信:`, - body: getNoteSummary(data), - icon: data.user.avatarUrl + '?thumbnail&size=64' - }; - - case 'quote': - return { - title: `${getUserName(data.user)}さんが引用:`, - body: getNoteSummary(data), - icon: data.user.avatarUrl + '?thumbnail&size=64' - }; - - case 'reaction': - return { - title: `${getUserName(data.user)}: ${getReactionEmoji(data.reaction)}:`, - body: getNoteSummary(data.note), - icon: data.user.avatarUrl + '?thumbnail&size=64' - }; - case 'unread_messaging_message': return { title: `${getUserName(data.user)}さんからメッセージ:`, @@ -62,6 +34,40 @@ export default function(type, data): Notification { icon: data.parent.avatarUrl + '?thumbnail&size=64' }; + case 'notification': + switch (data.type) { + case 'mention': + return { + title: `${getUserName(data.user)}さんから:`, + body: getNoteSummary(data), + icon: data.user.avatarUrl + '?thumbnail&size=64' + }; + + case 'reply': + return { + title: `${getUserName(data.user)}さんから返信:`, + body: getNoteSummary(data), + icon: data.user.avatarUrl + '?thumbnail&size=64' + }; + + case 'quote': + return { + title: `${getUserName(data.user)}さんが引用:`, + body: getNoteSummary(data), + icon: data.user.avatarUrl + '?thumbnail&size=64' + }; + + case 'reaction': + return { + title: `${getUserName(data.user)}: ${getReactionEmoji(data.reaction)}:`, + body: getNoteSummary(data.note), + icon: data.user.avatarUrl + '?thumbnail&size=64' + }; + + default: + return null; + } + default: return null; } diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts index 201ab0a83d..beb358c7ee 100644 --- a/src/client/app/desktop/script.ts +++ b/src/client/app/desktop/script.ts @@ -115,6 +115,15 @@ function registerNotifications(stream: HomeStreamManager) { }); function attach(connection) { + connection.on('notification', notification => { + const _n = composeNotification('notification', notification); + const n = new Notification(_n.title, { + body: _n.body, + icon: _n.icon + }); + setTimeout(n.close.bind(n), 6000); + }); + connection.on('drive_file_created', file => { const _n = composeNotification('drive_file_created', file); const n = new Notification(_n.title, { @@ -124,33 +133,6 @@ function registerNotifications(stream: HomeStreamManager) { setTimeout(n.close.bind(n), 5000); }); - connection.on('mention', note => { - const _n = composeNotification('mention', note); - const n = new Notification(_n.title, { - body: _n.body, - icon: _n.icon - }); - setTimeout(n.close.bind(n), 6000); - }); - - connection.on('reply', note => { - const _n = composeNotification('reply', note); - const n = new Notification(_n.title, { - body: _n.body, - icon: _n.icon - }); - setTimeout(n.close.bind(n), 6000); - }); - - connection.on('quote', note => { - const _n = composeNotification('quote', note); - const n = new Notification(_n.title, { - body: _n.body, - icon: _n.icon - }); - setTimeout(n.close.bind(n), 6000); - }); - connection.on('unread_messaging_message', message => { const _n = composeNotification('unread_messaging_message', message); const n = new Notification(_n.title, { diff --git a/src/publishers/notify.ts b/src/publishers/notify.ts index 0e480ef010..5b25fbf8aa 100644 --- a/src/publishers/notify.ts +++ b/src/publishers/notify.ts @@ -4,6 +4,7 @@ import Mute from '../models/mute'; import { pack } from '../models/notification'; import stream from './stream'; import User from '../models/user'; +import pushSw from '../publishers/push-sw'; export default ( notifiee: mongo.ObjectID, @@ -26,9 +27,10 @@ export default ( resolve(notification); + const packed = await pack(notification); + // Publish notification event - stream(notifiee, 'notification', - await pack(notification)); + stream(notifiee, 'notification', packed); // Update flag User.update({ _id: notifiee }, { @@ -52,7 +54,9 @@ export default ( } //#endregion - stream(notifiee, 'unread_notification', await pack(notification)); + stream(notifiee, 'unread_notification', packed); + + pushSw(notifiee, 'notification', packed); } }, 3000); }); diff --git a/src/services/note/create.ts b/src/services/note/create.ts index 782ac5a4fe..feabe2f0b7 100644 --- a/src/services/note/create.ts +++ b/src/services/note/create.ts @@ -12,7 +12,6 @@ import notify from '../../publishers/notify'; import NoteWatching from '../../models/note-watching'; import watch from './watch'; import Mute from '../../models/mute'; -import pushSw from '../../publishers/push-sw'; import event from '../../publishers/stream'; import parse from '../../mfm/parse'; import { IApp } from '../../models/app'; @@ -20,56 +19,56 @@ import UserList from '../../models/user-list'; import resolveUser from '../../remote/resolve-user'; import Meta from '../../models/meta'; -type Reason = 'reply' | 'quote' | 'mention'; +type Type = 'reply' | 'renote' | 'quote' | 'mention'; /** - * ServiceWorkerへの通知を担当 + * 通知を担当 */ class NotificationManager { - private user: IUser; + private notifier: IUser; private note: any; - private list: Array<{ - user: ILocalUser['_id'], - reason: Reason; + private queue: Array<{ + notifiee: ILocalUser['_id'], + type: Type; }> = []; - constructor(user: IUser, note: any) { - this.user = user; + constructor(notifier: IUser, note: any) { + this.notifier = notifier; this.note = note; } - public push(user: ILocalUser['_id'], reason: Reason) { + public push(notifiee: ILocalUser['_id'], type: Type) { // 自分自身へは通知しない - if (this.user._id.equals(user)) return; + if (this.notifier._id.equals(notifiee)) return; - const exist = this.list.find(x => x.user.equals(user)); + const exist = this.queue.find(x => x.notifiee.equals(notifiee)); if (exist) { // 「メンションされているかつ返信されている」場合は、メンションとしての通知ではなく返信としての通知にする - if (reason != 'mention') { - exist.reason = reason; + if (type != 'mention') { + exist.type = type; } } else { - this.list.push({ - user, reason + this.queue.push({ + notifiee, type }); } } public deliver() { - this.list.forEach(async x => { - const mentionee = x.user; - + this.queue.forEach(async x => { // ミュート情報を取得 const mentioneeMutes = await Mute.find({ - muterId: mentionee + muterId: x.notifiee }); const mentioneesMutedUserIds = mentioneeMutes.map(m => m.muteeId.toString()); // 通知される側のユーザーが通知する側のユーザーをミュートしていない限りは通知する - if (!mentioneesMutedUserIds.includes(this.user._id.toString())) { - pushSw(mentionee, x.reason, this.note); + if (!mentioneesMutedUserIds.includes(this.notifier._id.toString())) { + notify(x.notifiee, this.notifier._id, x.type, { + noteId: this.note._id + }); } }); } @@ -264,10 +263,6 @@ export default async (user: IUser, data: { if (data.renote && data.renote.userId.equals(u._id)) return; // Create notification - notify(u._id, user._id, 'mention', { - noteId: note._id - }); - nm.push(u._id, 'mention'); }); @@ -371,11 +366,6 @@ export default async (user: IUser, data: { } }); - // (自分自身へのリプライでない限りは)通知を作成 - notify(data.reply.userId, user._id, 'reply', { - noteId: note._id - }); - // Fetch watchers NoteWatching.find({ noteId: data.reply._id, @@ -388,9 +378,7 @@ export default async (user: IUser, data: { } }).then(watchers => { watchers.forEach(watcher => { - notify(watcher.userId, user._id, 'reply', { - noteId: note._id - }); + nm.push(watcher.userId, 'reply'); }); }); @@ -399,6 +387,7 @@ export default async (user: IUser, data: { watch(user._id, data.reply); } + // (自分自身へのリプライでない限りは)通知を作成 nm.push(data.reply.userId, 'reply'); } @@ -406,9 +395,7 @@ export default async (user: IUser, data: { if (data.renote) { // Notify const type = data.text ? 'quote' : 'renote'; - notify(data.renote.userId, user._id, type, { - noteId: note._id - }); + nm.push(data.renote.userId, type); // Fetch watchers NoteWatching.find({ @@ -420,9 +407,7 @@ export default async (user: IUser, data: { } }).then(watchers => { watchers.forEach(watcher => { - notify(watcher.userId, user._id, type, { - noteId: note._id - }); + nm.push(watcher.userId, type); }); }); diff --git a/src/services/note/reaction/create.ts b/src/services/note/reaction/create.ts index 5b30bb5e15..b3235e94dc 100644 --- a/src/services/note/reaction/create.ts +++ b/src/services/note/reaction/create.ts @@ -1,9 +1,8 @@ -import { IUser, pack as packUser, isLocalUser, isRemoteUser } from '../../../models/user'; -import Note, { INote, pack as packNote } from '../../../models/note'; +import { IUser, isLocalUser, isRemoteUser } from '../../../models/user'; +import Note, { INote } from '../../../models/note'; import NoteReaction from '../../../models/note-reaction'; import { publishNoteStream } from '../../../publishers/stream'; import notify from '../../../publishers/notify'; -import pushSw from '../../../publishers/push-sw'; import NoteWatching from '../../../models/note-watching'; import watch from '../watch'; import renderLike from '../../../remote/activitypub/renderer/like'; @@ -54,12 +53,6 @@ export default async (user: IUser, note: INote, reaction: string) => new Promise }); } - pushSw(note.userId, 'reaction', { - user: await packUser(user, note.userId), - note: await packNote(note, note.userId), - reaction: reaction - }); - // Fetch watchers NoteWatching .find({