frontend: message loading

This command finalizes support for dynamic message loading. The behavior is as follows:
When a user selects a channel for the first time, an "initial load" of messages will happen.
When the user is scrolled all the way to the bottom of the message view,
the store will continuously remove old messages to save memory.
Scrolling all the way to the top loads more messages.
This commit is contained in:
hippoz 2022-04-20 03:14:28 +03:00
parent da7e57fe82
commit 7260525eec
Signed by: hippoz
GPG key ID: 7C52899193467641
6 changed files with 38 additions and 21 deletions

View file

@ -49,7 +49,7 @@ import Messages from "./Messages.svelte";
<HashIcon />
<span class="h5 channel-heading">{ channel.name }</span>
</div>
<Messages channelId={ channel.id } />
<Messages channelId="{ channel.id }" />
<div class="message-input-container">
<input type="text" class="message-input">
</div>

View file

@ -3,16 +3,22 @@
export let channelId;
const messages = messagesStoreProvider.getStore(channelId);
if (!messages.didInitialLoad)
$: messages = messagesStoreProvider.getStore(channelId);
$: {
if (!messages.didDoInitialLoad) {
messages.doInitialLoad();
}
}
const onScroll = (e) => {
const { scrollTop, offsetHeight, scrollHeight } = e.target;
if (scrollTop === 0) {
messages.loadOlderMessages();
}
if ((scrollTop + offsetHeight) >= scrollHeight) {
setIsCollectingOldMessages(true);
messages.setIsCollectingOldMessages(true);
} else {
setIsCollectingOldMessages(false);
messages.setIsCollectingOldMessages(false);
}
};

View file

@ -1,6 +1,7 @@
import App from './components/App.svelte';
import gateway from './gateway';
import { initStorageDefaults } from './storage';
import request from './request';
import { apiRoute, initStorageDefaults } from './storage';
initStorageDefaults();
gateway.init();
@ -11,6 +12,14 @@ if (loadingElement) {
loadingElement.parentElement.removeChild(loadingElement);
}
window.__testing = async () => {
for (let i = 0; i < 100; i++) {
await request("POST", apiRoute("channels/6/messages"), true, {
content: `test ${i}`
});
}
};
const app = new App({
target: document.body
});

View file

@ -6,6 +6,7 @@ export default async function(method, endpoint, auth=true, body=null) {
};
if (body) {
options.body = JSON.stringify(body);
options.headers = {
...options.headers || {},
"Content-Type": "application/json"

View file

@ -141,6 +141,7 @@ class MessageStore extends Store {
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) {
res.json.reverse();
this.value = res.json.concat(this.value);
this.updated();
}
@ -168,10 +169,10 @@ class MessagesStoreProvider {
}
getStore(channelId) {
if (!this.storeByChannel[channelId]) {
this.storeByChannel[channelId] = new MessageStore(channelId);
if (!this.storeByChannel.get(channelId)) {
this.storeByChannel.set(channelId, new MessageStore(channelId));
}
return this.storeByChannel[channelId];
return this.storeByChannel.get(channelId);
}
}

View file

@ -19,13 +19,13 @@ content-type: application/json
###
GET http://localhost:3000/api/v1/users/self HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
###
POST http://localhost:3000/api/v1/channels HTTP/1.1
content-type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
{
"name": "channel 4"
@ -35,7 +35,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6M
PUT http://localhost:3000/api/v1/channels/7 HTTP/1.1
content-type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
#Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5MjU5NDUwLCJleHAiOjE2NDk0MzIyNTB9.JmF9NujFZnln7A-ynNpeyayGBqmR5poAyACYV6RnSQY
{
@ -45,24 +45,24 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6M
###
DELETE http://localhost:3000/api/v1/channels/9 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
#Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5MjU5NDUwLCJleHAiOjE2NDk0MzIyNTB9.JmF9NujFZnln7A-ynNpeyayGBqmR5poAyACYV6RnSQY
###
GET http://localhost:3000/api/v1/channels/1 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
###
GET http://localhost:3000/api/v1/channels HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
###
POST http://localhost:3000/api/v1/channels/1/messages HTTP/1.1
content-type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
{
"content": "i love cheese"
@ -71,13 +71,13 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6M
###
GET http://localhost:3000/api/v1/channels/5/messages HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
###
PUT http://localhost:3000/api/v1/messages/3 HTTP/1.1
content-type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
{
"content": "hello again!"
@ -86,9 +86,9 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6M
###
GET http://localhost:3000/api/v1/messages/3
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
###
DELETE http://localhost:3000/api/v1/messages/2 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss