This commit is contained in:
2026-08-09 10:30:54 +02:00
parent 93800e8460
commit 20beea24d5
11 changed files with 325 additions and 61 deletions
+9 -2
View File
@@ -1,7 +1,14 @@
<template>
<router-view/>
<router-view />
<v-snackbar v-model="notification.visible" :timeout="5000" location="bottom right">
<div class="font-weight-bold">{{ notification.title }}</div>
<div>{{ notification.message }}</div>
</v-snackbar>
</template>
<script lang="ts" setup>
//
import {useNotificationStore} from "@/stores/notification.ts";
const notification = useNotificationStore();
</script>
+35 -3
View File
@@ -1,6 +1,9 @@
import {defineStore} from "pinia";
import {useApi} from "@/composables/useApi.ts";
import {onGatewayEvent} from "@/plugins/events.ts";
import {useServerStore} from "@/stores/server.ts";
import {useAuthStore} from "@/stores/auth.ts";
import {useNotificationStore} from "@/stores/notification.ts";
// Change this value to adjust the maximum number of messages kept in the DOM.
// Directional loads automatically use half of this window.
@@ -9,6 +12,7 @@ export const MESSAGE_SHIFT_SIZE = Math.max(1, Math.floor(MESSAGE_WINDOW_SIZE / 2
export interface Message {
id: string;
server_id: string | null;
channel_id: string;
user_id: string;
content: string;
@@ -85,6 +89,7 @@ export const useMessageStore = defineStore("message", {
isAtBottom: true,
scrollToBottomRequested: false,
requestVersion: 0,
seenRealtimeMessageIds: new Set<string>(),
}),
actions: {
@@ -242,8 +247,29 @@ export const useMessageStore = defineStore("message", {
return await response.json() as ReadStateResponse;
},
addRealtimeMessage(message: Message) {
if (message.channel_id !== this.activeChannelId) return;
addRealtimeMessage(message: Message, fromGateway = false) {
const serverStore = useServerStore();
const authStore = useAuthStore();
const notificationStore = useNotificationStore();
if (fromGateway) {
if (this.seenRealtimeMessageIds.has(message.id)) return;
this.seenRealtimeMessageIds.add(message.id);
if (this.seenRealtimeMessageIds.size > 1000) {
const oldest = this.seenRealtimeMessageIds.values().next().value;
if (oldest) this.seenRealtimeMessageIds.delete(oldest);
}
}
const isOwnMessage = authStore.currentUser?.id === message.user_id;
const isActiveChannel = message.channel_id === this.activeChannelId;
if (!isActiveChannel) {
if (fromGateway && !isOwnMessage) {
serverStore.applyIncomingMessage(message.server_id, message.channel_id);
notificationStore.show("Nouveau message", "Un nouveau message est arrivé dans un autre canal.");
}
return;
}
const existingIndex = this.messages.findIndex(current => current.id === message.id);
if (existingIndex !== -1) {
@@ -253,6 +279,9 @@ export const useMessageStore = defineStore("message", {
if (!this.isAtBottom && this.newestId && message.id > this.newestId) {
this.hasMoreAfter = true;
if (fromGateway && !isOwnMessage) {
serverStore.applyIncomingMessage(message.server_id, message.channel_id);
}
return;
}
@@ -261,6 +290,8 @@ export const useMessageStore = defineStore("message", {
this.hasMoreAfter = false;
if (this.isAtBottom) {
this.scrollToBottomRequested = true;
} else if (fromGateway && !isOwnMessage) {
serverStore.applyIncomingMessage(message.server_id, message.channel_id);
}
},
@@ -300,6 +331,7 @@ export const useMessageStore = defineStore("message", {
this.loadingAfter = false;
this.isAtBottom = true;
this.scrollToBottomRequested = false;
this.seenRealtimeMessageIds.clear();
},
},
});
@@ -309,7 +341,7 @@ onGatewayEvent("Message", (payload) => {
switch (payload.action) {
case "add":
store.addRealtimeMessage(payload.content as Message);
store.addRealtimeMessage(payload.content as Message, true);
break;
case "update":
store.updateMessage(payload.content as Message);
+19
View File
@@ -0,0 +1,19 @@
import {defineStore} from "pinia";
export const useNotificationStore = defineStore("notification", {
state: () => ({
visible: false,
title: "",
message: "",
}),
actions: {
show(title: string, message: string) {
this.title = title;
this.message = message;
this.visible = true;
},
hide() {
this.visible = false;
},
},
});
+15
View File
@@ -131,6 +131,21 @@ export const useServerStore = defineStore("server", {
);
}
},
applyIncomingMessage(serverId: string | null, channelId: string) {
if (!serverId) return;
for (const item of this.currentTree) {
const channels = "Category" in item ? item.Category[1] : "Channel" in item ? [item.Channel] : [];
const channel = channels.find((candidate: { id: string }) => candidate.id === channelId);
if (channel) {
channel.unread_count = (channel.unread_count ?? 0) + 1;
break;
}
}
const server = this.servers.find(candidate => candidate.id === serverId);
if (server) server.unread_count = (server.unread_count ?? 0) + 1;
},
reset() {
this.servers = [];
this.loading = false;