summaryrefslogtreecommitdiff
path: root/ui/lib
diff options
context:
space:
mode:
authorKit La Touche <kit@transneptune.net>2024-11-08 21:43:59 -0500
committerKit La Touche <kit@transneptune.net>2024-11-08 21:43:59 -0500
commitcae917ee04c1b421107108d809f545cbf414cfae (patch)
tree0fe087c00b2caad7d316ee28fc9cf24eff7de836 /ui/lib
parentf31b4d8188ac7e38b6c42380649691c0e8e1e097 (diff)
parenta417c62edd4d3c07ba37b01835e89ed650489e09 (diff)
Merge branch 'main' into wip/pwa
Diffstat (limited to 'ui/lib')
-rw-r--r--ui/lib/components/ActiveChannel.svelte18
-rw-r--r--ui/lib/components/ChangePassword.svelte60
-rw-r--r--ui/lib/components/Invite.svelte5
-rw-r--r--ui/lib/components/Invites.svelte13
-rw-r--r--ui/lib/components/LogOut.svelte18
-rw-r--r--ui/lib/components/MessageInput.svelte2
-rw-r--r--ui/lib/components/MessageRun.svelte2
-rw-r--r--ui/lib/store/messages.svelte.js22
8 files changed, 111 insertions, 29 deletions
diff --git a/ui/lib/components/ActiveChannel.svelte b/ui/lib/components/ActiveChannel.svelte
index f939dbd..ba62d6c 100644
--- a/ui/lib/components/ActiveChannel.svelte
+++ b/ui/lib/components/ActiveChannel.svelte
@@ -4,16 +4,8 @@
let { messageRuns } = $props();
</script>
-<div class="container">
- {#each messageRuns as { sender, messages }}
- <div>
- <MessageRun {sender} {messages} />
- </div>
- {/each}
-</div>
-
-<style>
- .container {
- overflow: auto;
- }
-</style>
+{#each messageRuns as { sender, messages }}
+ <div>
+ <MessageRun {sender} {messages} />
+ </div>
+{/each}
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 @@
+<script>
+ import { changePassword } from '$lib/apiServer.js';
+
+ let currentPassword = $state(''),
+ newPassword = $state(''),
+ confirmPassword = $state(''),
+ pending = $state(false),
+ form;
+ let valid = $derived(newPassword === confirmPassword && newPassword !== currentPassword);
+ let disabled = $derived(pending || !valid);
+
+ async function onsubmit(event) {
+ event.preventDefault();
+ pending = true;
+ let response = await changePassword(currentPassword, newPassword);
+ switch (response.status) {
+ case 200:
+ form.reset();
+ break;
+ }
+ pending = false;
+ }
+</script>
+
+<form {onsubmit} bind:this={form}>
+ <label
+ >current password
+ <input
+ class="input"
+ name="currentPassword"
+ type="password"
+ placeholder="password"
+ bind:value={currentPassword}
+ />
+ </label>
+
+ <label
+ >new password
+ <input
+ class="input"
+ name="newPassword"
+ type="password"
+ placeholder="password"
+ bind:value={newPassword}
+ />
+ </label>
+
+ <label
+ >confirm new password
+ <input
+ class="input"
+ name="confirmPassword"
+ type="password"
+ placeholder="password"
+ bind:value={confirmPassword}
+ />
+ </label>
+
+ <button class="btn bg-orange-500 mt-4" type="submit" {disabled}>change password</button>
+</form>
diff --git a/ui/lib/components/Invite.svelte b/ui/lib/components/Invite.svelte
index 35e00b4..937c911 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));
</script>
-<button
- class="border-slate-500 border-solid border-2 font-bold p-1 rounded"
- use:clipboard={inviteUrl}>Copy</button
->
+<button class="btn bg-secondary-500" use:clipboard={inviteUrl}>copy</button>
<span data-clipboard="inviteUrl">{inviteUrl}</span>
diff --git a/ui/lib/components/Invites.svelte b/ui/lib/components/Invites.svelte
index cc14f3b..493bf1c 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 @@
}
</script>
-<ul>
+<form {onsubmit}>
+ <button class="btn bg-primary-500" type="submit">create invitation</button>
+</form>
+
+<ul class="mt-4">
{#each invites as invite}
- <li><Invite id={invite.id} /></li>
+ <li class="my-1"><Invite id={invite.id} /></li>
{/each}
</ul>
-<form onsubmit={onSubmit}>
- <button class="btn variant-filled" type="submit"> Create Invitation </button>
-</form>
diff --git a/ui/lib/components/LogOut.svelte b/ui/lib/components/LogOut.svelte
new file mode 100644
index 0000000..25dd5e9
--- /dev/null
+++ b/ui/lib/components/LogOut.svelte
@@ -0,0 +1,18 @@
+<script>
+ import { goto } from '$app/navigation';
+ import { logOut } from '$lib/apiServer.js';
+ import { currentUser } from '$lib/store';
+
+ async function onsubmit(event) {
+ event.preventDefault();
+ const response = await logOut();
+ if (200 <= response.status && response.status < 300) {
+ currentUser.update(() => null);
+ goto('/login');
+ }
+ }
+</script>
+
+<form {onsubmit}>
+ <button class="btn bg-orange-400" type="submit">log out</button>
+</form>
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"
></textarea>
<button
color="primary variant-filled-secondary"
diff --git a/ui/lib/components/MessageRun.svelte b/ui/lib/components/MessageRun.svelte
index b71e972..2e8c613 100644
--- a/ui/lib/components/MessageRun.svelte
+++ b/ui/lib/components/MessageRun.svelte
@@ -9,7 +9,7 @@
</script>
<div
- class="card m-4 px-4 py-1 relative"
+ class="card my-4 px-4 py-1 relative"
class:own-message={ownMessage}
class:other-message={!ownMessage}
>
diff --git a/ui/lib/store/messages.svelte.js b/ui/lib/store/messages.svelte.js
index 4630a40..c0db71b 100644
--- a/ui/lib/store/messages.svelte.js
+++ b/ui/lib/store/messages.svelte.js
@@ -11,7 +11,20 @@ export class Messages {
let parsedAt = new Date(at);
const message = { id, at: parsedAt, body };
- let runs = (this.channels[channel] ||= []);
+ // You might be thinking, can't this be
+ //
+ // let runs = (this.channels[channel] ||= []);
+ //
+ // Let me tell you, I thought that too. Javascript's semantics allow it. It
+ // didn't work - the first message in each channel was getting lost as the
+ // update to `this.channels` wasn't actually happening. I suspect this is
+ // due to the implementation of Svelte's `$state` rune, but I don't know it
+ // for sure.
+ //
+ // In any case, splitting the read and write up like this has the same
+ // semantics, and _works_. (This time, for sure!)
+ let runs = this.channels[channel] || [];
+
let currentRun = runs.slice(-1)[0];
if (currentRun === undefined) {
currentRun = { sender, messages: [message] };
@@ -19,8 +32,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] };
@@ -30,13 +42,15 @@ export class Messages {
}
}
+ this.channels[channel] = runs;
+
return this;
}
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;
}