summaryrefslogtreecommitdiff
path: root/packages/frontend/src/pages/notifications.vue
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src/pages/notifications.vue')
-rw-r--r--packages/frontend/src/pages/notifications.vue95
1 files changed, 95 insertions, 0 deletions
diff --git a/packages/frontend/src/pages/notifications.vue b/packages/frontend/src/pages/notifications.vue
new file mode 100644
index 0000000000..7106951de2
--- /dev/null
+++ b/packages/frontend/src/pages/notifications.vue
@@ -0,0 +1,95 @@
+<template>
+<MkStickyContainer>
+ <template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
+ <MkSpacer :content-max="800">
+ <div v-if="tab === 'all' || tab === 'unread'">
+ <XNotifications class="notifications" :include-types="includeTypes" :unread-only="unreadOnly"/>
+ </div>
+ <div v-else-if="tab === 'mentions'">
+ <XNotes :pagination="mentionsPagination"/>
+ </div>
+ <div v-else-if="tab === 'directNotes'">
+ <XNotes :pagination="directNotesPagination"/>
+ </div>
+ </MkSpacer>
+</MkStickyContainer>
+</template>
+
+<script lang="ts" setup>
+import { computed } from 'vue';
+import { notificationTypes } from 'misskey-js';
+import XNotifications from '@/components/MkNotifications.vue';
+import XNotes from '@/components/MkNotes.vue';
+import * as os from '@/os';
+import { i18n } from '@/i18n';
+import { definePageMetadata } from '@/scripts/page-metadata';
+
+let tab = $ref('all');
+let includeTypes = $ref<string[] | null>(null);
+let unreadOnly = $computed(() => tab === 'unread');
+
+const mentionsPagination = {
+ endpoint: 'notes/mentions' as const,
+ limit: 10,
+};
+
+const directNotesPagination = {
+ endpoint: 'notes/mentions' as const,
+ limit: 10,
+ params: {
+ visibility: 'specified',
+ },
+};
+
+function setFilter(ev) {
+ const typeItems = notificationTypes.map(t => ({
+ text: i18n.t(`_notification._types.${t}`),
+ active: includeTypes && includeTypes.includes(t),
+ action: () => {
+ includeTypes = [t];
+ },
+ }));
+ const items = includeTypes != null ? [{
+ icon: 'ti ti-x',
+ text: i18n.ts.clear,
+ action: () => {
+ includeTypes = null;
+ },
+ }, null, ...typeItems] : typeItems;
+ os.popupMenu(items, ev.currentTarget ?? ev.target);
+}
+
+const headerActions = $computed(() => [tab === 'all' ? {
+ text: i18n.ts.filter,
+ icon: 'ti ti-filter',
+ highlighted: includeTypes != null,
+ handler: setFilter,
+} : undefined, tab === 'all' ? {
+ text: i18n.ts.markAllAsRead,
+ icon: 'ti ti-check',
+ handler: () => {
+ os.apiWithDialog('notifications/mark-all-as-read');
+ },
+} : undefined].filter(x => x !== undefined));
+
+const headerTabs = $computed(() => [{
+ key: 'all',
+ title: i18n.ts.all,
+}, {
+ key: 'unread',
+ title: i18n.ts.unread,
+}, {
+ key: 'mentions',
+ title: i18n.ts.mentions,
+ icon: 'ti ti-at',
+}, {
+ key: 'directNotes',
+ title: i18n.ts.directNotes,
+ icon: 'ti ti-mail',
+}]);
+
+definePageMetadata(computed(() => ({
+ title: i18n.ts.notifications,
+ icon: 'ti ti-bell',
+})));
+</script>