mirror of
https://github.com/vrcx-team/VRCX.git
synced 2026-04-06 00:32:02 +02:00
Display only unseen notifications in the notification center and remove the past notifications section from the list
This commit is contained in:
@@ -124,6 +124,16 @@ export const useNotificationStore = defineStore('Notification', () => {
|
||||
(n) => getNotificationCategory(n.type) === 'other'
|
||||
)
|
||||
);
|
||||
const unseenSet = computed(() => new Set(unseenNotifications.value));
|
||||
const unseenFriendNotifications = computed(() =>
|
||||
friendNotifications.value.filter((n) => unseenSet.value.has(n.id))
|
||||
);
|
||||
const unseenGroupNotifications = computed(() =>
|
||||
groupNotifications.value.filter((n) => unseenSet.value.has(n.id))
|
||||
);
|
||||
const unseenOtherNotifications = computed(() =>
|
||||
otherNotifications.value.filter((n) => unseenSet.value.has(n.id))
|
||||
);
|
||||
const hasUnseenNotifications = computed(
|
||||
() => unseenNotifications.value.length > 0
|
||||
);
|
||||
@@ -2703,6 +2713,9 @@ export const useNotificationStore = defineStore('Notification', () => {
|
||||
friendNotifications,
|
||||
groupNotifications,
|
||||
otherNotifications,
|
||||
unseenFriendNotifications,
|
||||
unseenGroupNotifications,
|
||||
unseenOtherNotifications,
|
||||
hasUnseenNotifications,
|
||||
getNotificationCategory,
|
||||
isNotificationExpired,
|
||||
|
||||
@@ -10,43 +10,40 @@
|
||||
<TabsList class="mr-4 ml-2 mt-2 grid w-auto grid-cols-3">
|
||||
<TabsTrigger value="friend">
|
||||
{{ t('side_panel.notification_center.tab_friend') }}
|
||||
<span v-if="activeCount.friend" class="ml-1 text-xs text-muted-foreground">
|
||||
({{ activeCount.friend }})
|
||||
<span v-if="unseenFriendNotifications.length" class="ml-1 text-xs text-muted-foreground">
|
||||
({{ unseenFriendNotifications.length }})
|
||||
</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="group">
|
||||
{{ t('side_panel.notification_center.tab_group') }}
|
||||
<span v-if="activeCount.group" class="ml-1 text-xs text-muted-foreground">
|
||||
({{ activeCount.group }})
|
||||
<span v-if="unseenGroupNotifications.length" class="ml-1 text-xs text-muted-foreground">
|
||||
({{ unseenGroupNotifications.length }})
|
||||
</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="other">
|
||||
{{ t('side_panel.notification_center.tab_other') }}
|
||||
<span v-if="activeCount.other" class="ml-1 text-xs text-muted-foreground">
|
||||
({{ activeCount.other }})
|
||||
<span v-if="unseenOtherNotifications.length" class="ml-1 text-xs text-muted-foreground">
|
||||
({{ unseenOtherNotifications.length }})
|
||||
</span>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="friend" class="mt-0 min-h-0 flex-1 overflow-hidden">
|
||||
<NotificationList
|
||||
:notifications="friendNotifications"
|
||||
:unseen-ids="unseenNotifications"
|
||||
:notifications="unseenFriendNotifications"
|
||||
@show-invite-response="showSendInviteResponseDialog"
|
||||
@show-invite-request-response="showSendInviteRequestResponseDialog"
|
||||
@navigate-to-table="navigateToTable" />
|
||||
</TabsContent>
|
||||
<TabsContent value="group" class="mt-0 min-h-0 flex-1 overflow-hidden">
|
||||
<NotificationList
|
||||
:notifications="groupNotifications"
|
||||
:unseen-ids="unseenNotifications"
|
||||
:notifications="unseenGroupNotifications"
|
||||
@show-invite-response="showSendInviteResponseDialog"
|
||||
@show-invite-request-response="showSendInviteRequestResponseDialog"
|
||||
@navigate-to-table="navigateToTable" />
|
||||
</TabsContent>
|
||||
<TabsContent value="other" class="mt-0 min-h-0 flex-1 overflow-hidden">
|
||||
<NotificationList
|
||||
:notifications="otherNotifications"
|
||||
:unseen-ids="unseenNotifications"
|
||||
:notifications="unseenOtherNotifications"
|
||||
@show-invite-response="showSendInviteResponseDialog"
|
||||
@show-invite-request-response="showSendInviteRequestResponseDialog"
|
||||
@navigate-to-table="navigateToTable" />
|
||||
@@ -65,7 +62,7 @@
|
||||
<script setup>
|
||||
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { computed, ref } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
@@ -81,22 +78,11 @@
|
||||
const { refreshInviteMessageTableData } = useInviteStore();
|
||||
const { clearInviteImageUpload } = useGalleryStore();
|
||||
|
||||
const {
|
||||
isNotificationCenterOpen,
|
||||
friendNotifications,
|
||||
groupNotifications,
|
||||
otherNotifications,
|
||||
unseenNotifications
|
||||
} = storeToRefs(useNotificationStore());
|
||||
const { isNotificationCenterOpen, unseenFriendNotifications, unseenGroupNotifications, unseenOtherNotifications } =
|
||||
storeToRefs(useNotificationStore());
|
||||
|
||||
const activeTab = ref('friend');
|
||||
|
||||
const activeCount = computed(() => ({
|
||||
friend: friendNotifications.value.length,
|
||||
group: groupNotifications.value.length,
|
||||
other: otherNotifications.value.length
|
||||
}));
|
||||
|
||||
// Dialog state
|
||||
const sendInviteResponseDialog = ref({
|
||||
messageSlot: {},
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
v-for="n in activeNotifications"
|
||||
:key="n.id || n.type + n.created_at"
|
||||
:notification="n"
|
||||
:is-unseen="unseenIds.includes(n.id)"
|
||||
:is-unseen="true"
|
||||
@show-invite-response="$emit('show-invite-response', $event)"
|
||||
@show-invite-request-response="$emit('show-invite-request-response', $event)" />
|
||||
</div>
|
||||
@@ -14,22 +14,6 @@
|
||||
{{ t('side_panel.notification_center.no_new_notifications') }}
|
||||
</div>
|
||||
|
||||
<template v-if="expiredNotifications.length">
|
||||
<div class="flex items-center gap-2 px-4 py-2">
|
||||
<Separator class="flex-1" />
|
||||
<span class="shrink-0 text-[10px] text-muted-foreground uppercase tracking-wider">
|
||||
{{ t('side_panel.notification_center.past_notifications') }}
|
||||
</span>
|
||||
<Separator class="flex-1" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-0.5 px-2 pb-2">
|
||||
<NotificationItem
|
||||
v-for="n in expiredNotifications"
|
||||
:key="n.id || n.type + n.created_at"
|
||||
:notification="n"
|
||||
:is-unseen="false" />
|
||||
</div>
|
||||
</template>
|
||||
<div class="flex justify-center py-3">
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -45,7 +29,6 @@
|
||||
|
||||
<script setup>
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
@@ -54,8 +37,7 @@
|
||||
import NotificationItem from './NotificationItem.vue';
|
||||
|
||||
const props = defineProps({
|
||||
notifications: { type: Array, required: true },
|
||||
unseenIds: { type: Array, default: () => [] }
|
||||
notifications: { type: Array, required: true }
|
||||
});
|
||||
|
||||
defineEmits(['show-invite-response', 'show-invite-request-response', 'navigate-to-table']);
|
||||
@@ -71,15 +53,5 @@
|
||||
return Number.isFinite(ts) ? ts : 0;
|
||||
}
|
||||
|
||||
const sortedNotifications = computed(() => [...props.notifications].sort((a, b) => getTs(b) - getTs(a)));
|
||||
|
||||
const activeNotifications = computed(() =>
|
||||
sortedNotifications.value.filter((n) => getTs(n) > dayjs().subtract(1, 'week').valueOf())
|
||||
);
|
||||
|
||||
const MAX_EXPIRED = 20;
|
||||
|
||||
const expiredNotifications = computed(() =>
|
||||
sortedNotifications.value.filter((n) => getTs(n) <= dayjs().subtract(1, 'week').valueOf()).slice(0, MAX_EXPIRED)
|
||||
);
|
||||
const activeNotifications = computed(() => [...props.notifications].sort((a, b) => getTs(b) - getTs(a)));
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user