Improve ServiceWorker notification
This commit is contained in:
		
							parent
							
								
									b0408d1d6e
								
							
						
					
					
						commit
						87fc6522fb
					
				
					 5 changed files with 77 additions and 107 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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, {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
			});
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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({
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue