diff --git a/CHANGELOG.md b/CHANGELOG.md index 215555df7222324461451cafd4a21aa001635f2a..6550db98039c36bd4c1768d9160e16470064e9d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,9 @@ - アカウント登録ã«ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã®è¨å®šã‚’å¿…é ˆã«ã™ã‚‹ã‚ªãƒ—ション - クライアント: アニメーションを減らã™è¨å®šã‚’メニューã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã«ã‚‚é©ç”¨ã™ã‚‹ã‚ˆã†ã« - クライアント: MFM関数構文ã®ã‚µã‚¸ã‚§ã‚¹ãƒˆã‚’実装 +- クライアント: 未èªã®é€šçŸ¥ã®ã¿è¡¨ç¤ºã™ã‚‹æ©Ÿèƒ½ - ActivityPub: HTML -> MFMã®å¤‰æ›ã‚’強化 +- API: i/notifications ã« unreadOnly ã‚ªãƒ—ã‚·ãƒ§ãƒ³ã‚’è¿½åŠ - API: apç³»ã®ã‚¨ãƒ³ãƒ‰ãƒã‚¤ãƒ³ãƒˆã‚’ãƒã‚°ã‚¤ãƒ³å¿…é ˆåŒ–+ãƒ¬ãƒ¼ãƒˆãƒªãƒŸãƒƒãƒˆè¿½åŠ - Misskeyã®ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚ªãƒ—ã‚·ãƒ§ãƒ³ã‚’å»ƒæ¢ - 代ã‚ã‚Šã«ç’°å¢ƒå¤‰æ•°ã§è¨å®šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 0be87cf2c500cab37fa35d4b47cf346f26262563..eb72c7ca17b9bca0ed5e3951e2de18e5bd7657c4 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -792,6 +792,7 @@ unresolved: "未解決" itsOn: "オンã«ãªã£ã¦ã„ã¾ã™" itsOff: "オフã«ãªã£ã¦ã„ã¾ã™" emailRequiredForSignup: "アカウント登録ã«ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’å¿…é ˆã«ã™ã‚‹" +unread: "未èª" _signup: almostThere: "ã»ã¨ã‚“ã©å®Œäº†ã§ã™" diff --git a/src/client/components/notifications.vue b/src/client/components/notifications.vue index e91f18a69300f40fe06f27ca7b536d8e45ba8560..8be1e191b99f8aea269abc0870a21fcec8cf5dfd 100644 --- a/src/client/components/notifications.vue +++ b/src/client/components/notifications.vue @@ -48,6 +48,11 @@ export default defineComponent({ required: false, default: null, }, + unreadOnly: { + type: Boolean, + required: false, + default: false, + }, }, data() { @@ -58,6 +63,7 @@ export default defineComponent({ limit: 10, params: () => ({ includeTypes: this.allIncludeTypes || undefined, + unreadOnly: this.unreadOnly, }) }, }; @@ -76,6 +82,11 @@ export default defineComponent({ }, deep: true }, + unreadOnly: { + handler() { + this.reload(); + }, + }, // TODO: vue/vuexã®ãƒã‚°ã‹ä»•æ§˜ã‹ã¯ä¸æ˜Žãªã‚‚ã®ã®ã€ãƒ—ãƒãƒ•ã‚£ãƒ¼ãƒ«æ›´æ–°ã™ã‚‹ãªã©ã—㦠$i ãŒæ›´æ–°ã•ã‚Œã‚‹ã¨ã€ // mutingNotificationTypes ã«å¤‰åŒ–ãŒç„¡ãã¦ã‚‚ã“ã®ãƒãƒ³ãƒ‰ãƒ©ãƒ¼ãŒå‘¼ã³å‡ºã•ã‚Œç„¡é§„ãªãƒªãƒãƒ¼ãƒ‰ãŒç™ºç”Ÿã™ã‚‹ã®ã‚’ç›´ã™ '$i.mutingNotificationTypes': { diff --git a/src/client/pages/notifications.vue b/src/client/pages/notifications.vue index 6cbcc9b8e5a846e2dc8d3aa8c904e3fcf48fc173..9728b87bf1a4b6397f97ed05e2e2bbe911d46d23 100644 --- a/src/client/pages/notifications.vue +++ b/src/client/pages/notifications.vue @@ -2,13 +2,13 @@ <div> <MkHeader :info="header"/> <div class="clupoqwt" v-size="{ min: [800] }"> - <XNotifications class="notifications" @before="before" @after="after" page/> + <XNotifications class="notifications" @before="before" @after="after" :unread-only="tab === 'unread'"/> </div> </div> </template> <script lang="ts"> -import { defineComponent } from 'vue'; +import { computed, defineComponent } from 'vue'; import Progress from '@client/scripts/loading'; import XNotifications from '@client/components/notifications.vue'; import * as os from '@client/os'; @@ -26,7 +26,8 @@ export default defineComponent({ icon: 'fas fa-bell', bg: 'var(--bg)', }, - header: { + tab: 'all', + header: computed(() => ({ title: this.$ts.notifications, icon: 'fas fa-bell', bg: 'var(--bg)', @@ -35,9 +36,18 @@ export default defineComponent({ icon: 'fas fa-check', handler: () => { os.apiWithDialog('notifications/mark-all-as-read'); - } - }] - }, + }, + }], + tabs: [{ + active: this.tab === 'all', + title: this.$ts.all, + onClick: () => { this.tab = 'all'; }, + }, { + active: this.tab === 'unread', + title: this.$ts.unread, + onClick: () => { this.tab = 'unread'; }, + },] + })), }; }, diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts index 3c265a10c173bdd86c795f0ea59d0d4a0a00a1c3..0c5586054ff00d451e40e6d70993b9452cdd96ce 100644 --- a/src/server/api/endpoints/i/notifications.ts +++ b/src/server/api/endpoints/i/notifications.ts @@ -33,6 +33,11 @@ export const meta = { default: false }, + unreadOnly: { + validator: $.optional.bool, + default: false + }, + markAsRead: { validator: $.optional.bool, default: true @@ -105,6 +110,10 @@ export default define(meta, async (ps, user) => { query.andWhere(`notification.type NOT IN (:...excludeTypes)`, { excludeTypes: ps.excludeTypes }); } + if (ps.unreadOnly) { + query.andWhere(`notification.isRead = false`); + } + const notifications = await query.take(ps.limit!).getMany(); // Mark all as read