enh: infinite scroll messages

This commit is contained in:
Timothy J. Baek 2024-09-24 00:27:22 +02:00
parent 93cb2be35d
commit d7b64ff447
2 changed files with 49 additions and 6 deletions

View File

@ -9,6 +9,8 @@
import Placeholder from './Messages/Placeholder.svelte'; import Placeholder from './Messages/Placeholder.svelte';
import Message from './Messages/Message.svelte'; import Message from './Messages/Message.svelte';
import Loader from '../common/Loader.svelte';
import Spinner from '../common/Spinner.svelte';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
@ -33,12 +35,21 @@
export let bottomPadding = false; export let bottomPadding = false;
export let autoScroll; export let autoScroll;
let messagesCount = 20;
let messagesLoading = false;
const loadMoreMessages = async () => {
messagesLoading = true;
messagesCount += 20;
messagesLoading = false;
};
$: if (history.currentId) { $: if (history.currentId) {
let _messages = []; let _messages = [];
let message = history.messages[history.currentId]; let message = history.messages[history.currentId];
while (message) { while (message && _messages.length <= messagesCount) {
_messages.unshift({ ...message }); _messages.push({ ...message });
message = message.parentId !== null ? history.messages[message.parentId] : null; message = message.parentId !== null ? history.messages[message.parentId] : null;
} }
@ -330,7 +341,7 @@
{:else} {:else}
<div class="w-full pt-2"> <div class="w-full pt-2">
{#key chatId} {#key chatId}
<div class="w-full"> <div class="w-full flex flex-col-reverse">
{#each messages as message, messageIdx (message.id)} {#each messages as message, messageIdx (message.id)}
<Message <Message
{chatId} {chatId}
@ -361,6 +372,22 @@
}} }}
/> />
{/each} {/each}
{#if messages.at(-1).parentId !== null}
<Loader
on:visible={(e) => {
console.log('visible');
if (!messagesLoading) {
loadMoreMessages();
}
}}
>
<div class="w-full flex justify-center py-1 text-xs animate-pulse items-center gap-2">
<Spinner className=" size-4" />
<div class=" ">Loading...</div>
</div>
</Loader>
{/if}
</div> </div>
<div class="pb-12" /> <div class="pb-12" />
{#if bottomPadding} {#if bottomPadding}

View File

@ -1,16 +1,24 @@
<script lang="ts"> <script lang="ts">
import { createEventDispatcher, onMount } from 'svelte'; import { createEventDispatcher, onDestroy, onMount } from 'svelte';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
let loaderElement: HTMLElement; let loaderElement: HTMLElement;
let observer;
let intervalId;
onMount(() => { onMount(() => {
const observer = new IntersectionObserver( observer = new IntersectionObserver(
(entries, observer) => { (entries, observer) => {
entries.forEach((entry) => { entries.forEach((entry) => {
if (entry.isIntersecting) { if (entry.isIntersecting) {
intervalId = setInterval(() => {
dispatch('visible'); dispatch('visible');
}, 100);
// dispatch('visible');
// observer.unobserve(loaderElement); // Stop observing until content is loaded // observer.unobserve(loaderElement); // Stop observing until content is loaded
} else {
clearInterval(intervalId);
} }
}); });
}, },
@ -23,6 +31,14 @@
observer.observe(loaderElement); observer.observe(loaderElement);
}); });
onDestroy(() => {
observer.disconnect();
if (intervalId) {
clearInterval(intervalId);
}
});
</script> </script>
<div bind:this={loaderElement}> <div bind:this={loaderElement}>