From 14dc9e1c1581fa04b37e81d76499f705512660b2 Mon Sep 17 00:00:00 2001 From: Owen Jacobson Date: Wed, 6 Nov 2024 18:42:38 -0500 Subject: Split message runs after ten minutes' silence. I've also refactored how runs are processed, to avoid re-splitting runs every time the channel view is rendered. They're generated when messages are ingested into the `$messages` store, instead. --- ui/lib/components/ActiveChannel.svelte | 27 ++-------------- ui/lib/store.js | 2 +- ui/lib/store/messages.js | 40 ----------------------- ui/lib/store/messages.svelte.js | 59 ++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 66 deletions(-) delete mode 100644 ui/lib/store/messages.js create mode 100644 ui/lib/store/messages.svelte.js (limited to 'ui/lib') diff --git a/ui/lib/components/ActiveChannel.svelte b/ui/lib/components/ActiveChannel.svelte index a4ccd24..f939dbd 100644 --- a/ui/lib/components/ActiveChannel.svelte +++ b/ui/lib/components/ActiveChannel.svelte @@ -1,34 +1,11 @@
- {#each chunkBy(messageList, (msg) => msg.sender) as [sender, messages]} + {#each messageRuns as { sender, messages }}
diff --git a/ui/lib/store.js b/ui/lib/store.js index ae17ffa..3b20e05 100644 --- a/ui/lib/store.js +++ b/ui/lib/store.js @@ -1,6 +1,6 @@ import { writable } from 'svelte/store'; import { Channels } from '$lib/store/channels'; -import { Messages } from '$lib/store/messages'; +import { Messages } from '$lib/store/messages.svelte.js'; import { Logins } from '$lib/store/logins'; export const currentUser = writable(null); diff --git a/ui/lib/store/messages.js b/ui/lib/store/messages.js deleted file mode 100644 index 62c567a..0000000 --- a/ui/lib/store/messages.js +++ /dev/null @@ -1,40 +0,0 @@ -export class Messages { - constructor() { - this.channels = {}; - } - - inChannel(channel) { - return (this.channels[channel] = this.channels[channel] || []); - } - - addMessage(channel, id, at, sender, body) { - this.updateChannel(channel, (messages) => [...messages, { id, at, sender, body }]); - return this; - } - - setMessages(messages) { - this.channels = {}; - for (let { channel, id, at, sender, body } of messages) { - this.inChannel(channel).push({ id, at, sender, body }); - } - return this; - } - - deleteMessage(message) { - for (let channel in this.channels) { - this.updateChannel(channel, (messages) => messages.filter((msg) => msg.id != message)); - } - return this; - } - - deleteChannel(id) { - delete this.channels[id]; - return this; - } - - updateChannel(channel, callback) { - let messages = callback(this.inChannel(channel)); - messages.sort((a, b) => a.at - b.at); - this.channels[channel] = messages; - } -} diff --git a/ui/lib/store/messages.svelte.js b/ui/lib/store/messages.svelte.js new file mode 100644 index 0000000..1c59599 --- /dev/null +++ b/ui/lib/store/messages.svelte.js @@ -0,0 +1,59 @@ +const RUN_COALESCE_MAX_INTERVAL = 10 /* min */ * 60 /* sec */ * 1000; /* ms */ + +export class Messages { + channels = $state({}); + + inChannel(channel) { + return this.channels[channel]; + } + + addMessage(channel, id, at, sender, body) { + let parsedAt = new Date(at); + const message = { id, at: parsedAt, body }; + + let runs = (this.channels[channel] ||= []); + let currentRun = runs.slice(-1)[0]; + if (currentRun === undefined) { + currentRun = { sender, messages: [message] }; + runs.push(currentRun); + } else { + let lastMessage = currentRun.messages.slice(-1)[0]; + let newRun = + currentRun.sender !== sender || parsedAt - lastMessage.at > RUN_COALESCE_MAX_INTERVAL; + + if (newRun) { + currentRun = { sender, messages: [message] }; + runs.push(currentRun); + } else { + currentRun.messages.push(message); + } + } + + return this; + } + + setMessages(messages) { + this.channels = {}; + for (let { channel, id, at, sender, body } of messages) { + this.addMessage(channel, id, at, sender, body); + } + return this; + } + + deleteMessage(messageId) { + for (let channel in this.channels) { + this.channels[channel] = this.channels[channel] + .map(({ sender, messages }) => ({ + sender, + messages: messages.filter(({ id }) => id != messageId) + })) + .filter(({ messages }) => messages.length > 0); + } + return this; + } + + deleteChannel(id) { + delete this.channels[id]; + return this; + } +} -- cgit v1.2.3 From 1d4d4ca4832a49b50f382647327706bb50c9981d Mon Sep 17 00:00:00 2001 From: Kit La Touche Date: Thu, 7 Nov 2024 10:18:30 -0500 Subject: Backport multiline logic from prop/multiline-shift --- ui/lib/components/MessageInput.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'ui/lib') diff --git a/ui/lib/components/MessageInput.svelte b/ui/lib/components/MessageInput.svelte index 907391c..c071bea 100644 --- a/ui/lib/components/MessageInput.svelte +++ b/ui/lib/components/MessageInput.svelte @@ -18,7 +18,8 @@ } function onKeyDown(event) { - if (!event.altKey && event.key === 'Enter') { + let modifier = event.shiftKey || event.altKey || event.ctrlKey || event.metaKey; + if (!modifier && event.key === 'Enter') { onSubmit(event); } } -- cgit v1.2.3 From be6a2a94ffca6ffa2d007185d384d0bc06bda137 Mon Sep 17 00:00:00 2001 From: Kit La Touche Date: Thu, 7 Nov 2024 10:45:00 -0500 Subject: Tweak addMessage call signature --- ui/lib/apiServer.js | 6 +++++- ui/lib/store/messages.svelte.js | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'ui/lib') diff --git a/ui/lib/apiServer.js b/ui/lib/apiServer.js index a6fdaa6..6ada0f7 100644 --- a/ui/lib/apiServer.js +++ b/ui/lib/apiServer.js @@ -111,7 +111,11 @@ function onMessageEvent(data) { switch (data.event) { case 'sent': messages.update((value) => - value.addMessage(data.channel, data.id, data.at, data.sender, data.body) + value.addMessage(data.channel, data.id, { + at: data.at, + sender: data.sender, + body: data.body + }) ); break; case 'deleted': diff --git a/ui/lib/store/messages.svelte.js b/ui/lib/store/messages.svelte.js index 1c59599..4630a40 100644 --- a/ui/lib/store/messages.svelte.js +++ b/ui/lib/store/messages.svelte.js @@ -7,7 +7,7 @@ export class Messages { return this.channels[channel]; } - addMessage(channel, id, at, sender, body) { + addMessage(channel, id, { at, sender, body }) { let parsedAt = new Date(at); const message = { id, at: parsedAt, body }; @@ -19,7 +19,8 @@ export class Messages { } else { let lastMessage = currentRun.messages.slice(-1)[0]; let newRun = - currentRun.sender !== sender || parsedAt - lastMessage.at > RUN_COALESCE_MAX_INTERVAL; + currentRun.sender !== sender + || parsedAt - lastMessage.at > RUN_COALESCE_MAX_INTERVAL; if (newRun) { currentRun = { sender, messages: [message] }; -- cgit v1.2.3 From 93d204ae60fb340bb9c3dc047e375a48b98f713e Mon Sep 17 00:00:00 2001 From: Owen Jacobson Date: Thu, 7 Nov 2024 18:57:10 -0500 Subject: Fix up calls to `addMessage` inside `Messages`. --- ui/lib/store/messages.svelte.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'ui/lib') diff --git a/ui/lib/store/messages.svelte.js b/ui/lib/store/messages.svelte.js index 4630a40..2442675 100644 --- a/ui/lib/store/messages.svelte.js +++ b/ui/lib/store/messages.svelte.js @@ -19,8 +19,7 @@ export class Messages { } else { let lastMessage = currentRun.messages.slice(-1)[0]; let newRun = - currentRun.sender !== sender - || parsedAt - lastMessage.at > RUN_COALESCE_MAX_INTERVAL; + currentRun.sender !== sender || parsedAt - lastMessage.at > RUN_COALESCE_MAX_INTERVAL; if (newRun) { currentRun = { sender, messages: [message] }; @@ -36,7 +35,7 @@ export class Messages { setMessages(messages) { this.channels = {}; for (let { channel, id, at, sender, body } of messages) { - this.addMessage(channel, id, at, sender, body); + this.addMessage(channel, id, { at, sender, body }); } return this; } -- cgit v1.2.3 From ae9f3889de763d7841ab0acc7d7589da5bb830ff Mon Sep 17 00:00:00 2001 From: Owen Jacobson Date: Wed, 6 Nov 2024 17:12:25 -0500 Subject: Sort out padding and wrapping for the chat input --- ui/lib/components/MessageInput.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui/lib') diff --git a/ui/lib/components/MessageInput.svelte b/ui/lib/components/MessageInput.svelte index c071bea..26521e1 100644 --- a/ui/lib/components/MessageInput.svelte +++ b/ui/lib/components/MessageInput.svelte @@ -31,7 +31,7 @@ bind:value {disabled} type="search" - class="flex-auto h-6 input rounded-r-none" + class="flex-auto h-6 py-0 input rounded-r-none text-nowrap" >
-- cgit v1.2.3 From 9f0ba2e243be772a7677f8250893f5da7b2acbfe Mon Sep 17 00:00:00 2001 From: Owen Jacobson Date: Wed, 6 Nov 2024 17:42:02 -0500 Subject: Factor out the elements of the `/me` page, and style them a little. --- ui/lib/components/ChangePassword.svelte | 60 +++++++++++++++++++++++ ui/lib/components/Invite.svelte | 5 +- ui/lib/components/Invites.svelte | 13 ++--- ui/lib/components/LogOut.svelte | 18 +++++++ ui/routes/(app)/me/+page.svelte | 84 +++++---------------------------- 5 files changed, 97 insertions(+), 83 deletions(-) create mode 100644 ui/lib/components/ChangePassword.svelte create mode 100644 ui/lib/components/LogOut.svelte (limited to 'ui/lib') diff --git a/ui/lib/components/ChangePassword.svelte b/ui/lib/components/ChangePassword.svelte new file mode 100644 index 0000000..1e48bee --- /dev/null +++ b/ui/lib/components/ChangePassword.svelte @@ -0,0 +1,60 @@ + + +
+ + + + + + + +
diff --git a/ui/lib/components/Invite.svelte b/ui/lib/components/Invite.svelte index 35e00b4..381f483 100644 --- a/ui/lib/components/Invite.svelte +++ b/ui/lib/components/Invite.svelte @@ -5,8 +5,5 @@ let inviteUrl = $derived(new URL(`/invite/${id}`, document.location)); - + {inviteUrl} diff --git a/ui/lib/components/Invites.svelte b/ui/lib/components/Invites.svelte index cc14f3b..314782a 100644 --- a/ui/lib/components/Invites.svelte +++ b/ui/lib/components/Invites.svelte @@ -4,7 +4,7 @@ let invites = $state([]); - async function onSubmit(event) { + async function onsubmit(event) { event.preventDefault(); let response = await createInvite(); if (response.status == 200) { @@ -13,11 +13,12 @@ } -