Improve ServiceWorker notification

This commit is contained in:
syuilo 2018-06-21 11:35:28 +09:00
parent 2cd4b62c84
commit 2368f00dfc
5 changed files with 77 additions and 107 deletions

View File

@ -20,34 +20,6 @@ export default function(type, data): Notification {
icon: data.url + '?thumbnail&size=64' 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': case 'unread_messaging_message':
return { return {
title: `${getUserName(data.user)}さんからメッセージ:`, title: `${getUserName(data.user)}さんからメッセージ:`,
@ -62,6 +34,40 @@ export default function(type, data): Notification {
icon: data.parent.avatarUrl + '?thumbnail&size=64' 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: default:
return null; return null;
} }

View File

@ -115,6 +115,15 @@ function registerNotifications(stream: HomeStreamManager) {
}); });
function attach(connection) { 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 => { connection.on('drive_file_created', file => {
const _n = composeNotification('drive_file_created', file); const _n = composeNotification('drive_file_created', file);
const n = new Notification(_n.title, { const n = new Notification(_n.title, {
@ -124,33 +133,6 @@ function registerNotifications(stream: HomeStreamManager) {
setTimeout(n.close.bind(n), 5000); 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 => { connection.on('unread_messaging_message', message => {
const _n = composeNotification('unread_messaging_message', message); const _n = composeNotification('unread_messaging_message', message);
const n = new Notification(_n.title, { const n = new Notification(_n.title, {

View File

@ -4,6 +4,7 @@ import Mute from '../models/mute';
import { pack } from '../models/notification'; import { pack } from '../models/notification';
import stream from './stream'; import stream from './stream';
import User from '../models/user'; import User from '../models/user';
import pushSw from '../publishers/push-sw';
export default ( export default (
notifiee: mongo.ObjectID, notifiee: mongo.ObjectID,
@ -26,9 +27,10 @@ export default (
resolve(notification); resolve(notification);
const packed = await pack(notification);
// Publish notification event // Publish notification event
stream(notifiee, 'notification', stream(notifiee, 'notification', packed);
await pack(notification));
// Update flag // Update flag
User.update({ _id: notifiee }, { User.update({ _id: notifiee }, {
@ -52,7 +54,9 @@ export default (
} }
//#endregion //#endregion
stream(notifiee, 'unread_notification', await pack(notification)); stream(notifiee, 'unread_notification', packed);
pushSw(notifiee, 'notification', packed);
} }
}, 3000); }, 3000);
}); });

View File

@ -12,7 +12,6 @@ import notify from '../../publishers/notify';
import NoteWatching from '../../models/note-watching'; import NoteWatching from '../../models/note-watching';
import watch from './watch'; import watch from './watch';
import Mute from '../../models/mute'; import Mute from '../../models/mute';
import pushSw from '../../publishers/push-sw';
import event from '../../publishers/stream'; import event from '../../publishers/stream';
import parse from '../../mfm/parse'; import parse from '../../mfm/parse';
import { IApp } from '../../models/app'; import { IApp } from '../../models/app';
@ -20,56 +19,56 @@ import UserList from '../../models/user-list';
import resolveUser from '../../remote/resolve-user'; import resolveUser from '../../remote/resolve-user';
import Meta from '../../models/meta'; import Meta from '../../models/meta';
type Reason = 'reply' | 'quote' | 'mention'; type Type = 'reply' | 'renote' | 'quote' | 'mention';
/** /**
* ServiceWorkerへの通知を担 *
*/ */
class NotificationManager { class NotificationManager {
private user: IUser; private notifier: IUser;
private note: any; private note: any;
private list: Array<{ private queue: Array<{
user: ILocalUser['_id'], notifiee: ILocalUser['_id'],
reason: Reason; type: Type;
}> = []; }> = [];
constructor(user: IUser, note: any) { constructor(notifier: IUser, note: any) {
this.user = user; this.notifier = notifier;
this.note = note; 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 (exist) {
// 「メンションされているかつ返信されている」場合は、メンションとしての通知ではなく返信としての通知にする // 「メンションされているかつ返信されている」場合は、メンションとしての通知ではなく返信としての通知にする
if (reason != 'mention') { if (type != 'mention') {
exist.reason = reason; exist.type = type;
} }
} else { } else {
this.list.push({ this.queue.push({
user, reason notifiee, type
}); });
} }
} }
public deliver() { public deliver() {
this.list.forEach(async x => { this.queue.forEach(async x => {
const mentionee = x.user;
// ミュート情報を取得 // ミュート情報を取得
const mentioneeMutes = await Mute.find({ const mentioneeMutes = await Mute.find({
muterId: mentionee muterId: x.notifiee
}); });
const mentioneesMutedUserIds = mentioneeMutes.map(m => m.muteeId.toString()); const mentioneesMutedUserIds = mentioneeMutes.map(m => m.muteeId.toString());
// 通知される側のユーザーが通知する側のユーザーをミュートしていない限りは通知する // 通知される側のユーザーが通知する側のユーザーをミュートしていない限りは通知する
if (!mentioneesMutedUserIds.includes(this.user._id.toString())) { if (!mentioneesMutedUserIds.includes(this.notifier._id.toString())) {
pushSw(mentionee, x.reason, this.note); 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; if (data.renote && data.renote.userId.equals(u._id)) return;
// Create notification // Create notification
notify(u._id, user._id, 'mention', {
noteId: note._id
});
nm.push(u._id, 'mention'); 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 // Fetch watchers
NoteWatching.find({ NoteWatching.find({
noteId: data.reply._id, noteId: data.reply._id,
@ -388,9 +378,7 @@ export default async (user: IUser, data: {
} }
}).then(watchers => { }).then(watchers => {
watchers.forEach(watcher => { watchers.forEach(watcher => {
notify(watcher.userId, user._id, 'reply', { nm.push(watcher.userId, 'reply');
noteId: note._id
});
}); });
}); });
@ -399,6 +387,7 @@ export default async (user: IUser, data: {
watch(user._id, data.reply); watch(user._id, data.reply);
} }
// (自分自身へのリプライでない限りは)通知を作成
nm.push(data.reply.userId, 'reply'); nm.push(data.reply.userId, 'reply');
} }
@ -406,9 +395,7 @@ export default async (user: IUser, data: {
if (data.renote) { if (data.renote) {
// Notify // Notify
const type = data.text ? 'quote' : 'renote'; const type = data.text ? 'quote' : 'renote';
notify(data.renote.userId, user._id, type, { nm.push(data.renote.userId, type);
noteId: note._id
});
// Fetch watchers // Fetch watchers
NoteWatching.find({ NoteWatching.find({
@ -420,9 +407,7 @@ export default async (user: IUser, data: {
} }
}).then(watchers => { }).then(watchers => {
watchers.forEach(watcher => { watchers.forEach(watcher => {
notify(watcher.userId, user._id, type, { nm.push(watcher.userId, type);
noteId: note._id
});
}); });
}); });

View File

@ -1,9 +1,8 @@
import { IUser, pack as packUser, isLocalUser, isRemoteUser } from '../../../models/user'; import { IUser, isLocalUser, isRemoteUser } from '../../../models/user';
import Note, { INote, pack as packNote } from '../../../models/note'; import Note, { INote } from '../../../models/note';
import NoteReaction from '../../../models/note-reaction'; import NoteReaction from '../../../models/note-reaction';
import { publishNoteStream } from '../../../publishers/stream'; import { publishNoteStream } from '../../../publishers/stream';
import notify from '../../../publishers/notify'; import notify from '../../../publishers/notify';
import pushSw from '../../../publishers/push-sw';
import NoteWatching from '../../../models/note-watching'; import NoteWatching from '../../../models/note-watching';
import watch from '../watch'; import watch from '../watch';
import renderLike from '../../../remote/activitypub/renderer/like'; 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 // Fetch watchers
NoteWatching NoteWatching
.find({ .find({