This commit is contained in:
		
							parent
							
								
									973b1e42ef
								
							
						
					
					
						commit
						ab16fb3a3f
					
				|  | @ -28,6 +28,30 @@ export class HomeStream extends Stream { | |||
| 			os.store.dispatch('mergeMe', i); | ||||
| 		}); | ||||
| 
 | ||||
| 		this.on('read_all_notifications', () => { | ||||
| 			os.store.dispatch('mergeMe', { | ||||
| 				hasUnreadNotification: false | ||||
| 			}); | ||||
| 		}); | ||||
| 
 | ||||
| 		this.on('unread_notification', () => { | ||||
| 			os.store.dispatch('mergeMe', { | ||||
| 				hasUnreadNotification: true | ||||
| 			}); | ||||
| 		}); | ||||
| 
 | ||||
| 		this.on('read_all_messaging_messages', () => { | ||||
| 			os.store.dispatch('mergeMe', { | ||||
| 				hasUnreadMessagingMessage: false | ||||
| 			}); | ||||
| 		}); | ||||
| 
 | ||||
| 		this.on('unread_messaging_message', () => { | ||||
| 			os.store.dispatch('mergeMe', { | ||||
| 				hasUnreadMessagingMessage: true | ||||
| 			}); | ||||
| 		}); | ||||
| 
 | ||||
| 		this.on('clientSettingUpdated', x => { | ||||
| 			os.store.commit('settings/set', { | ||||
| 				key: x.key, | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="notifications"> | ||||
| 	<button :data-active="isOpen" @click="toggle" title="%i18n:@title%"> | ||||
| 		%fa:R bell%<template v-if="hasUnreadNotifications">%fa:circle%</template> | ||||
| 		%fa:R bell%<template v-if="hasUnreadNotification">%fa:circle%</template> | ||||
| 	</button> | ||||
| 	<div class="pop" v-if="isOpen"> | ||||
| 		<mk-notifications/> | ||||
|  | @ -16,44 +16,15 @@ import contains from '../../../common/scripts/contains'; | |||
| export default Vue.extend({ | ||||
| 	data() { | ||||
| 		return { | ||||
| 			isOpen: false, | ||||
| 			hasUnreadNotifications: false, | ||||
| 			connection: null, | ||||
| 			connectionId: null | ||||
| 			isOpen: false | ||||
| 		}; | ||||
| 	}, | ||||
| 	mounted() { | ||||
| 		if (this.$store.getters.isSignedIn) { | ||||
| 			this.connection = (this as any).os.stream.getConnection(); | ||||
| 			this.connectionId = (this as any).os.stream.use(); | ||||
| 
 | ||||
| 			this.connection.on('read_all_notifications', this.onReadAllNotifications); | ||||
| 			this.connection.on('unread_notification', this.onUnreadNotification); | ||||
| 
 | ||||
| 			// Fetch count of unread notifications | ||||
| 			(this as any).api('notifications/get_unread_count').then(res => { | ||||
| 				if (res.count > 0) { | ||||
| 					this.hasUnreadNotifications = true; | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 	}, | ||||
| 	beforeDestroy() { | ||||
| 		if (this.$store.getters.isSignedIn) { | ||||
| 			this.connection.off('read_all_notifications', this.onReadAllNotifications); | ||||
| 			this.connection.off('unread_notification', this.onUnreadNotification); | ||||
| 			(this as any).os.stream.dispose(this.connectionId); | ||||
| 	computed: { | ||||
| 		hasUnreadNotification(): boolean { | ||||
| 			return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadNotification; | ||||
| 		} | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		onReadAllNotifications() { | ||||
| 			this.hasUnreadNotifications = false; | ||||
| 		}, | ||||
| 
 | ||||
| 		onUnreadNotification() { | ||||
| 			this.hasUnreadNotifications = true; | ||||
| 		}, | ||||
| 
 | ||||
| 		toggle() { | ||||
| 			this.isOpen ? this.close() : this.open(); | ||||
| 		}, | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| 		<p ref="welcomeback" v-if="$store.getters.isSignedIn">おかえりなさい、<b>{{ $store.state.i | userName }}</b>さん</p> | ||||
| 		<div class="content" ref="mainContainer"> | ||||
| 			<button class="nav" @click="$parent.isDrawerOpening = true">%fa:bars%</button> | ||||
| 			<template v-if="hasUnreadNotifications || hasUnreadMessagingMessages || hasGameInvitations">%fa:circle%</template> | ||||
| 			<template v-if="hasUnreadNotification || hasUnreadMessagingMessage || hasGameInvitation">%fa:circle%</template> | ||||
| 			<h1> | ||||
| 				<slot>Misskey</slot> | ||||
| 			</h1> | ||||
|  | @ -25,13 +25,19 @@ export default Vue.extend({ | |||
| 	props: ['func'], | ||||
| 	data() { | ||||
| 		return { | ||||
| 			hasUnreadNotifications: false, | ||||
| 			hasUnreadMessagingMessages: false, | ||||
| 			hasGameInvitations: false, | ||||
| 			hasGameInvitation: false, | ||||
| 			connection: null, | ||||
| 			connectionId: null | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
| 		hasUnreadNotification(): boolean { | ||||
| 			return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadNotification; | ||||
| 		}, | ||||
| 		hasUnreadMessagingMessage(): boolean { | ||||
| 			return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadMessagingMessage; | ||||
| 		} | ||||
| 	}, | ||||
| 	mounted() { | ||||
| 		this.$store.commit('setUiHeaderHeight', 48); | ||||
| 
 | ||||
|  | @ -39,27 +45,9 @@ export default Vue.extend({ | |||
| 			this.connection = (this as any).os.stream.getConnection(); | ||||
| 			this.connectionId = (this as any).os.stream.use(); | ||||
| 
 | ||||
| 			this.connection.on('read_all_notifications', this.onReadAllNotifications); | ||||
| 			this.connection.on('unread_notification', this.onUnreadNotification); | ||||
| 			this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages); | ||||
| 			this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage); | ||||
| 			this.connection.on('othello_invited', this.onOthelloInvited); | ||||
| 			this.connection.on('othello_no_invites', this.onOthelloNoInvites); | ||||
| 
 | ||||
| 			// Fetch count of unread notifications | ||||
| 			(this as any).api('notifications/get_unread_count').then(res => { | ||||
| 				if (res.count > 0) { | ||||
| 					this.hasUnreadNotifications = true; | ||||
| 				} | ||||
| 			}); | ||||
| 
 | ||||
| 			// Fetch count of unread messaging messages | ||||
| 			(this as any).api('messaging/unread').then(res => { | ||||
| 				if (res.count > 0) { | ||||
| 					this.hasUnreadMessagingMessages = true; | ||||
| 				} | ||||
| 			}); | ||||
| 
 | ||||
| 			const ago = (new Date().getTime() - new Date(this.$store.state.i.lastUsedAt).getTime()) / 1000; | ||||
| 			const isHisasiburi = ago >= 3600; | ||||
| 			this.$store.state.i.lastUsedAt = new Date(); | ||||
|  | @ -110,33 +98,17 @@ export default Vue.extend({ | |||
| 	}, | ||||
| 	beforeDestroy() { | ||||
| 		if (this.$store.getters.isSignedIn) { | ||||
| 			this.connection.off('read_all_notifications', this.onReadAllNotifications); | ||||
| 			this.connection.off('unread_notification', this.onUnreadNotification); | ||||
| 			this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages); | ||||
| 			this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage); | ||||
| 			this.connection.off('othello_invited', this.onOthelloInvited); | ||||
| 			this.connection.off('othello_no_invites', this.onOthelloNoInvites); | ||||
| 			(this as any).os.stream.dispose(this.connectionId); | ||||
| 		} | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		onReadAllNotifications() { | ||||
| 			this.hasUnreadNotifications = false; | ||||
| 		}, | ||||
| 		onUnreadNotification() { | ||||
| 			this.hasUnreadNotifications = true; | ||||
| 		}, | ||||
| 		onReadAllMessagingMessages() { | ||||
| 			this.hasUnreadMessagingMessages = false; | ||||
| 		}, | ||||
| 		onUnreadMessagingMessage() { | ||||
| 			this.hasUnreadMessagingMessages = true; | ||||
| 		}, | ||||
| 		onOthelloInvited() { | ||||
| 			this.hasGameInvitations = true; | ||||
| 			this.hasGameInvitation = true; | ||||
| 		}, | ||||
| 		onOthelloNoInvites() { | ||||
| 			this.hasGameInvitations = false; | ||||
| 			this.hasGameInvitation = false; | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ | |||
| 			<div class="links"> | ||||
| 				<ul> | ||||
| 					<li><router-link to="/" :data-active="$route.name == 'index'">%fa:home%%i18n:@home%%fa:angle-right%</router-link></li> | ||||
| 					<li><router-link to="/i/notifications" :data-active="$route.name == 'notifications'">%fa:R bell%%i18n:@notifications%<template v-if="hasUnreadNotifications">%fa:circle%</template>%fa:angle-right%</router-link></li> | ||||
| 					<li><router-link to="/i/notifications" :data-active="$route.name == 'notifications'">%fa:R bell%%i18n:@notifications%<template v-if="hasUnreadNotification">%fa:circle%</template>%fa:angle-right%</router-link></li> | ||||
| 					<li><router-link to="/i/messaging" :data-active="$route.name == 'messaging'">%fa:R comments%%i18n:@messaging%<template v-if="hasUnreadMessagingMessages">%fa:circle%</template>%fa:angle-right%</router-link></li> | ||||
| 					<li><router-link to="/othello" :data-active="$route.name == 'othello'">%fa:gamepad%ゲーム<template v-if="hasGameInvitations">%fa:circle%</template>%fa:angle-right%</router-link></li> | ||||
| 				</ul> | ||||
|  | @ -46,47 +46,31 @@ export default Vue.extend({ | |||
| 	props: ['isOpen'], | ||||
| 	data() { | ||||
| 		return { | ||||
| 			hasUnreadNotifications: false, | ||||
| 			hasUnreadMessagingMessages: false, | ||||
| 			hasGameInvitations: false, | ||||
| 			hasGameInvitation: false, | ||||
| 			connection: null, | ||||
| 			connectionId: null, | ||||
| 			aboutUrl: `${docsUrl}/${lang}/about` | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
| 		hasUnreadNotification(): boolean { | ||||
| 			return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadNotification; | ||||
| 		}, | ||||
| 		hasUnreadMessagingMessage(): boolean { | ||||
| 			return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadMessagingMessage; | ||||
| 		} | ||||
| 	}, | ||||
| 	mounted() { | ||||
| 		if (this.$store.getters.isSignedIn) { | ||||
| 			this.connection = (this as any).os.stream.getConnection(); | ||||
| 			this.connectionId = (this as any).os.stream.use(); | ||||
| 
 | ||||
| 			this.connection.on('read_all_notifications', this.onReadAllNotifications); | ||||
| 			this.connection.on('unread_notification', this.onUnreadNotification); | ||||
| 			this.connection.on('read_all_messaging_messages', this.onReadAllMessagingMessages); | ||||
| 			this.connection.on('unread_messaging_message', this.onUnreadMessagingMessage); | ||||
| 			this.connection.on('othello_invited', this.onOthelloInvited); | ||||
| 			this.connection.on('othello_no_invites', this.onOthelloNoInvites); | ||||
| 
 | ||||
| 			// Fetch count of unread notifications | ||||
| 			(this as any).api('notifications/get_unread_count').then(res => { | ||||
| 				if (res.count > 0) { | ||||
| 					this.hasUnreadNotifications = true; | ||||
| 				} | ||||
| 			}); | ||||
| 
 | ||||
| 			// Fetch count of unread messaging messages | ||||
| 			(this as any).api('messaging/unread').then(res => { | ||||
| 				if (res.count > 0) { | ||||
| 					this.hasUnreadMessagingMessages = true; | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 	}, | ||||
| 	beforeDestroy() { | ||||
| 		if (this.$store.getters.isSignedIn) { | ||||
| 			this.connection.off('read_all_notifications', this.onReadAllNotifications); | ||||
| 			this.connection.off('unread_notification', this.onUnreadNotification); | ||||
| 			this.connection.off('read_all_messaging_messages', this.onReadAllMessagingMessages); | ||||
| 			this.connection.off('unread_messaging_message', this.onUnreadMessagingMessage); | ||||
| 			this.connection.off('othello_invited', this.onOthelloInvited); | ||||
| 			this.connection.off('othello_no_invites', this.onOthelloNoInvites); | ||||
| 			(this as any).os.stream.dispose(this.connectionId); | ||||
|  | @ -98,23 +82,11 @@ export default Vue.extend({ | |||
| 			if (query == null || query == '') return; | ||||
| 			this.$router.push('/search?q=' + encodeURIComponent(query)); | ||||
| 		}, | ||||
| 		onReadAllNotifications() { | ||||
| 			this.hasUnreadNotifications = false; | ||||
| 		}, | ||||
| 		onUnreadNotification() { | ||||
| 			this.hasUnreadNotifications = true; | ||||
| 		}, | ||||
| 		onReadAllMessagingMessages() { | ||||
| 			this.hasUnreadMessagingMessages = false; | ||||
| 		}, | ||||
| 		onUnreadMessagingMessage() { | ||||
| 			this.hasUnreadMessagingMessages = true; | ||||
| 		}, | ||||
| 		onOthelloInvited() { | ||||
| 			this.hasGameInvitations = true; | ||||
| 			this.hasGameInvitation = true; | ||||
| 		}, | ||||
| 		onOthelloNoInvites() { | ||||
| 			this.hasGameInvitations = false; | ||||
| 			this.hasGameInvitation = false; | ||||
| 		}, | ||||
| 		dark() { | ||||
| 			this.$store.commit('device/set', { | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ import Notification from '../models/notification'; | |||
| import Mute from '../models/mute'; | ||||
| import { pack } from '../models/notification'; | ||||
| import stream from './stream'; | ||||
| import User from '../models/user'; | ||||
| 
 | ||||
| export default ( | ||||
| 	notifiee: mongo.ObjectID, | ||||
|  | @ -29,6 +30,13 @@ export default ( | |||
| 	stream(notifiee, 'notification', | ||||
| 		await pack(notification)); | ||||
| 
 | ||||
| 	// Update flag
 | ||||
| 	User.update({ _id: notifiee }, { | ||||
| 		$set: { | ||||
| 			hasUnreadNotification: true | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	// 3秒経っても(今回作成した)通知が既読にならなかったら「未読の通知がありますよ」イベントを発行する
 | ||||
| 	setTimeout(async () => { | ||||
| 		const fresh = await Notification.findOne({ _id: notification._id }, { isRead: true }); | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ import { IMessagingMessage as IMessage } from '../../../models/messaging-message | |||
| import publishUserStream from '../../../publishers/stream'; | ||||
| import { publishMessagingStream } from '../../../publishers/stream'; | ||||
| import { publishMessagingIndexStream } from '../../../publishers/stream'; | ||||
| import User from '../../../models/user'; | ||||
| 
 | ||||
| /** | ||||
|  * Mark as read message(s) | ||||
|  | @ -62,6 +63,13 @@ export default ( | |||
| 		}); | ||||
| 
 | ||||
| 	if (count == 0) { | ||||
| 		// Update flag
 | ||||
| 		User.update({ _id: userId }, { | ||||
| 			$set: { | ||||
| 				hasUnreadMessagingMessage: false | ||||
| 			} | ||||
| 		}); | ||||
| 
 | ||||
| 		// 全ての(いままで未読だった)自分宛てのメッセージを(これで)読みましたよというイベントを発行
 | ||||
| 		publishUserStream(userId, 'read_all_messaging_messages'); | ||||
| 	} | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ import * as mongo from 'mongodb'; | |||
| import { default as Notification, INotification } from '../../../models/notification'; | ||||
| import publishUserStream from '../../../publishers/stream'; | ||||
| import Mute from '../../../models/mute'; | ||||
| import User from '../../../models/user'; | ||||
| 
 | ||||
| /** | ||||
|  * Mark as read notification(s) | ||||
|  | @ -57,6 +58,13 @@ export default ( | |||
| 		}); | ||||
| 
 | ||||
| 	if (count == 0) { | ||||
| 		// Update flag
 | ||||
| 		User.update({ _id: userId }, { | ||||
| 			$set: { | ||||
| 				hasUnreadNotification: false | ||||
| 			} | ||||
| 		}); | ||||
| 
 | ||||
| 		// 全ての(いままで未読だった)通知を(これで)読みましたよというイベントを発行
 | ||||
| 		publishUserStream(userId, 'read_all_notifications'); | ||||
| 	} | ||||
|  |  | |||
|  | @ -279,11 +279,6 @@ const endpoints: Endpoint[] = [ | |||
| 		kind: 'account/read' | ||||
| 	}, | ||||
| 
 | ||||
| 	{ | ||||
| 		name: 'notifications/get_unread_count', | ||||
| 		withCredential: true, | ||||
| 		kind: 'notification-read' | ||||
| 	}, | ||||
| 	{ | ||||
| 		name: 'notifications/delete', | ||||
| 		withCredential: true, | ||||
|  | @ -610,11 +605,6 @@ const endpoints: Endpoint[] = [ | |||
| 		withCredential: true, | ||||
| 		kind: 'messaging-read' | ||||
| 	}, | ||||
| 	{ | ||||
| 		name: 'messaging/unread', | ||||
| 		withCredential: true, | ||||
| 		kind: 'messaging-read' | ||||
| 	}, | ||||
| 	{ | ||||
| 		name: 'messaging/messages', | ||||
| 		withCredential: true, | ||||
|  |  | |||
|  | @ -1,6 +1,3 @@ | |||
| /** | ||||
|  * Module dependencies | ||||
|  */ | ||||
| import $ from 'cafy'; import ID from '../../../../cafy-id'; | ||||
| import Message from '../../../../models/messaging-message'; | ||||
| import User from '../../../../models/user'; | ||||
|  | @ -9,10 +6,6 @@ import read from '../../common/read-messaging-message'; | |||
| 
 | ||||
| /** | ||||
|  * Get messages | ||||
|  * | ||||
|  * @param {any} params | ||||
|  * @param {any} user | ||||
|  * @return {Promise<any>} | ||||
|  */ | ||||
| module.exports = (params, user) => new Promise(async (res, rej) => { | ||||
| 	// Get 'userId' parameter
 | ||||
|  |  | |||
|  | @ -91,6 +91,13 @@ module.exports = (params, user) => new Promise(async (res, rej) => { | |||
| 	publishMessagingIndexStream(message.recipientId, 'message', messageObj); | ||||
| 	publishUserStream(message.recipientId, 'messaging_message', messageObj); | ||||
| 
 | ||||
| 	// Update flag
 | ||||
| 	User.update({ _id: recipient._id }, { | ||||
| 		$set: { | ||||
| 			hasUnreadMessagingMessage: true | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	// 3秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する
 | ||||
| 	setTimeout(async () => { | ||||
| 		const freshMessage = await Message.findOne({ _id: message._id }, { isRead: true }); | ||||
|  |  | |||
|  | @ -1,29 +0,0 @@ | |||
| /** | ||||
|  * Module dependencies | ||||
|  */ | ||||
| import Message from '../../../../models/messaging-message'; | ||||
| import Mute from '../../../../models/mute'; | ||||
| 
 | ||||
| /** | ||||
|  * Get count of unread messages | ||||
|  */ | ||||
| module.exports = (params, user) => new Promise(async (res, rej) => { | ||||
| 	const mute = await Mute.find({ | ||||
| 		muterId: user._id, | ||||
| 		deletedAt: { $exists: false } | ||||
| 	}); | ||||
| 	const mutedUserIds = mute.map(m => m.muteeId); | ||||
| 
 | ||||
| 	const count = await Message | ||||
| 		.count({ | ||||
| 			userId: { | ||||
| 				$nin: mutedUserIds | ||||
| 			}, | ||||
| 			recipientId: user._id, | ||||
| 			isRead: false | ||||
| 		}); | ||||
| 
 | ||||
| 	res({ | ||||
| 		count: count | ||||
| 	}); | ||||
| }); | ||||
|  | @ -1,28 +0,0 @@ | |||
| /** | ||||
|  * Module dependencies | ||||
|  */ | ||||
| import Notification from '../../../../models/notification'; | ||||
| import Mute from '../../../../models/mute'; | ||||
| 
 | ||||
| /** | ||||
|  * Get count of unread notifications | ||||
|  */ | ||||
| module.exports = (params, user) => new Promise(async (res, rej) => { | ||||
| 	const mute = await Mute.find({ | ||||
| 		muterId: user._id | ||||
| 	}); | ||||
| 	const mutedUserIds = mute.map(m => m.muteeId); | ||||
| 
 | ||||
| 	const count = await Notification | ||||
| 		.count({ | ||||
| 			notifieeId: user._id, | ||||
| 			notifierId: { | ||||
| 				$nin: mutedUserIds | ||||
| 			}, | ||||
| 			isRead: false | ||||
| 		}); | ||||
| 
 | ||||
| 	res({ | ||||
| 		count: count | ||||
| 	}); | ||||
| }); | ||||
|  | @ -1,8 +1,6 @@ | |||
| /** | ||||
|  * Module dependencies | ||||
|  */ | ||||
| import Notification from '../../../../models/notification'; | ||||
| import event from '../../../../publishers/stream'; | ||||
| import User from '../../../../models/user'; | ||||
| 
 | ||||
| /** | ||||
|  * Mark as read all notifications | ||||
|  | @ -23,6 +21,13 @@ module.exports = (params, user) => new Promise(async (res, rej) => { | |||
| 	// Response
 | ||||
| 	res(); | ||||
| 
 | ||||
| 	// Update flag
 | ||||
| 	User.update({ _id: user._id }, { | ||||
| 		$set: { | ||||
| 			hasUnreadNotification: false | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	// 全ての通知を読みましたよというイベントを発行
 | ||||
| 	event(user._id, 'read_all_notifications'); | ||||
| }); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue