2020-01-29 20:37:25 +01:00
|
|
|
<template>
|
2024-04-26 16:39:58 +02:00
|
|
|
<MkPagination
|
|
|
|
ref="pagingComponent"
|
|
|
|
:pagination="pagination"
|
|
|
|
:folder="convertNotification"
|
|
|
|
>
|
2023-04-08 02:01:42 +02:00
|
|
|
<template #empty>
|
|
|
|
<div class="_fullinfo">
|
|
|
|
<img
|
2023-09-26 05:57:14 +02:00
|
|
|
src="/static-assets/badges/info.webp"
|
2023-04-08 02:01:42 +02:00
|
|
|
class="_ghost"
|
|
|
|
alt="Info"
|
|
|
|
/>
|
|
|
|
<div>{{ i18n.ts.noNotifications }}</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
2022-01-09 13:35:35 +01:00
|
|
|
|
2024-04-26 16:39:58 +02:00
|
|
|
<template #default="{ foldedItems: notifications }">
|
2023-04-08 02:01:42 +02:00
|
|
|
<XList
|
2024-04-26 16:39:58 +02:00
|
|
|
:items="notifications"
|
2023-04-08 02:01:42 +02:00
|
|
|
v-slot="{ item: notification }"
|
|
|
|
class="elsfgstc"
|
|
|
|
:no-gap="true"
|
|
|
|
>
|
2024-04-24 15:33:56 +02:00
|
|
|
<XNotificationFolded
|
|
|
|
v-if="isFoldedNotification(notification)"
|
|
|
|
:key="'nf-' + notification.id"
|
|
|
|
:notification="notification"
|
|
|
|
:with-time="true"
|
|
|
|
:full="true"
|
|
|
|
class="_panel notification"
|
|
|
|
/>
|
2023-04-08 02:01:42 +02:00
|
|
|
<XNote
|
2024-04-24 15:33:56 +02:00
|
|
|
v-else-if="isNoteNotification(notification)"
|
2024-04-03 17:10:49 +02:00
|
|
|
:key="'nn-' + notification.id"
|
2023-04-08 02:01:42 +02:00
|
|
|
:note="notification.note"
|
2023-09-02 01:27:33 +02:00
|
|
|
:collapsed-reply="
|
2023-06-23 01:46:18 +02:00
|
|
|
notification.type === 'reply' ||
|
|
|
|
(notification.type === 'mention' &&
|
|
|
|
notification.note.replyId != null)
|
|
|
|
"
|
2023-04-08 02:01:42 +02:00
|
|
|
/>
|
|
|
|
<XNotification
|
|
|
|
v-else
|
2024-04-03 17:10:49 +02:00
|
|
|
:key="'n-' + notification.id"
|
2023-04-08 02:01:42 +02:00
|
|
|
:notification="notification"
|
|
|
|
:with-time="true"
|
|
|
|
:full="true"
|
|
|
|
class="_panel notification"
|
|
|
|
/>
|
|
|
|
</XList>
|
|
|
|
</template>
|
|
|
|
</MkPagination>
|
2020-01-29 20:37:25 +01:00
|
|
|
</template>
|
|
|
|
|
2022-01-09 13:35:35 +01:00
|
|
|
<script lang="ts" setup>
|
2023-09-02 01:27:33 +02:00
|
|
|
import { computed, onMounted, onUnmounted, ref } from "vue";
|
2024-04-03 18:07:44 +02:00
|
|
|
import type { StreamTypes, entities, notificationTypes } from "firefish-js";
|
2024-04-12 10:37:32 +02:00
|
|
|
import MkPagination, {
|
|
|
|
type MkPaginationType,
|
|
|
|
} from "@/components/MkPagination.vue";
|
2023-04-08 02:01:42 +02:00
|
|
|
import XNotification from "@/components/MkNotification.vue";
|
2024-04-24 15:33:56 +02:00
|
|
|
import XNotificationFolded from "@/components/MkNotificationFolded.vue";
|
2023-04-08 02:01:42 +02:00
|
|
|
import XList from "@/components/MkDateSeparatedList.vue";
|
|
|
|
import XNote from "@/components/MkNote.vue";
|
2024-02-29 14:21:19 +01:00
|
|
|
import { useStream } from "@/stream";
|
2024-03-07 03:06:45 +01:00
|
|
|
import { me } from "@/me";
|
2023-04-08 02:01:42 +02:00
|
|
|
import { i18n } from "@/i18n";
|
2024-04-24 15:33:56 +02:00
|
|
|
import type { NotificationFolded } from "@/types/notification";
|
|
|
|
import { foldNotifications } from "@/scripts/fold";
|
|
|
|
import { defaultStore } from "@/store";
|
2022-01-09 13:35:35 +01:00
|
|
|
|
|
|
|
const props = defineProps<{
|
2023-04-08 02:01:42 +02:00
|
|
|
includeTypes?: (typeof notificationTypes)[number][];
|
2022-01-09 13:35:35 +01:00
|
|
|
unreadOnly?: boolean;
|
|
|
|
}>();
|
|
|
|
|
2024-02-29 14:21:19 +01:00
|
|
|
const stream = useStream();
|
|
|
|
|
2024-04-12 10:37:32 +02:00
|
|
|
const pagingComponent = ref<MkPaginationType<"i/notifications"> | null>(null);
|
2022-01-09 13:35:35 +01:00
|
|
|
|
2024-04-25 02:55:18 +02:00
|
|
|
const shouldFold = defaultStore.state.foldNotification;
|
|
|
|
|
2024-04-24 16:21:49 +02:00
|
|
|
const FETCH_LIMIT = 90;
|
2024-04-24 15:33:56 +02:00
|
|
|
|
2024-04-25 02:55:18 +02:00
|
|
|
const pagination = Object.assign(
|
|
|
|
{
|
|
|
|
endpoint: "i/notifications" as const,
|
|
|
|
params: computed(() => ({
|
|
|
|
includeTypes: props.includeTypes ?? undefined,
|
|
|
|
excludeTypes: props.includeTypes
|
|
|
|
? undefined
|
|
|
|
: me?.mutingNotificationTypes,
|
|
|
|
unreadOnly: props.unreadOnly,
|
|
|
|
})),
|
|
|
|
},
|
|
|
|
shouldFold
|
|
|
|
? {
|
2024-04-26 16:39:58 +02:00
|
|
|
limit: 50,
|
2024-04-25 02:55:18 +02:00
|
|
|
secondFetchLimit: FETCH_LIMIT,
|
|
|
|
}
|
|
|
|
: {
|
|
|
|
limit: 30,
|
|
|
|
},
|
|
|
|
);
|
2022-01-09 13:35:35 +01:00
|
|
|
|
2024-04-03 17:10:49 +02:00
|
|
|
function isNoteNotification(
|
|
|
|
n: entities.Notification,
|
|
|
|
): n is
|
|
|
|
| entities.ReplyNotification
|
|
|
|
| entities.QuoteNotification
|
|
|
|
| entities.MentionNotification {
|
|
|
|
return n.type === "reply" || n.type === "quote" || n.type === "mention";
|
|
|
|
}
|
2024-04-24 15:33:56 +02:00
|
|
|
function isFoldedNotification(
|
|
|
|
n: NotificationFolded | entities.Notification,
|
|
|
|
): n is NotificationFolded {
|
|
|
|
return "folded" in n;
|
|
|
|
}
|
2024-04-03 17:10:49 +02:00
|
|
|
|
|
|
|
const onNotification = (notification: entities.Notification) => {
|
2023-04-08 02:01:42 +02:00
|
|
|
const isMuted = props.includeTypes
|
|
|
|
? !props.includeTypes.includes(notification.type)
|
2024-04-03 17:10:49 +02:00
|
|
|
: me?.mutingNotificationTypes.includes(notification.type);
|
2023-04-08 02:01:42 +02:00
|
|
|
if (isMuted || document.visibilityState === "visible") {
|
|
|
|
stream.send("readNotification", {
|
2022-06-05 05:26:36 +02:00
|
|
|
id: notification.id,
|
2022-01-09 13:35:35 +01:00
|
|
|
});
|
|
|
|
}
|
2020-07-29 16:03:08 +02:00
|
|
|
|
2022-01-09 13:35:35 +01:00
|
|
|
if (!isMuted) {
|
2024-02-29 14:21:19 +01:00
|
|
|
pagingComponent.value?.prepend({
|
2022-01-09 13:35:35 +01:00
|
|
|
...notification,
|
2023-04-08 02:01:42 +02:00
|
|
|
isRead: document.visibilityState === "visible",
|
2022-01-09 13:35:35 +01:00
|
|
|
});
|
2020-01-29 20:37:25 +01:00
|
|
|
}
|
2022-01-09 13:35:35 +01:00
|
|
|
};
|
|
|
|
|
2024-04-03 18:07:44 +02:00
|
|
|
let connection: StreamTypes.ChannelOf<"main"> | undefined;
|
2022-06-25 20:12:58 +02:00
|
|
|
|
2024-04-26 16:39:58 +02:00
|
|
|
function convertNotification(ns: entities.Notification[]) {
|
2024-04-25 02:55:18 +02:00
|
|
|
if (shouldFold) {
|
2024-04-26 16:39:58 +02:00
|
|
|
return foldNotifications(ns);
|
2024-04-24 15:33:56 +02:00
|
|
|
} else {
|
2024-04-26 16:39:58 +02:00
|
|
|
return ns;
|
2024-04-24 15:33:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-09 13:35:35 +01:00
|
|
|
onMounted(() => {
|
2023-04-08 02:01:42 +02:00
|
|
|
connection = stream.useChannel("main");
|
|
|
|
connection.on("notification", onNotification);
|
|
|
|
connection.on("readAllNotifications", () => {
|
2022-04-30 14:52:07 +02:00
|
|
|
if (pagingComponent.value) {
|
|
|
|
for (const item of pagingComponent.value.queue) {
|
|
|
|
item.isRead = true;
|
|
|
|
}
|
|
|
|
for (const item of pagingComponent.value.items) {
|
|
|
|
item.isRead = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2023-04-08 02:01:42 +02:00
|
|
|
connection.on("readNotifications", (notificationIds) => {
|
2022-04-30 14:52:07 +02:00
|
|
|
if (pagingComponent.value) {
|
|
|
|
for (let i = 0; i < pagingComponent.value.queue.length; i++) {
|
2024-03-28 17:26:52 +01:00
|
|
|
if (notificationIds.includes(pagingComponent.value.queue[i].id)) {
|
2022-04-30 14:52:07 +02:00
|
|
|
pagingComponent.value.queue[i].isRead = true;
|
|
|
|
}
|
|
|
|
}
|
2024-03-28 17:26:52 +01:00
|
|
|
for (let i = 0; i < (pagingComponent.value.items || []).length; i++) {
|
|
|
|
if (notificationIds.includes(pagingComponent.value.items[i].id)) {
|
2022-04-30 14:52:07 +02:00
|
|
|
pagingComponent.value.items[i].isRead = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2022-06-25 20:12:58 +02:00
|
|
|
});
|
2022-04-30 14:52:07 +02:00
|
|
|
|
2022-06-25 20:12:58 +02:00
|
|
|
onUnmounted(() => {
|
|
|
|
if (connection) connection.dispose();
|
2020-01-29 20:37:25 +01:00
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
2021-08-21 10:40:15 +02:00
|
|
|
.elsfgstc {
|
|
|
|
background: var(--panel);
|
2023-03-26 05:33:44 +02:00
|
|
|
border-radius: var(--radius);
|
2021-08-21 10:40:15 +02:00
|
|
|
}
|
2020-01-29 20:37:25 +01:00
|
|
|
</style>
|