This commit is contained in:
2026-08-08 14:57:04 +02:00
parent 0d8c86af16
commit d1f9234457
5 changed files with 56 additions and 38 deletions
+41 -2
View File
@@ -17,7 +17,7 @@ const userStore = useUserStore();
const {renderMarkdown} = useMarkdown()
const messageContainer = ref<HTMLElement | null>(null);
const {messages, loading, loadingBefore, loadingAfter} = storeToRefs(messageStore);
const {messages, loading, loadingBefore, loadingAfter, hasMoreAfter, isAtBottom} = storeToRefs(messageStore);
const newMessage = ref('');
const SCROLL_LOAD_THRESHOLD = 120;
@@ -26,6 +26,10 @@ const paginationLock = ref<'before' | 'after' | null>(null);
const paginationLockScrollTop = ref(0);
const lastScrollTop = ref(0);
const showRecentMessagesButton = computed(() =>
!loading.value && (hasMoreAfter.value || !isAtBottom.value),
);
interface ScrollAnchor {
id: string;
top: number;
@@ -36,6 +40,8 @@ const scrollToBottom = async () => {
if (messageContainer.value) {
messageContainer.value.scrollTop = messageContainer.value.scrollHeight;
messageStore.setAtBottom(true);
paginationLock.value = null;
lastScrollTop.value = messageContainer.value.scrollTop;
}
};
@@ -153,6 +159,12 @@ const sendMessage = async () => {
}
};
const returnToRecentMessages = async () => {
paginationLock.value = null;
await messageStore.fetchMessages(channelId.value);
await scrollToBottom();
};
// Only explicit initial loads and realtime messages received while at the
// bottom request an automatic scroll. Pagination restores its own anchor.
watch(messages, async () => {
@@ -169,7 +181,7 @@ watch(channelId, async (newChannelId) => {
</script>
<template>
<v-container class="pa-0 fill-height d-flex flex-column" fluid>
<v-container class="pa-0 fill-height d-flex flex-column channel-layout" fluid>
<div
ref="messageContainer"
class="flex-grow-1 overflow-y-auto w-100 message-container"
@@ -211,6 +223,22 @@ watch(channelId, async (newChannelId) => {
<v-progress-linear v-if="loadingAfter" color="primary" indeterminate />
</div>
<div v-if="showRecentMessagesButton" class="recent-messages-button">
<v-tooltip location="top" text="Revenir aux messages récents">
<template #activator="{ props: tooltipProps }">
<v-btn
v-bind="tooltipProps"
aria-label="Revenir aux messages récents"
color="primary"
elevation="4"
icon="mdi-arrow-down-bold"
:loading="loading"
@click="returnToRecentMessages"
/>
</template>
</v-tooltip>
</div>
<v-sheet class="pa-4 flex-shrink-0" width="100%">
<v-textarea
v-model="newMessage"
@@ -244,6 +272,17 @@ watch(channelId, async (newChannelId) => {
height: 0;
}
.channel-layout {
position: relative;
}
.recent-messages-button {
position: absolute;
right: 16px;
bottom: 92px;
z-index: 2;
}
.markdown-content :deep(p) {
margin-bottom: 0;
}