106 lines
2.9 KiB
Svelte
106 lines
2.9 KiB
Svelte
<script>
|
|
import { SendIcon } from "svelte-feather-icons";
|
|
import request from "../request";
|
|
import { apiRoute } from "../storage";
|
|
import { messagesStoreProvider, overlayStore, smallViewport, userInfoStore } from "../stores";
|
|
|
|
export let channel;
|
|
let messageInput = "";
|
|
let messageTextarea;
|
|
|
|
$: messages = messagesStoreProvider.getStore(channel.id);
|
|
|
|
const sendMessage = async () => {
|
|
messageTextarea.focus();
|
|
|
|
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,
|
|
created_at: Date.now().toString(),
|
|
_isPending: true
|
|
};
|
|
messages.addMessage(optimisticMessage);
|
|
messageInput = "";
|
|
|
|
const res = await request("POST", apiRoute(`channels/${channel.id}/messages`), true, {
|
|
content: optimisticMessage.content
|
|
});
|
|
|
|
if (res.success && res.ok) {
|
|
messages.setMessage(optimisticMessageId, res.json);
|
|
} else {
|
|
messages.deleteMessage({
|
|
id: optimisticMessageId
|
|
});
|
|
overlayStore.open("toast", {
|
|
message: "Couldn't send message"
|
|
});
|
|
}
|
|
};
|
|
|
|
const onKeydown = async (e) => {
|
|
if (e.code === "Enter") {
|
|
if (e.shiftKey) {
|
|
return;
|
|
} else {
|
|
e.preventDefault();
|
|
await sendMessage();
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style>
|
|
.message-input-container {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
width: 100%;
|
|
padding: var(--space-norm);
|
|
}
|
|
|
|
.message-input {
|
|
width: 100%;
|
|
background-color : var(--background-color-2);
|
|
border: none;
|
|
color: currentColor;
|
|
border-radius: var(--radius-md);
|
|
padding: var(--space-sm);
|
|
font-size: inherit;
|
|
line-height: inherit;
|
|
resize: none;
|
|
}
|
|
|
|
.message-input::placeholder {
|
|
color: var(--foreground-color-3);
|
|
}
|
|
|
|
.send-button {
|
|
margin-left: var(--space-sm);
|
|
}
|
|
</style>
|
|
|
|
<div class="message-input-container">
|
|
<textarea
|
|
placeholder={$smallViewport ? `Message #${channel.name}` : `Send something interesting to #${channel.name}`}
|
|
type="text"
|
|
class="message-input"
|
|
rows="1"
|
|
on:keydown={ onKeydown }
|
|
bind:value={ messageInput }
|
|
bind:this={ messageTextarea }
|
|
/>
|
|
{#if $smallViewport}
|
|
<button class="icon-button send-button" on:click="{ sendMessage }">
|
|
<SendIcon />
|
|
</button>
|
|
{/if}
|
|
</div>
|