diff options
| author | Kit La Touche <kit@transneptune.net> | 2024-10-30 23:26:23 -0400 |
|---|---|---|
| committer | Kit La Touche <kit@transneptune.net> | 2024-10-30 23:26:23 -0400 |
| commit | 80220d2188e0553304f2c78d225bbe275d8ba572 (patch) | |
| tree | de0a62325c698197612574c7a9f37dad279581be | |
| parent | 51aabd07ca5eeaee45a564f8799cc42dc195068c (diff) | |
| parent | 35b8a914b867237c9c64f33838b1e1f85fc46fb8 (diff) | |
Merge branch 'main' into wip/mobile
| -rw-r--r-- | migrations/20241030213852_token_login_index.sql | 2 | ||||
| -rw-r--r-- | ui/lib/apiServer.js | 18 | ||||
| -rw-r--r-- | ui/lib/components/ActiveChannel.svelte | 27 | ||||
| -rw-r--r-- | ui/lib/components/CreateChannelForm.svelte | 9 | ||||
| -rw-r--r-- | ui/lib/components/Message.svelte | 30 | ||||
| -rw-r--r-- | ui/lib/components/MessageInput.svelte | 10 | ||||
| -rw-r--r-- | ui/lib/components/MessageRun.svelte | 34 | ||||
| -rw-r--r-- | ui/lib/store/messages.js | 3 | ||||
| -rw-r--r-- | ui/routes/(app)/me/+page.svelte | 2 | ||||
| -rw-r--r-- | ui/routes/(login)/invite/[invite]/+page.svelte | 10 | ||||
| -rw-r--r-- | ui/routes/(login)/login/+page.svelte | 10 | ||||
| -rw-r--r-- | ui/routes/(login)/setup/+page.svelte | 10 |
12 files changed, 97 insertions, 68 deletions
diff --git a/migrations/20241030213852_token_login_index.sql b/migrations/20241030213852_token_login_index.sql new file mode 100644 index 0000000..7e57846 --- /dev/null +++ b/migrations/20241030213852_token_login_index.sql @@ -0,0 +1,2 @@ +create index token_login +on token (login); diff --git a/ui/lib/apiServer.js b/ui/lib/apiServer.js index 19dcf60..5c6e5ef 100644 --- a/ui/lib/apiServer.js +++ b/ui/lib/apiServer.js @@ -10,20 +10,12 @@ export async function boot() { return apiServer.get('/boot'); } -export async function setup(username, password) { - const data = { - name: username, - password, - }; - return apiServer.post('/setup', data); +export async function setup(name, password) { + return apiServer.post('/setup', { name, password }); } -export async function logIn(username, password) { - const data = { - name: username, - password, - }; - return apiServer.post('/auth/login', data); +export async function logIn(name, password) { + return apiServer.post('/auth/login', { name, password }); } export async function logOut() { @@ -46,7 +38,7 @@ export async function deleteMessage(messageId) { // TODO } -export async function createInvite(inviteId) { +export async function createInvite() { return apiServer.post(`/invite`, {}); } diff --git a/ui/lib/components/ActiveChannel.svelte b/ui/lib/components/ActiveChannel.svelte index ece9f55..1b23bc1 100644 --- a/ui/lib/components/ActiveChannel.svelte +++ b/ui/lib/components/ActiveChannel.svelte @@ -1,10 +1,33 @@ <script> import { messages } from '$lib/store'; import Message from './Message.svelte'; + import MessageRun from './MessageRun.svelte'; export let channel = null; $: messageList = channel !== null ? $messages.inChannel(channel) : []; + function *chunkBy(xs, fn) { + let chunk; + let key; + for (let x of xs) { + let newKey = fn(x); + if (key !== newKey) { + if (chunk !== undefined) { + yield [key, chunk]; + } + + chunk = [x]; + key = newKey; + } else { + chunk.push(x); + } + } + if (chunk !== undefined) { + yield [key, chunk]; + } + } + + let container; // TODO: eventually, store scroll height/last unread in channel? scroll there? @@ -14,9 +37,9 @@ </script> <div class="container" bind:this={container}> - {#each messageList as message} + {#each chunkBy(messageList, msg => msg.sender) as [sender, messages]} <div use:scroll> - <Message {...message} /> + <MessageRun {sender} {messages} /> </div> {/each} </div> diff --git a/ui/lib/components/CreateChannelForm.svelte b/ui/lib/components/CreateChannelForm.svelte index ddcf486..b716736 100644 --- a/ui/lib/components/CreateChannelForm.svelte +++ b/ui/lib/components/CreateChannelForm.svelte @@ -1,16 +1,17 @@ <script> import { createChannel } from '$lib/apiServer'; - let name = ''; - let disabled = false; + let name = ""; + let pending = false; + $: disabled = pending; async function handleSubmit(event) { - disabled = true; + pending = true; const response = await createChannel(name); if (200 <= response.status && response.status < 300) { name = ''; } - disabled = false; + pending = false; } </script> diff --git a/ui/lib/components/Message.svelte b/ui/lib/components/Message.svelte index 2705e4b..ef8ea0b 100644 --- a/ui/lib/components/Message.svelte +++ b/ui/lib/components/Message.svelte @@ -1,42 +1,22 @@ <script> import SvelteMarkdown from 'svelte-markdown'; - import { currentUser, logins } from '$lib/store'; - import { deleteMessage } from '$lib/apiServer'; - export let at; // XXX: Omitted for now. - export let sender; + export let at; export let body; - - let timestamp = new Date(at).toTimeString(); - let name; - $: name = $logins.get(sender); - $: ownMessage = $currentUser.id == sender; </script> -<div class="card card-hover m-4 relative" class:own-message={ownMessage} class:other-message={!ownMessage}> - <span class="chip variant-soft sticky top-o left-0"> - <!-- TODO: should this show up for only the first of a run? --> - @{name}: - </span> +<div class="message relative"> <span class="timestamp chip variant-soft absolute top-0 right-0">{at}</span> - <section class="p-4"> + <section class="p-1"> <SvelteMarkdown source={body} /> </section> </div> <style> - .card .timestamp { + .message .timestamp { display: none; } - .card:hover .timestamp { + .message:hover .timestamp { display: flex; } - .own-message { - width: 80%; - margin-right: auto; - } - .other-message { - width: 80%; - margin-left: auto; - } </style> diff --git a/ui/lib/components/MessageInput.svelte b/ui/lib/components/MessageInput.svelte index b2746e0..03ac7fa 100644 --- a/ui/lib/components/MessageInput.svelte +++ b/ui/lib/components/MessageInput.svelte @@ -5,16 +5,16 @@ export let channel = null; let input; let value = ''; - let sending = false; + let pending = false; - $: disabled = (channel === null); + $: disabled = pending || (channel === null); async function handleSubmit() { if (channel !== null) { - sending = true; + pending = true; // TODO try/catch: await postToChannel(channel, value); - sending = false; + pending = false; value = ''; await tick(); input.focus(); @@ -23,6 +23,6 @@ </script> <form on:submit|preventDefault={handleSubmit} class="flex flex-row flex-nowrap"> - <input bind:this={input} bind:value={value} disabled={sending || disabled} type="search" class="flex-auto h-6 input rounded-r-none" /> + <input bind:this={input} bind:value={value} disabled={disabled} type="search" class="flex-auto h-6 input rounded-r-none" /> <button color="primary variant-filled-secondary" type="submit" class="flex-none w-6 h-6 btn-icon variant-filled rounded-l-none">»</button> </form> diff --git a/ui/lib/components/MessageRun.svelte b/ui/lib/components/MessageRun.svelte new file mode 100644 index 0000000..0ecaabc --- /dev/null +++ b/ui/lib/components/MessageRun.svelte @@ -0,0 +1,34 @@ +<script> + import { logins, currentUser } from '$lib/store'; + import Message from '$lib/components/Message.svelte'; + + export let sender; + export let messages; + + let name; + $: name = $logins.get(sender); + $: ownMessage = $currentUser.id == sender; +</script> + +<div + class="card card-hover m-4 relative" + class:own-message={ownMessage} + class:other-message={!ownMessage}> + <span class="chip variant-soft sticky top-o left-0"> + @{name}: + </span> + {#each messages as { at, body }} + <Message {at} {body} /> + {/each} +</div> + +<style> + .own-message { + width: 80%; + margin-right: auto; + } + .other-message { + width: 80%; + margin-left: auto; + } +</style> diff --git a/ui/lib/store/messages.js b/ui/lib/store/messages.js index 931b8fb..7d1fbe1 100644 --- a/ui/lib/store/messages.js +++ b/ui/lib/store/messages.js @@ -17,9 +17,6 @@ export class Messages { for (let { channel, id, at, sender, body } of messages) { this.inChannel(channel).push({ id, at, sender, body, }); } - for (let channel in this.channels) { - this.channels[channel].sort((a, b) => a.at - b.at); - } return this; } diff --git a/ui/routes/(app)/me/+page.svelte b/ui/routes/(app)/me/+page.svelte index 7559dbe..82af3c7 100644 --- a/ui/routes/(app)/me/+page.svelte +++ b/ui/routes/(app)/me/+page.svelte @@ -3,7 +3,7 @@ import Invites from '$lib/components/Invites.svelte'; - let currentPassword, newPassword, confirmPassword, passwordForm; + let currentPassword = "", newPassword = "", confirmPassword = "", passwordForm; let pending = false; $: valid = (newPassword === confirmPassword) && (newPassword !== currentPassword); $: disabled = pending || !valid; diff --git a/ui/routes/(login)/invite/[invite]/+page.svelte b/ui/routes/(login)/invite/[invite]/+page.svelte index 798dfb7..7ae388a 100644 --- a/ui/routes/(login)/invite/[invite]/+page.svelte +++ b/ui/routes/(login)/invite/[invite]/+page.svelte @@ -6,19 +6,19 @@ export let data; - let disabled; - let username; - let password; + let username = "", password = ""; + let pending = false; + $: disabled = pending; async function onSubmit() { - disabled = true; + pending = true; const response = await acceptInvite(data.invite.id, username, password); if (200 <= response.status && response.status < 300) { username = ''; password = ''; goto('/'); } - disabled = false; + pending = false; } </script> diff --git a/ui/routes/(login)/login/+page.svelte b/ui/routes/(login)/login/+page.svelte index 29dba54..0387e4a 100644 --- a/ui/routes/(login)/login/+page.svelte +++ b/ui/routes/(login)/login/+page.svelte @@ -4,19 +4,19 @@ import LogIn from '$lib/components/LogIn.svelte'; - let disabled; - let username; - let password; + let username = "", password = ""; + let pending = false; + $: disabled = pending; async function onSubmit() { - disabled = true; + pending = true; const response = await logIn(username, password); if (200 <= response.status && response.status < 300) { username = ''; password = ''; goto('/'); } - disabled = false; + pending = false; } </script> diff --git a/ui/routes/(login)/setup/+page.svelte b/ui/routes/(login)/setup/+page.svelte index 2503502..a1974b8 100644 --- a/ui/routes/(login)/setup/+page.svelte +++ b/ui/routes/(login)/setup/+page.svelte @@ -4,19 +4,19 @@ import LogIn from '$lib/components/LogIn.svelte'; - let disabled; - let username; - let password; + let username = "", password = ""; + let pending = false; + $: disabled = pending; async function onSubmit() { - disabled = true; + pending = true; const response = await setup(username, password); if (200 <= response.status && response.status < 300) { username = ''; password = ''; goto('/'); } - disabled = false; + pending = false; } </script> |
