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:
parent
da7e57fe82
commit
7260525eec
6 changed files with 38 additions and 21 deletions
|
@ -49,7 +49,7 @@ import Messages from "./Messages.svelte";
|
||||||
<HashIcon />
|
<HashIcon />
|
||||||
<span class="h5 channel-heading">{ channel.name }</span>
|
<span class="h5 channel-heading">{ channel.name }</span>
|
||||||
</div>
|
</div>
|
||||||
<Messages channelId={ channel.id } />
|
<Messages channelId="{ channel.id }" />
|
||||||
<div class="message-input-container">
|
<div class="message-input-container">
|
||||||
<input type="text" class="message-input">
|
<input type="text" class="message-input">
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,16 +3,22 @@
|
||||||
|
|
||||||
export let channelId;
|
export let channelId;
|
||||||
|
|
||||||
const messages = messagesStoreProvider.getStore(channelId);
|
$: messages = messagesStoreProvider.getStore(channelId);
|
||||||
if (!messages.didInitialLoad)
|
$: {
|
||||||
|
if (!messages.didDoInitialLoad) {
|
||||||
messages.doInitialLoad();
|
messages.doInitialLoad();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const onScroll = (e) => {
|
const onScroll = (e) => {
|
||||||
const { scrollTop, offsetHeight, scrollHeight } = e.target;
|
const { scrollTop, offsetHeight, scrollHeight } = e.target;
|
||||||
|
if (scrollTop === 0) {
|
||||||
|
messages.loadOlderMessages();
|
||||||
|
}
|
||||||
if ((scrollTop + offsetHeight) >= scrollHeight) {
|
if ((scrollTop + offsetHeight) >= scrollHeight) {
|
||||||
setIsCollectingOldMessages(true);
|
messages.setIsCollectingOldMessages(true);
|
||||||
} else {
|
} else {
|
||||||
setIsCollectingOldMessages(false);
|
messages.setIsCollectingOldMessages(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import App from './components/App.svelte';
|
import App from './components/App.svelte';
|
||||||
import gateway from './gateway';
|
import gateway from './gateway';
|
||||||
import { initStorageDefaults } from './storage';
|
import request from './request';
|
||||||
|
import { apiRoute, initStorageDefaults } from './storage';
|
||||||
|
|
||||||
initStorageDefaults();
|
initStorageDefaults();
|
||||||
gateway.init();
|
gateway.init();
|
||||||
|
@ -11,6 +12,14 @@ if (loadingElement) {
|
||||||
loadingElement.parentElement.removeChild(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({
|
const app = new App({
|
||||||
target: document.body
|
target: document.body
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,6 +6,7 @@ export default async function(method, endpoint, auth=true, body=null) {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (body) {
|
if (body) {
|
||||||
|
options.body = JSON.stringify(body);
|
||||||
options.headers = {
|
options.headers = {
|
||||||
...options.headers || {},
|
...options.headers || {},
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
|
|
|
@ -141,6 +141,7 @@ class MessageStore extends Store {
|
||||||
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) {
|
||||||
|
res.json.reverse();
|
||||||
this.value = res.json.concat(this.value);
|
this.value = res.json.concat(this.value);
|
||||||
this.updated();
|
this.updated();
|
||||||
}
|
}
|
||||||
|
@ -168,10 +169,10 @@ class MessagesStoreProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
getStore(channelId) {
|
getStore(channelId) {
|
||||||
if (!this.storeByChannel[channelId]) {
|
if (!this.storeByChannel.get(channelId)) {
|
||||||
this.storeByChannel[channelId] = new MessageStore(channelId);
|
this.storeByChannel.set(channelId, new MessageStore(channelId));
|
||||||
}
|
}
|
||||||
return this.storeByChannel[channelId];
|
return this.storeByChannel.get(channelId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
22
test.rest
22
test.rest
|
@ -19,13 +19,13 @@ content-type: application/json
|
||||||
###
|
###
|
||||||
|
|
||||||
GET http://localhost:3000/api/v1/users/self HTTP/1.1
|
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
|
POST http://localhost:3000/api/v1/channels HTTP/1.1
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
|
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "channel 4"
|
"name": "channel 4"
|
||||||
|
@ -35,7 +35,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6M
|
||||||
|
|
||||||
PUT http://localhost:3000/api/v1/channels/7 HTTP/1.1
|
PUT http://localhost:3000/api/v1/channels/7 HTTP/1.1
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
|
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
|
||||||
#Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5MjU5NDUwLCJleHAiOjE2NDk0MzIyNTB9.JmF9NujFZnln7A-ynNpeyayGBqmR5poAyACYV6RnSQY
|
#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
|
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
|
#Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwidHlwZSI6MSwiaWF0IjoxNjQ5MjU5NDUwLCJleHAiOjE2NDk0MzIyNTB9.JmF9NujFZnln7A-ynNpeyayGBqmR5poAyACYV6RnSQY
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
GET http://localhost:3000/api/v1/channels/1 HTTP/1.1
|
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
|
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
|
POST http://localhost:3000/api/v1/channels/1/messages HTTP/1.1
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
|
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
|
||||||
|
|
||||||
{
|
{
|
||||||
"content": "i love cheese"
|
"content": "i love cheese"
|
||||||
|
@ -71,13 +71,13 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6M
|
||||||
###
|
###
|
||||||
|
|
||||||
GET http://localhost:3000/api/v1/channels/5/messages HTTP/1.1
|
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
|
PUT http://localhost:3000/api/v1/messages/3 HTTP/1.1
|
||||||
content-type: application/json
|
content-type: application/json
|
||||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
|
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
|
||||||
|
|
||||||
{
|
{
|
||||||
"content": "hello again!"
|
"content": "hello again!"
|
||||||
|
@ -86,9 +86,9 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6M
|
||||||
###
|
###
|
||||||
|
|
||||||
GET http://localhost:3000/api/v1/messages/3
|
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
|
DELETE http://localhost:3000/api/v1/messages/2 HTTP/1.1
|
||||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwMzg2NjcyLCJleHAiOjE2NTA1NTk0NzJ9.qoBPvIwm9uFf5ZhEjlo87FUgm3qsCHq-AbcZ_WDrtWY
|
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
|
||||||
|
|
Loading…
Reference in a new issue