summaryrefslogtreecommitdiff
path: root/ui/lib/state/remote
diff options
context:
space:
mode:
Diffstat (limited to 'ui/lib/state/remote')
-rw-r--r--ui/lib/state/remote/channels.svelte.js22
-rw-r--r--ui/lib/state/remote/logins.svelte.js18
-rw-r--r--ui/lib/state/remote/messages.svelte.js52
-rw-r--r--ui/lib/state/remote/state.svelte.js89
4 files changed, 181 insertions, 0 deletions
diff --git a/ui/lib/state/remote/channels.svelte.js b/ui/lib/state/remote/channels.svelte.js
new file mode 100644
index 0000000..64edb09
--- /dev/null
+++ b/ui/lib/state/remote/channels.svelte.js
@@ -0,0 +1,22 @@
+import { SvelteMap } from 'svelte/reactivity';
+
+export class Channels {
+ all = $state();
+
+ static boot(channels) {
+ const all = new SvelteMap(channels.map((channel) => [channel.id, channel]));
+ return new Channels({ all });
+ }
+
+ constructor({ all }) {
+ this.all = all;
+ }
+
+ add({ id, name }) {
+ this.all.set(id, { id, name });
+ }
+
+ remove(id) {
+ this.all.delete(id);
+ }
+}
diff --git a/ui/lib/state/remote/logins.svelte.js b/ui/lib/state/remote/logins.svelte.js
new file mode 100644
index 0000000..d19068d
--- /dev/null
+++ b/ui/lib/state/remote/logins.svelte.js
@@ -0,0 +1,18 @@
+import { SvelteMap } from 'svelte/reactivity';
+
+export class Logins {
+ all = $state();
+
+ static boot(logins) {
+ const all = new SvelteMap(logins.map((login) => [login.id, login]));
+ return new Logins({ all });
+ }
+
+ constructor({ all }) {
+ this.all = all;
+ }
+
+ add({ id, name }) {
+ this.all.set(id, { id, name });
+ }
+}
diff --git a/ui/lib/state/remote/messages.svelte.js b/ui/lib/state/remote/messages.svelte.js
new file mode 100644
index 0000000..576a74e
--- /dev/null
+++ b/ui/lib/state/remote/messages.svelte.js
@@ -0,0 +1,52 @@
+import { DateTime } from 'luxon';
+import { render } from '$lib/markdown.js';
+
+class Message {
+ static boot({ id, at, channel, sender, body }) {
+ return new Message({
+ id,
+ at: DateTime.fromISO(at),
+ channel,
+ sender,
+ body,
+ renderedBody: render(body)
+ });
+ }
+
+ constructor({ id, at, channel, sender, body, renderedBody }) {
+ this.id = id;
+ this.at = at;
+ this.channel = channel;
+ this.sender = sender;
+ this.body = body;
+ this.renderedBody = renderedBody;
+ }
+
+ resolve(get) {
+ const { sender, ...rest } = this;
+ return new Message({ sender: get.sender(sender), ...rest });
+ }
+}
+
+export class Messages {
+ all = $state([]);
+
+ static boot(messages) {
+ const all = messages.map(Message.boot);
+ return new Messages({ all });
+ }
+
+ constructor({ all }) {
+ this.all = all;
+ }
+
+ add({ id, at, channel, sender, body }) {
+ const message = Message.boot({ id, at, channel, sender, body });
+ this.all.push(message);
+ }
+
+ remove(id) {
+ const index = this.all.findIndex((message) => message.id === id);
+ this.all.splice(index, 1);
+ }
+}
diff --git a/ui/lib/state/remote/state.svelte.js b/ui/lib/state/remote/state.svelte.js
new file mode 100644
index 0000000..c4daf17
--- /dev/null
+++ b/ui/lib/state/remote/state.svelte.js
@@ -0,0 +1,89 @@
+import { Logins } from './logins.svelte.js';
+import { Channels } from './channels.svelte.js';
+import { Messages } from './messages.svelte.js';
+
+export class State {
+ currentUser = $state();
+ logins = $state();
+ channels = $state();
+ messages = $state();
+
+ static boot({ currentUser, logins, channels, messages, resumePoint }) {
+ return new State({
+ currentUser,
+ logins: Logins.boot(logins),
+ channels: Channels.boot(channels),
+ messages: Messages.boot(messages),
+ resumePoint
+ });
+ }
+
+ constructor({ currentUser, logins, channels, messages, resumePoint }) {
+ this.currentUser = currentUser;
+ this.logins = logins;
+ this.channels = channels;
+ this.messages = messages;
+ this.resumePoint = resumePoint;
+ }
+
+ onEvent(event) {
+ switch (event.type) {
+ case 'channel':
+ return this.onChannelEvent(event);
+ case 'login':
+ return this.onLoginEvent(event);
+ case 'message':
+ return this.onMessageEvent(event);
+ }
+ }
+
+ onChannelEvent(event) {
+ switch (event.event) {
+ case 'created':
+ return this.onChannelCreated(event);
+ case 'deleted':
+ return this.onChannelDeleted(event);
+ }
+ }
+
+ onChannelCreated(event) {
+ const { id, name } = event;
+ this.channels.add({ id, name });
+ }
+
+ onChannelDeleted(event) {
+ const { id } = event;
+ this.channels.remove(id);
+ }
+
+ onLoginEvent(event) {
+ switch (event.event) {
+ case 'created':
+ return this.onLoginCreated(event);
+ }
+ }
+
+ onLoginCreated(event) {
+ const { id, name } = event;
+ this.logins.add({ id, name });
+ }
+
+ onMessageEvent(event) {
+ switch (event.event) {
+ case 'sent':
+ return this.onMessageSent(event);
+ case 'deleted':
+ return this.onMessageDeleted(event);
+ }
+ }
+
+ onMessageSent(event) {
+ const { id, at, channel, sender, body } = event;
+ this.messages.add({ id, at, channel, sender, body });
+ }
+
+ onMessageDeleted(event) {
+ const { id } = event;
+ this.messages.remove(id);
+ }
+}