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>
|
<script>
|
||||||
import Main from "./pages/main/Main.svelte";
|
import Main from "./pages/main/Main.svelte";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Main />
|
<Main />
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
import { afterUpdate, beforeUpdate } from "svelte";
|
import { afterUpdate, beforeUpdate } from "svelte";
|
||||||
import { element } from "svelte/internal";
|
|
||||||
import { messagesStoreProvider } from "../../../stores.js";
|
import { messagesStoreProvider } from "../../../stores.js";
|
||||||
|
|
||||||
export let channelId;
|
export let channelId;
|
||||||
let scrollTarget;
|
let scrollTarget;
|
||||||
let shouldAutoscroll = false;
|
let shouldAutoscroll = false;
|
||||||
|
let lastScrollHeight = null;
|
||||||
|
|
||||||
$: messages = messagesStoreProvider.getStore(channelId);
|
$: messages = messagesStoreProvider.getStore(channelId);
|
||||||
|
|
||||||
|
@ -14,6 +14,12 @@ import { element } from "svelte/internal";
|
||||||
});
|
});
|
||||||
|
|
||||||
afterUpdate(() => {
|
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) {
|
if (shouldAutoscroll && scrollTarget) {
|
||||||
scrollTarget.scrollTo(0, scrollTarget.scrollHeight);
|
scrollTarget.scrollTo(0, scrollTarget.scrollHeight);
|
||||||
}
|
}
|
||||||
|
@ -21,11 +27,18 @@ import { element } from "svelte/internal";
|
||||||
|
|
||||||
const onScroll = (e) => {
|
const onScroll = (e) => {
|
||||||
const { scrollTop, offsetHeight, scrollHeight } = e.target;
|
const { scrollTop, offsetHeight, scrollHeight } = e.target;
|
||||||
if ((scrollTop + offsetHeight) >= scrollHeight) {
|
if ((scrollTop + offsetHeight) >= scrollHeight) { // user scrolled to bottom
|
||||||
messages.setIsCollectingOldMessages(true);
|
messages.setIsCollectingOldMessages(true);
|
||||||
} else {
|
} else {
|
||||||
if (scrollTop === 0) {
|
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);
|
messages.setIsCollectingOldMessages(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,11 +172,13 @@ class MessageStore extends Store {
|
||||||
this.collectOldMessages();
|
this.collectOldMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadOlderMessages() {
|
async loadOlderMessages(beforeCommitToStore=null) {
|
||||||
const oldestMessage = this.value[0];
|
const oldestMessage = this.value[0];
|
||||||
const endpoint = oldestMessage ? `channels/${this.channelId}/messages/?before=${oldestMessage.id}` : `channels/${this.channelId}/messages`;
|
const endpoint = oldestMessage ? `channels/${this.channelId}/messages/?before=${oldestMessage.id}` : `channels/${this.channelId}/messages`;
|
||||||
const res = await request("GET", apiRoute(endpoint), true, null);
|
const res = await request("GET", apiRoute(endpoint), true, null);
|
||||||
if (res.success && res.ok && res.json && res.json.length > 0) {
|
if (res.success && res.ok && res.json && res.json.length > 0) {
|
||||||
|
if (beforeCommitToStore)
|
||||||
|
beforeCommitToStore(res.json);
|
||||||
res.json.reverse();
|
res.json.reverse();
|
||||||
this.value = res.json.concat(this.value);
|
this.value = res.json.concat(this.value);
|
||||||
this.updated();
|
this.updated();
|
||||||
|
|
Loading…
Reference in a new issue