142 lines
4.3 KiB
Vue
142 lines
4.3 KiB
Vue
<template>
|
|
<MagPagination ref="pagingComponent" :pagination="pagination">
|
|
<template #empty>
|
|
<div class="_fullinfo">
|
|
<img
|
|
src="/static-assets/badges/info.png"
|
|
class="_ghost"
|
|
alt="Info"
|
|
/>
|
|
<div>{{ i18n.ts.noNotifications }}</div>
|
|
</div>
|
|
</template>
|
|
|
|
<template #items="{ items: notifications }">
|
|
<XList
|
|
v-slot="{ item: notification }"
|
|
class="elsfgstc"
|
|
:items="notifications"
|
|
:no-gap="true"
|
|
>
|
|
<XNote
|
|
v-if="
|
|
notification.note &&
|
|
(notification.type === 'Quote' ||
|
|
notification.type === 'Mention' ||
|
|
notification.type === 'Reply')
|
|
"
|
|
:key="notification.id"
|
|
:note="notification.note"
|
|
:collapsedReply="!!notification.note.parent_note"
|
|
/>
|
|
<XNotification
|
|
v-else
|
|
:key="notification.id"
|
|
:notification="notification"
|
|
:with-time="true"
|
|
:full="true"
|
|
class="_panel notification"
|
|
/>
|
|
</XList>
|
|
</template>
|
|
</MagPagination>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { onMounted, onUnmounted, ref } from "vue";
|
|
import XNotification from "@/components/MkNotification.vue";
|
|
import XList from "@/components/MkDateSeparatedList.vue";
|
|
import XNote from "@/components/MagNote.vue";
|
|
import { stream } from "@/stream";
|
|
import { $i } from "@/account";
|
|
import MagPagination, { Paging } from "@/components/MagPagination.vue";
|
|
import { endpoints, types } from "magnetar-common";
|
|
import { i18n } from "@/i18n";
|
|
|
|
const props = defineProps<{
|
|
includeTypes?: types.NotificationType[];
|
|
unreadOnly?: boolean;
|
|
}>();
|
|
|
|
const pagingComponent = ref<InstanceType<typeof MagPagination>>();
|
|
|
|
const pagination: Paging = {
|
|
endpoint: endpoints.GetNotifications,
|
|
params: {
|
|
include_types: props.includeTypes ?? undefined,
|
|
exclude_types: props.includeTypes
|
|
? undefined
|
|
: $i?.mutingNotificationTypes,
|
|
unread_only: props.unreadOnly,
|
|
} as types.NotificationsReq,
|
|
};
|
|
|
|
const onNotification = (notification) => {
|
|
const isMuted = props.includeTypes
|
|
? !props.includeTypes.includes(notification.type)
|
|
: $i?.mutingNotificationTypes?.includes(notification.type);
|
|
if (isMuted || document.visibilityState === "visible") {
|
|
stream.send("readNotification", {
|
|
id: notification.id,
|
|
});
|
|
}
|
|
|
|
if (!isMuted) {
|
|
pagingComponent.value.prepend({
|
|
...notification,
|
|
isRead: document.visibilityState === "visible",
|
|
});
|
|
}
|
|
};
|
|
|
|
let connection;
|
|
|
|
onMounted(() => {
|
|
connection = stream.useChannel("main");
|
|
connection.on("notification", onNotification);
|
|
connection.on("readAllNotifications", () => {
|
|
if (pagingComponent.value) {
|
|
for (const item of pagingComponent.value.queue) {
|
|
item.isRead = true;
|
|
}
|
|
for (const item of pagingComponent.value.items) {
|
|
item.isRead = true;
|
|
}
|
|
}
|
|
});
|
|
connection.on("readNotifications", (notificationIds) => {
|
|
if (pagingComponent.value) {
|
|
for (let i = 0; i < pagingComponent.value.queue.length; i++) {
|
|
if (
|
|
notificationIds.includes(pagingComponent.value.queue[i].id)
|
|
) {
|
|
pagingComponent.value.queue[i].isRead = true;
|
|
}
|
|
}
|
|
for (
|
|
let i = 0;
|
|
i < (pagingComponent.value.items || []).length;
|
|
i++
|
|
) {
|
|
if (
|
|
notificationIds.includes(pagingComponent.value.items[i].id)
|
|
) {
|
|
pagingComponent.value.items[i].isRead = true;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
onUnmounted(() => {
|
|
if (connection) connection.dispose();
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.elsfgstc {
|
|
background: var(--panel);
|
|
border-radius: var(--radius);
|
|
}
|
|
</style>
|