frontend: send messages

This commit is contained in:
hippoz 2022-04-20 03:44:48 +03:00
parent 7260525eec
commit 0d95b02401
Signed by: hippoz
GPG key ID: 7C52899193467641
4 changed files with 74 additions and 9 deletions

View file

@ -1,8 +1,46 @@
<script> <script>
import { HashIcon } from "svelte-feather-icons"; import { HashIcon } from "svelte-feather-icons";
import Messages from "./Messages.svelte"; import request from "../../../request";
import { apiRoute } from "../../../storage";
import { messagesStoreProvider, userInfoStore } from "../../../stores";
import Messages from "./Messages.svelte";
export let channel; export let channel;
let messageInput = "";
$: messages = messagesStoreProvider.getStore(channel.id);
const onKeydown = async (e) => {
if (e.code !== "Enter")
return;
if (messageInput.trim() === "" || !$userInfoStore)
return;
// optimistically add message to store
const optimisticMessageId = Math.floor(Math.random() * 999999);
const optimisticMessage = {
id: optimisticMessageId,
content: messageInput,
channel_id: channel.id,
author_id: $userInfoStore.id,
author_username: $userInfoStore.username,
createdAt: Date.now().toString()
};
messages.addMessage(optimisticMessage);
const res = await request("POST", apiRoute(`channels/${channel.id}/messages`), true, {
content: messageInput
});
if (res.success && res.ok) {
messages.updateId(optimisticMessageId, res.json.id);
} else {
messages.deleteMessage({
id: optimisticMessageId
});
}
};
</script> </script>
<style> <style>
@ -51,6 +89,6 @@ import Messages from "./Messages.svelte";
</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" on:keydown={ onKeydown } bind:value={ messageInput }>
</div> </div>
</div> </div>

View file

@ -4,11 +4,6 @@
export let channelId; export let channelId;
$: messages = messagesStoreProvider.getStore(channelId); $: messages = messagesStoreProvider.getStore(channelId);
$: {
if (!messages.didDoInitialLoad) {
messages.doInitialLoad();
}
}
const onScroll = (e) => { const onScroll = (e) => {
const { scrollTop, offsetHeight, scrollHeight } = e.target; const { scrollTop, offsetHeight, scrollHeight } = e.target;

View file

@ -80,6 +80,22 @@ class GatewayStatusStore extends Store {
} }
} }
class UserInfoStore extends Store {
constructor() {
super(null);
gateway.subscribe(GatewayEventType.Ready, ({ user }) => {
this.value = user;
this.updated();
});
gateway.subscribe(GatewayEventType.Close, () => {
this.value = null;
this.updated();
});
}
}
class MessageStore extends Store { class MessageStore extends Store {
constructor(channelId) { constructor(channelId) {
super([]); super([]);
@ -96,6 +112,16 @@ class MessageStore extends Store {
} }
} }
updateId(oldId, newId) {
const index = this.value.findIndex(e => e.id === oldId);
if (index === -1)
return;
this.value[index].id = newId;
this.updated();
}
updateMessage(message) { updateMessage(message) {
const index = this.value.findIndex(e => e.id === message.id); const index = this.value.findIndex(e => e.id === message.id);
if (index === -1) if (index === -1)
@ -158,6 +184,9 @@ class MessagesStoreProvider {
this.storeByChannel = new Map(); this.storeByChannel = new Map();
gateway.subscribe(GatewayEventType.MessageCreate, (message) => { gateway.subscribe(GatewayEventType.MessageCreate, (message) => {
// we currently don't care about our own messages
if (gateway.user && message.author_id === gateway.user.id)
return;
this.getStore(message.channel_id).addMessage(message); this.getStore(message.channel_id).addMessage(message);
}); });
gateway.subscribe(GatewayEventType.MessageUpdate, (message) => { gateway.subscribe(GatewayEventType.MessageUpdate, (message) => {
@ -170,7 +199,9 @@ class MessagesStoreProvider {
getStore(channelId) { getStore(channelId) {
if (!this.storeByChannel.get(channelId)) { if (!this.storeByChannel.get(channelId)) {
this.storeByChannel.set(channelId, new MessageStore(channelId)); const store = new MessageStore(channelId);
store.doInitialLoad();
this.storeByChannel.set(channelId, store);
} }
return this.storeByChannel.get(channelId); return this.storeByChannel.get(channelId);
} }
@ -179,4 +210,5 @@ class MessagesStoreProvider {
export const channels = new ChannelsStore(); export const channels = new ChannelsStore();
export const gatewayStatus = new GatewayStatusStore(); export const gatewayStatus = new GatewayStatusStore();
export const messagesStoreProvider = new MessagesStoreProvider(); export const messagesStoreProvider = new MessagesStoreProvider();
export const userInfoStore = new UserInfoStore();
export const selectedChannel = writable({ id: -1, name: "none", creator_id: -1 }); export const selectedChannel = writable({ id: -1, name: "none", creator_id: -1 });

View file

@ -70,7 +70,7 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6M
### ###
GET http://localhost:3000/api/v1/channels/5/messages HTTP/1.1 GET http://localhost:3000/api/v1/channels/6/messages HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidHlwZSI6MSwiaWF0IjoxNjUwNDA4NTQ1LCJleHAiOjE2NTA1ODEzNDV9.DCt_IpukPaihSGl1N8a5ve5pd75N4aePxR4YKzw98Ss
### ###