From f62ad3ed3eccfd242b2d1f1e25f00276f2bfff77 Mon Sep 17 00:00:00 2001 From: syuilo Date: Thu, 2 Nov 2023 15:57:55 +0900 Subject: feat: notification grouping Resolve #12211 --- .../frontend/src/components/MkNotification.vue | 82 ++++++++++++++++++++-- .../frontend/src/components/MkNotifications.vue | 11 ++- packages/frontend/src/pages/settings/general.vue | 3 + packages/frontend/src/store.ts | 4 ++ 4 files changed, 94 insertions(+), 6 deletions(-) (limited to 'packages/frontend/src') diff --git a/packages/frontend/src/components/MkNotification.vue b/packages/frontend/src/components/MkNotification.vue index c507236216..ff20bc591f 100644 --- a/packages/frontend/src/components/MkNotification.vue +++ b/packages/frontend/src/components/MkNotification.vue @@ -9,9 +9,11 @@ SPDX-License-Identifier: AGPL-3.0-only +
+
- +
@@ -52,16 +53,18 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._notification.achievementEarned }} {{ i18n.ts._notification.testNotification }} + {{ i18n.t('_notification.reactedBySomeUsers', { n: notification.reactions.length }) }} + {{ i18n.t('_notification.renotedBySomeUsers', { n: notification.users.length }) }} {{ notification.header }}
- + - + @@ -102,6 +105,24 @@ SPDX-License-Identifier: AGPL-3.0-only + +
+
+ +
+ +
+
+
+
+
+ +
+
@@ -181,6 +202,29 @@ useTooltip(reactionRef, (showing) => { display: block; width: 100%; height: 100%; +} + +.icon_reactionGroup, +.icon_renoteGroup { + display: grid; + align-items: center; + justify-items: center; + width: 80%; + height: 80%; + font-size: 15px; + border-radius: 100%; + color: #fff; +} + +.icon_reactionGroup { + background: #e99a0b; +} + +.icon_renoteGroup { + background: #36d298; +} + +.icon_app { border-radius: 6px; } @@ -305,6 +349,36 @@ useTooltip(reactionRef, (showing) => { flex: 1; } +.reactionsItem { + display: inline-block; + position: relative; + width: 38px; + height: 38px; + margin-top: 8px; + margin-right: 8px; +} + +.reactionsItemAvatar { + width: 100%; + height: 100%; +} + +.reactionsItemReaction { + position: absolute; + z-index: 1; + bottom: -2px; + right: -2px; + width: 20px; + height: 20px; + box-sizing: border-box; + border-radius: 100%; + background: var(--panel); + box-shadow: 0 0 0 3px var(--panel); + font-size: 11px; + text-align: center; + color: #fff; +} + @container (max-width: 600px) { .root { padding: 16px; diff --git a/packages/frontend/src/components/MkNotifications.vue b/packages/frontend/src/components/MkNotifications.vue index 896f97a48d..8d99e440e1 100644 --- a/packages/frontend/src/components/MkNotifications.vue +++ b/packages/frontend/src/components/MkNotifications.vue @@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only @@ -32,6 +32,7 @@ import { $i } from '@/account.js'; import { i18n } from '@/i18n.js'; import { notificationTypes } from '@/const.js'; import { infoImageUrl } from '@/instance.js'; +import { defaultStore } from '@/store.js'; const props = defineProps<{ excludeTypes?: typeof notificationTypes[number][]; @@ -39,7 +40,13 @@ const props = defineProps<{ const pagingComponent = shallowRef>(); -const pagination: Paging = { +const pagination: Paging = defaultStore.state.useGroupedNotifications ? { + endpoint: 'i/notifications-grouped' as const, + limit: 20, + params: computed(() => ({ + excludeTypes: props.excludeTypes ?? undefined, + })), +} : { endpoint: 'i/notifications' as const, limit: 20, params: computed(() => ({ diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index 85d038e3d1..d96c984688 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -88,6 +88,8 @@ SPDX-License-Identifier: AGPL-3.0-only
+ {{ i18n.ts.useGroupedNotifications }} + @@ -255,6 +257,7 @@ const notificationStackAxis = computed(defaultStore.makeGetterSetter('notificati const keepScreenOn = computed(defaultStore.makeGetterSetter('keepScreenOn')); const defaultWithReplies = computed(defaultStore.makeGetterSetter('defaultWithReplies')); const disableStreamingTimeline = computed(defaultStore.makeGetterSetter('disableStreamingTimeline')); +const useGroupedNotifications = computed(defaultStore.makeGetterSetter('useGroupedNotifications')); watch(lang, () => { miLocalStorage.setItem('lang', lang.value as string); diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index 803f2f648d..0f2e642b7b 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -373,6 +373,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'device', default: false, }, + useGroupedNotifications: { + where: 'device', + default: true, + }, })); // TODO: 他のタブと永続化されたstateを同期 -- cgit v1.2.3-freya