diff --git a/src/app/components/RoomChat.svelte b/src/app/components/RoomChat.svelte
index 58ce9963..391dd964 100644
--- a/src/app/components/RoomChat.svelte
+++ b/src/app/components/RoomChat.svelte
@@ -21,6 +21,8 @@
import Divider from "@lib/components/Divider.svelte"
import Icon from "@lib/components/Icon.svelte"
import Spinner from "@lib/components/Spinner.svelte"
+ import VirtualList from "@lib/components/VirtualList.svelte"
+ import type {VirtualListController} from "@lib/components/VirtualList.svelte"
import RoomCompose from "@app/components/RoomCompose.svelte"
import RoomComposeEdit from "@app/components/RoomComposeEdit.svelte"
import RoomComposeParent from "@app/components/RoomComposeParent.svelte"
@@ -232,6 +234,8 @@
}
}
+ const getElementKey = (element: {id: string}) => element.id
+
const manageScrollPosition = () => {
// Only treat an `at` jump as "scrolled up" when it targets an event below the
// newest one; jumping to the most recent message already lands us at the bottom.
@@ -259,6 +263,10 @@
const targetEvent = $events.find(event => event.created_at >= at)
if (targetEvent) {
+ // The list renders from the newest message outward, so a jump target deep in history
+ // may not be on the page yet
+ virtualList?.reveal(targetEvent.id)
+
const target = element?.querySelector(`[data-event="${targetEvent.id}"]`)
if (target instanceof HTMLElement) {
@@ -280,8 +288,16 @@
isProgrammaticScroll = false
}
- const scrollToNewMessages = () =>
- document.getElementById("new-messages")?.scrollIntoView({behavior: "smooth", block: "center"})
+ const scrollToNewMessages = () => {
+ virtualList?.reveal("new-messages")
+
+ // Revealing it renders it on the next flush, so the scroll has to wait for that
+ requestAnimationFrame(() =>
+ document
+ .getElementById("new-messages")
+ ?.scrollIntoView({behavior: "smooth", block: "center"}),
+ )
+ }
const scrollToBottom = () => {
if (!isNaN(at)) {
@@ -308,6 +324,7 @@
let userHasScrolled = $state(false)
let isProgrammaticScroll = $state(false)
let isUserScrolling = $state(false)
+ let virtualList: Maybe
- New Messages -
- -+ New Messages +
+ +
{#if loadingBackward}