init
This commit is contained in:
@@ -7,6 +7,9 @@ import {useServerStore} from '@/stores/server';
|
||||
import {useUserStore} from "@/stores/user.ts";
|
||||
import {useMarkdown} from '@/composables/useMarkdown'
|
||||
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'
|
||||
|
||||
const props = defineProps<{
|
||||
serverId: string
|
||||
@@ -17,6 +20,8 @@ const channelId = computed(() => props.channelId);
|
||||
const messageStore = useMessageStore();
|
||||
const serverStore = useServerStore();
|
||||
const userStore = useUserStore();
|
||||
const emojiStore = useEmojiStore();
|
||||
const authStore = useAuthStore();
|
||||
const {renderMarkdown} = useMarkdown()
|
||||
|
||||
const messageContainer = ref<HTMLElement | null>(null);
|
||||
@@ -29,6 +34,7 @@ const paginationLock = ref<'before' | 'after' | null>(null);
|
||||
const paginationLockScrollTop = ref(0);
|
||||
const lastScrollTop = ref(0);
|
||||
const markedMessageByChannel = new Map<string, string>();
|
||||
const reactionPending = ref(new Set<string>());
|
||||
|
||||
const markCurrentChannelRead = async (targetChannelId: string) => {
|
||||
if (messageStore.activeChannelId !== targetChannelId || !newestId.value) return;
|
||||
@@ -180,6 +186,34 @@ const sendMessage = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const reactionKey = (messageId: string, emojiId: string, skinTone: number | null) =>
|
||||
`${messageId}:${emojiId}:${skinTone ?? 0}`;
|
||||
|
||||
const toggleReaction = async (messageId: string, emojiId: string, skinTone: number | null, active: boolean) => {
|
||||
const key = reactionKey(messageId, emojiId, skinTone);
|
||||
if (reactionPending.value.has(key)) return;
|
||||
reactionPending.value.add(key);
|
||||
try {
|
||||
if (active) await messageStore.removeReaction(messageId, emojiId, skinTone);
|
||||
else await messageStore.addReaction(messageId, emojiId);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la modification de la réaction:', error);
|
||||
} finally {
|
||||
reactionPending.value.delete(key);
|
||||
}
|
||||
};
|
||||
|
||||
const addReaction = (messageId: string, emoji: Emoji) =>
|
||||
toggleReaction(messageId, emoji.id, null, false);
|
||||
|
||||
const emojiText = (emojiId: string, sequence: string | null) => {
|
||||
const emoji = emojiStore.emojisById[emojiId];
|
||||
if (emoji?.emoji_type === 'custom') return null;
|
||||
return sequence ?? emoji?.unicode_sequence ?? '';
|
||||
};
|
||||
|
||||
const reactionIsActive = (userIds: string[]) => Boolean(authStore.currentUser?.id && userIds.includes(authStore.currentUser.id));
|
||||
|
||||
const returnToRecentMessages = async () => {
|
||||
paginationLock.value = null;
|
||||
await messageStore.fetchMessages(channelId.value);
|
||||
@@ -213,11 +247,16 @@ watch(isAtBottom, async (atBottom) => {
|
||||
|
||||
watch(channelId, async (newChannelId) => {
|
||||
if (newChannelId) {
|
||||
await emojiStore.fetchEmojis(props.serverId);
|
||||
await messageStore.fetchMessages(newChannelId);
|
||||
await scrollToBottom();
|
||||
await markCurrentChannelRead(newChannelId);
|
||||
}
|
||||
}, {immediate: true})
|
||||
|
||||
watch(() => props.serverId, (newServerId) => {
|
||||
if (newServerId) void emojiStore.fetchEmojis(newServerId);
|
||||
}, {immediate: true});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -257,6 +296,29 @@ watch(channelId, async (newChannelId) => {
|
||||
<div class="text-body-1 text-high-emphasis opacity-100 mt-1">
|
||||
<div class="markdown-content" v-html="renderMarkdown(msg.content)"></div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap align-center ga-1 mt-2">
|
||||
<v-chip
|
||||
v-for="reaction in msg.reactions"
|
||||
:key="`${reaction.emoji_id}:${reaction.skin_tone ?? 0}`"
|
||||
:color="reactionIsActive(reaction.user_ids) ? 'primary' : undefined"
|
||||
:variant="reactionIsActive(reaction.user_ids) ? 'flat' : 'outlined'"
|
||||
class="reaction-chip"
|
||||
size="small"
|
||||
@click="toggleReaction(msg.id, reaction.emoji_id, reaction.skin_tone, reactionIsActive(reaction.user_ids))"
|
||||
>
|
||||
<img v-if="emojiStore.emojisById[reaction.emoji_id]?.emoji_type === 'custom' && reaction.asset_url" :alt="reaction.name" :src="reaction.asset_url" />
|
||||
<span v-else>{{ emojiText(reaction.emoji_id, reaction.unicode_sequence) }}</span>
|
||||
<span class="ml-1">{{ reaction.count }}</span>
|
||||
</v-chip>
|
||||
|
||||
<v-menu :close-on-content-click="false">
|
||||
<template #activator="{props: menuProps}">
|
||||
<v-btn v-bind="menuProps" density="compact" icon="mdi-plus" size="small" variant="text" />
|
||||
</template>
|
||||
<EmojiPicker :emojis="emojiStore.emojis" @select="(emoji) => addReaction(msg.id, emoji)" />
|
||||
</v-menu>
|
||||
</div>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
@@ -300,7 +362,12 @@ watch(channelId, async (newChannelId) => {
|
||||
<template v-slot:append-inner>
|
||||
<v-btn color="grey-darken-1" density="compact" icon="mdi-gift" variant="text"></v-btn>
|
||||
<v-btn color="grey-darken-1" density="compact" icon="mdi-sticker-emoji" variant="text"></v-btn>
|
||||
<v-btn color="grey-darken-1" density="compact" icon="mdi-emoticon" variant="text"></v-btn>
|
||||
<v-menu :close-on-content-click="false">
|
||||
<template #activator="{props: menuProps}">
|
||||
<v-btn v-bind="menuProps" color="grey-darken-1" density="compact" icon="mdi-emoticon" variant="text" />
|
||||
</template>
|
||||
<EmojiPicker :emojis="emojiStore.emojis" @select="(emoji) => { newMessage += emoji.emoji_type === 'custom' ? `:${emoji.name}:` : (emoji.unicode_sequence ?? '') }" />
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-textarea>
|
||||
</v-sheet>
|
||||
@@ -342,4 +409,10 @@ watch(channelId, async (newChannelId) => {
|
||||
margin: 8px 0;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.reaction-chip img {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
object-fit: contain;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user