init
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user