frontend: preserve scroll position when loading more messages
This commit is contained in:
parent
e19a3aa6cc
commit
f7f536b318
3 changed files with 20 additions and 6 deletions
|
@ -1,6 +1,5 @@
|
|||
<script>
|
||||
import Main from "./pages/main/Main.svelte";
|
||||
|
||||
</script>
|
||||
|
||||
<Main />
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script>
|
||||
import { afterUpdate, beforeUpdate } from "svelte";
|
||||
import { element } from "svelte/internal";
|
||||
import { messagesStoreProvider } from "../../../stores.js";
|
||||
|
||||
export let channelId;
|
||||
let scrollTarget;
|
||||
let shouldAutoscroll = false;
|
||||
let lastScrollHeight = null;
|
||||
|
||||
$: messages = messagesStoreProvider.getStore(channelId);
|
||||
|
||||
|
@ -14,6 +14,12 @@ import { element } from "svelte/internal";
|
|||
});
|
||||
|
||||
afterUpdate(() => {
|
||||
// hacky way to preserve scroll position when messages are pushed back
|
||||
if (lastScrollHeight) {
|
||||
scrollTarget.scrollTop = scrollTarget.scrollHeight - lastScrollHeight;
|
||||
lastScrollHeight = null;
|
||||
return;
|
||||
}
|
||||
if (shouldAutoscroll && scrollTarget) {
|
||||
scrollTarget.scrollTo(0, scrollTarget.scrollHeight);
|
||||
}
|
||||
|
@ -21,11 +27,18 @@ import { element } from "svelte/internal";
|
|||
|
||||
const onScroll = (e) => {
|
||||
const { scrollTop, offsetHeight, scrollHeight } = e.target;
|
||||
if ((scrollTop + offsetHeight) >= scrollHeight) {
|
||||
if ((scrollTop + offsetHeight) >= scrollHeight) { // user scrolled to bottom
|
||||
messages.setIsCollectingOldMessages(true);
|
||||
} else {
|
||||
if (scrollTop === 0) {
|
||||
messages.loadOlderMessages();
|
||||
// load older messages if the user scrolls to the top.
|
||||
// save the current scroll height if the server returned any messages,
|
||||
// before commiting them to the store. this is to provide the jank scroll height
|
||||
// preservation
|
||||
messages.loadOlderMessages(() => {
|
||||
if (scrollTarget)
|
||||
lastScrollHeight = scrollTarget.scrollHeight;
|
||||
});
|
||||
}
|
||||
messages.setIsCollectingOldMessages(false);
|
||||
}
|
||||
|
|
|
@ -172,11 +172,13 @@ class MessageStore extends Store {
|
|||
this.collectOldMessages();
|
||||
}
|
||||
|
||||
async loadOlderMessages() {
|
||||
async loadOlderMessages(beforeCommitToStore=null) {
|
||||
const oldestMessage = this.value[0];
|
||||
const endpoint = oldestMessage ? `channels/${this.channelId}/messages/?before=${oldestMessage.id}` : `channels/${this.channelId}/messages`;
|
||||
const res = await request("GET", apiRoute(endpoint), true, null);
|
||||
if (res.success && res.ok && res.json && res.json.length > 0) {
|
||||
if (beforeCommitToStore)
|
||||
beforeCommitToStore(res.json);
|
||||
res.json.reverse();
|
||||
this.value = res.json.concat(this.value);
|
||||
this.updated();
|
||||
|
|
Loading…
Reference in a new issue