This commit is contained in:
2026-08-22 20:34:43 +02:00
parent 120b6cf4d5
commit da151c13ed
14 changed files with 366 additions and 21 deletions
+46 -3
View File
@@ -10,9 +10,11 @@ import {onReloadAll} from '@/plugins/events.ts'
import EmojiPicker from '@/components/EmojiPicker.vue'
import {useEmojiStore, type Emoji} from '@/stores/emoji.ts'
import {useAuthStore} from '@/stores/auth.ts'
import {useConversationStore} from '@/stores/conversation'
import {useRoute, useRouter} from 'vue-router'
const props = defineProps<{
serverId: string
serverId?: string
channelId: string
}>();
@@ -22,6 +24,9 @@ const serverStore = useServerStore();
const userStore = useUserStore();
const emojiStore = useEmojiStore();
const authStore = useAuthStore();
const conversationStore = useConversationStore()
const route = useRoute()
const router = useRouter()
const {renderMarkdown} = useMarkdown()
const messageContainer = ref<HTMLElement | null>(null);
@@ -35,6 +40,16 @@ const paginationLockScrollTop = ref(0);
const lastScrollTop = ref(0);
const markedMessageByChannel = new Map<string, string>();
const reactionPending = ref(new Set<string>());
const isConversation = computed(() => route.name === 'home-conversation')
const addParticipantDialog = ref(false)
const selectedParticipantIds = ref<string[]>([])
const addingParticipants = ref(false)
const currentConversation = computed(() => conversationStore.conversations.find(item => item.id === channelId.value))
const availableParticipants = computed(() => userStore.users.filter(user =>
user.id !== authStore.currentUser?.id &&
!currentConversation.value?.participants.some(participant => participant.id === user.id) &&
!selectedParticipantIds.value.includes(user.id),
))
const markCurrentChannelRead = async (targetChannelId: string) => {
if (messageStore.activeChannelId !== targetChannelId || !newestId.value) return;
@@ -47,12 +62,24 @@ const markCurrentChannelRead = async (targetChannelId: string) => {
if (messageStore.activeChannelId !== targetChannelId) return;
markedMessageByChannel.set(targetChannelId, messageId);
serverStore.applyChannelReadState(props.serverId, targetChannelId, readState.unread_count);
if (isConversation.value) conversationStore.applyReadState(targetChannelId, readState.unread_count)
else if (props.serverId) serverStore.applyChannelReadState(props.serverId, targetChannelId, readState.unread_count);
} catch (error) {
console.error('Erreur lors de la mise à jour de la lecture:', error);
}
};
const forkConversation = async () => {
if (!selectedParticipantIds.value.length) return
addingParticipants.value = true
try {
const conversation = await conversationStore.forkConversation(channelId.value, selectedParticipantIds.value)
addParticipantDialog.value = false
selectedParticipantIds.value = []
await router.push(`/conversation/${conversation.id}`)
} finally { addingParticipants.value = false }
}
const showRecentMessagesButton = computed(() =>
!loading.value && (hasMoreAfter.value || !isAtBottom.value),
);
@@ -247,7 +274,7 @@ watch(isAtBottom, async (atBottom) => {
watch(channelId, async (newChannelId) => {
if (newChannelId) {
await emojiStore.fetchEmojis(props.serverId);
if (props.serverId) await emojiStore.fetchEmojis(props.serverId);
await messageStore.fetchMessages(newChannelId);
await scrollToBottom();
await markCurrentChannelRead(newChannelId);
@@ -261,6 +288,12 @@ watch(() => props.serverId, (newServerId) => {
<template>
<v-container class="pa-0 fill-height d-flex flex-column channel-layout" fluid>
<v-sheet v-if="isConversation" class="px-4 py-2 d-flex align-center" border>
<v-icon class="mr-3" icon="mdi-account-multiple-outline" />
<span class="font-weight-medium">{{ currentConversation?.title ?? 'Discussion' }}</span>
<v-spacer />
<v-btn prepend-icon="mdi-account-plus" variant="text" @click="addParticipantDialog = true">Ajouter</v-btn>
</v-sheet>
<div
ref="messageContainer"
class="flex-grow-1 overflow-y-auto w-100 message-container"
@@ -372,6 +405,16 @@ watch(() => props.serverId, (newServerId) => {
</v-textarea>
</v-sheet>
</v-container>
<v-dialog v-model="addParticipantDialog" width="420">
<v-card>
<v-card-title>Nouvelle discussion de groupe</v-card-title>
<v-card-text>
<v-select v-model="selectedParticipantIds" :items="availableParticipants" item-title="username" item-value="id" label="Ajouter des participants" multiple chips closable-chips />
</v-card-text>
<v-card-actions><v-spacer /><v-btn @click="addParticipantDialog = false">Annuler</v-btn><v-btn color="primary" :loading="addingParticipants" :disabled="!selectedParticipantIds.length" @click="forkConversation">Créer</v-btn></v-card-actions>
</v-card>
</v-dialog>
</template>
<style scoped>