diff --git a/frontend/src/pages/server/channel/index.vue b/frontend/src/pages/server/channel/index.vue index f4644f7..5c5e0e8 100644 --- a/frontend/src/pages/server/channel/index.vue +++ b/frontend/src/pages/server/channel/index.vue @@ -17,7 +17,7 @@ const userStore = useUserStore(); const {renderMarkdown} = useMarkdown() const messageContainer = ref(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) => {