summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2024-10-30 18:50:01 -0400
committerOwen Jacobson <owen@grimoire.ca>2024-10-30 18:50:01 -0400
commita356546fc706b2ade758e7f42069e6d669330421 (patch)
tree1da521415b6fe99eddbbb395a95f4b5a154de18c
parent1eec6338e1146439b1dbc6207843fbc44dd13088 (diff)
Coalesce adjacent messages by the same author into runs, to consolidate message display.
-rw-r--r--ui/lib/components/ActiveChannel.svelte27
-rw-r--r--ui/lib/components/Message.svelte21
-rw-r--r--ui/lib/components/MessageRun.svelte20
-rw-r--r--ui/lib/store/messages.js3
4 files changed, 50 insertions, 21 deletions
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/Message.svelte b/ui/lib/components/Message.svelte
index d040433..ef8ea0b 100644
--- a/ui/lib/components/Message.svelte
+++ b/ui/lib/components/Message.svelte
@@ -1,33 +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);
</script>
-<div class="card card-hover m-4 relative">
- <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;
}
</style>
diff --git a/ui/lib/components/MessageRun.svelte b/ui/lib/components/MessageRun.svelte
new file mode 100644
index 0000000..b998a8b
--- /dev/null
+++ b/ui/lib/components/MessageRun.svelte
@@ -0,0 +1,20 @@
+<script>
+ import { logins } from '$lib/store';
+ import Message from '$lib/components/Message.svelte';
+
+ export let sender;
+ export let messages;
+
+ let name;
+ $: name = $logins.get(sender);
+</script>
+
+<div class="card card-hover m-4 relative">
+ <span class="chip variant-soft sticky top-o left-0">
+ <!-- TODO: should this show up for only the first of a run? -->
+ @{name}:
+ </span>
+ {#each messages as { at, body }}
+ <Message {at} {body} />
+ {/each}
+</div>
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;
}