From ab16fb3a3fff96a4fa2bc1fc0e56a87c129a4625 Mon Sep 17 00:00:00 2001 From: syuilo <syuilotan@yahoo.co.jp> Date: Tue, 29 May 2018 01:22:39 +0900 Subject: [PATCH] #1634 --- .../app/common/scripts/streaming/home.ts | 24 +++++++++ .../components/ui.header.notifications.vue | 39 ++------------ .../app/mobile/views/components/ui.header.vue | 52 +++++-------------- .../app/mobile/views/components/ui.nav.vue | 52 +++++-------------- src/publishers/notify.ts | 8 +++ .../api/common/read-messaging-message.ts | 8 +++ src/server/api/common/read-notification.ts | 8 +++ src/server/api/endpoints.ts | 10 ---- .../api/endpoints/messaging/messages.ts | 7 --- .../endpoints/messaging/messages/create.ts | 7 +++ src/server/api/endpoints/messaging/unread.ts | 29 ----------- .../notifications/get_unread_count.ts | 28 ---------- .../notifications/mark_as_read_all.ts | 11 ++-- 13 files changed, 92 insertions(+), 191 deletions(-) delete mode 100644 src/server/api/endpoints/messaging/unread.ts delete mode 100644 src/server/api/endpoints/notifications/get_unread_count.ts diff --git a/src/client/app/common/scripts/streaming/home.ts b/src/client/app/common/scripts/streaming/home.ts index 2715b9e0e..50bbb5689 100644 --- a/src/client/app/common/scripts/streaming/home.ts +++ b/src/client/app/common/scripts/streaming/home.ts @@ -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, diff --git a/src/client/app/desktop/views/components/ui.header.notifications.vue b/src/client/app/desktop/views/components/ui.header.notifications.vue index 9eaaa62c6..59a16df9e 100644 --- a/src/client/app/desktop/views/components/ui.header.notifications.vue +++ b/src/client/app/desktop/views/components/ui.header.notifications.vue @@ -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(); }, diff --git a/src/client/app/mobile/views/components/ui.header.vue b/src/client/app/mobile/views/components/ui.header.vue index 09aa18f76..c72b15fb8 100644 --- a/src/client/app/mobile/views/components/ui.header.vue +++ b/src/client/app/mobile/views/components/ui.header.vue @@ -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; } } }); diff --git a/src/client/app/mobile/views/components/ui.nav.vue b/src/client/app/mobile/views/components/ui.nav.vue index 5f0cc831c..de8c21e79 100644 --- a/src/client/app/mobile/views/components/ui.nav.vue +++ b/src/client/app/mobile/views/components/ui.nav.vue @@ -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', { diff --git a/src/publishers/notify.ts b/src/publishers/notify.ts index 2b89515d4..0e480ef01 100644 --- a/src/publishers/notify.ts +++ b/src/publishers/notify.ts @@ -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 }); diff --git a/src/server/api/common/read-messaging-message.ts b/src/server/api/common/read-messaging-message.ts index 28854e186..fd5e9f242 100644 --- a/src/server/api/common/read-messaging-message.ts +++ b/src/server/api/common/read-messaging-message.ts @@ -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'); } diff --git a/src/server/api/common/read-notification.ts b/src/server/api/common/read-notification.ts index cdb87a411..6505c58c3 100644 --- a/src/server/api/common/read-notification.ts +++ b/src/server/api/common/read-notification.ts @@ -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'); } diff --git a/src/server/api/endpoints.ts b/src/server/api/endpoints.ts index c1ac4777b..b4ab65eb1 100644 --- a/src/server/api/endpoints.ts +++ b/src/server/api/endpoints.ts @@ -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, diff --git a/src/server/api/endpoints/messaging/messages.ts b/src/server/api/endpoints/messaging/messages.ts index 0338aba68..9c3a48334 100644 --- a/src/server/api/endpoints/messaging/messages.ts +++ b/src/server/api/endpoints/messaging/messages.ts @@ -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 diff --git a/src/server/api/endpoints/messaging/messages/create.ts b/src/server/api/endpoints/messaging/messages/create.ts index db471839e..41238de1e 100644 --- a/src/server/api/endpoints/messaging/messages/create.ts +++ b/src/server/api/endpoints/messaging/messages/create.ts @@ -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 }); diff --git a/src/server/api/endpoints/messaging/unread.ts b/src/server/api/endpoints/messaging/unread.ts deleted file mode 100644 index 1d83af501..000000000 --- a/src/server/api/endpoints/messaging/unread.ts +++ /dev/null @@ -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 - }); -}); diff --git a/src/server/api/endpoints/notifications/get_unread_count.ts b/src/server/api/endpoints/notifications/get_unread_count.ts deleted file mode 100644 index 9766366ff..000000000 --- a/src/server/api/endpoints/notifications/get_unread_count.ts +++ /dev/null @@ -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 - }); -}); diff --git a/src/server/api/endpoints/notifications/mark_as_read_all.ts b/src/server/api/endpoints/notifications/mark_as_read_all.ts index dce3cb466..7a48ca3e6 100644 --- a/src/server/api/endpoints/notifications/mark_as_read_all.ts +++ b/src/server/api/endpoints/notifications/mark_as_read_all.ts @@ -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'); });