diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2024-12-02 22:51:10 -0500 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2024-12-02 22:51:10 -0500 |
| commit | 4e3ad13aca163e733724b205c250bdb67cc56c29 (patch) | |
| tree | 216842b15b55181a495af1643102718bbe041a38 /ui/routes/(app)/ch | |
| parent | 5ce6c9f6277c43caf7413cce255af7bdc947e74c (diff) | |
| parent | 0276d22c9ed49b035129cac99f68ada7fc1015d2 (diff) | |
Merge remote-tracking branch 'origin/wip/unreadish'
Diffstat (limited to 'ui/routes/(app)/ch')
| -rw-r--r-- | ui/routes/(app)/ch/[channel]/+page.svelte | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/ui/routes/(app)/ch/[channel]/+page.svelte b/ui/routes/(app)/ch/[channel]/+page.svelte index 0961665..7d5b8cf 100644 --- a/ui/routes/(app)/ch/[channel]/+page.svelte +++ b/ui/routes/(app)/ch/[channel]/+page.svelte @@ -1,14 +1,70 @@ <script> + import { DateTime } from 'luxon'; import { page } from '$app/stores'; import ActiveChannel from '$lib/components/ActiveChannel.svelte'; import MessageInput from '$lib/components/MessageInput.svelte'; - import { messages } from '$lib/store'; + import { channelsList, messages } from '$lib/store'; let channel = $derived($page.params.channel); let messageRuns = $derived($messages.inChannel(channel)); + let activeChannel; + + function inView(parentElement, element) { + const parRect = parentElement.getBoundingClientRect(); + const parentTop = parRect.top; + const parentBottom = parRect.bottom; + + const elRect = element.getBoundingClientRect(); + const elementTop = elRect.top; + const elementBottom = elRect.bottom; + + return ((parentTop < elementTop) && (parentBottom > elementBottom)); + } + + function getLastVisibleMessage() { + const parentElement = activeChannel; + const childElements = parentElement.getElementsByClassName('message'); + const lastInView = Array.from(childElements).reverse().find((el) => { + return inView(parentElement, el); + }); + return lastInView; + } + + function setLastRead() { + const channelObject = $channelsList.getChannel(channel); + const lastInView = getLastVisibleMessage(); + if (!channelObject || !lastInView) { + return; + } + const at = DateTime.fromISO(lastInView.dataset.at); + // Do it this way, rather than with Math.max tricks, to avoid assignment + // when we don't need it, to minimize reactive changes: + if (at > channelObject.lastReadAt) { + channelObject.lastReadAt = at; + } + } + + $effect(() => { + const _ = $messages.inChannel(channel); + setLastRead(); + }); + + function handleKeydown(event) { + if (event.key === 'Escape') { + setLastRead(); // TODO: pass in "last message DT"? + } + } + + let lastReadCallback = null; + function handleScroll() { + clearTimeout(lastReadCallback); // Fine if lastReadCallback is null still. + lastReadCallback = setTimeout(setLastRead, 2 * 1000); + } </script> -<div class="active-channel"> +<svelte:window onkeydown={handleKeydown} /> + +<div class="active-channel" on:scroll={handleScroll} bind:this={activeChannel}> <ActiveChannel {messageRuns} /> </div> <div class="create-message max-h-full"> |
