summaryrefslogtreecommitdiff
path: root/ui/lib/store
diff options
context:
space:
mode:
Diffstat (limited to 'ui/lib/store')
-rw-r--r--ui/lib/store/channels.svelte.js115
-rw-r--r--ui/lib/store/logins.js22
-rw-r--r--ui/lib/store/messages.svelte.js79
3 files changed, 0 insertions, 216 deletions
diff --git a/ui/lib/store/channels.svelte.js b/ui/lib/store/channels.svelte.js
deleted file mode 100644
index 9058d86..0000000
--- a/ui/lib/store/channels.svelte.js
+++ /dev/null
@@ -1,115 +0,0 @@
-import { DateTime } from 'luxon';
-import { get } from 'svelte/store';
-import { STORE_KEY_CHANNELS_DATA, EPOCH_STRING } from '$lib/constants';
-
-export class Channels {
- channels = $state([]);
-
- constructor({ channelsMetaList }) {
- // This is the state wrapper around the channels meta object. Dammit.
- this.channelsMetaList = channelsMetaList;
- }
-
- getChannel(channelId) {
- return this.channels.filter((ch) => ch.id === channelId)[0] || null;
- }
-
- setChannels(channels) {
- // Because this is called at initialization, we need to initialize the matching meta:
- get(this.channelsMetaList).ensureChannels(channels);
- this.channels = channels;
- this.sort();
- return this;
- }
-
- addChannel(id, name) {
- const newChannel = { id, name };
- this.channels = [...this.channels, newChannel];
- get(this.channelsMetaList).initializeChannel(newChannel);
- this.sort();
- return this;
- }
-
- deleteChannel(id) {
- const channelIndex = this.channels.map((e) => e.id).indexOf(id);
- if (channelIndex !== -1) {
- this.channels.splice(channelIndex, 1);
- }
- return this;
- }
-
- sort() {
- this.channels.sort((a, b) => {
- if (a.name < b.name) {
- return -1;
- } else if (a.name > b.name) {
- return 1;
- }
- return 0;
- });
- }
-}
-
-export class ChannelsMeta {
- // Store channelId -> { draft = '', lastReadAt = null, scrollPosition = null }
- channelsMeta = $state({});
-
- constructor({ channelsMetaData }) {
- const channelsMeta = objectMap(channelsMetaData, (ch) => {
- let lastReadAt = ch.lastReadAt;
- if (typeof lastReadAt === 'string') {
- lastReadAt = DateTime.fromISO(lastReadAt);
- }
- if (!Boolean(lastReadAt)) {
- lastReadAt = DateTime.fromISO(EPOCH_STRING);
- }
- return {
- ...ch,
- lastReadAt
- };
- });
- this.channelsMeta = channelsMeta;
- }
-
- writeOutToLocalStorage() {
- localStorage.setItem(STORE_KEY_CHANNELS_DATA, JSON.stringify(this.channelsMeta));
- }
-
- updateLastReadAt(channelId, at) {
- const channelObject = this.getChannel(channelId);
- // Do it this way, rather than with Math.max tricks, to avoid assignment
- // when we don't need it, to minimize reactive changes:
- if (at > channelObject?.lastReadAt) {
- channelObject.lastReadAt = at;
- this.writeOutToLocalStorage();
- }
- }
-
- ensureChannels(channelsList) {
- channelsList.forEach(({ id }) => {
- this.initializeChannel(id);
- });
- }
-
- initializeChannel(channelId) {
- if (!this.channelsMeta[channelId]) {
- const channelData = {
- lastReadAt: null,
- draft: '',
- scrollPosition: null
- };
- this.channelsMeta[channelId] = channelData;
- }
- }
-
- getChannel(channelId) {
- return this.channelsMeta[channelId] || null;
- }
-}
-
-function objectMap(object, mapFn) {
- return Object.keys(object).reduce((result, key) => {
- result[key] = mapFn(object[key]);
- return result;
- }, {});
-}
diff --git a/ui/lib/store/logins.js b/ui/lib/store/logins.js
deleted file mode 100644
index d449b3a..0000000
--- a/ui/lib/store/logins.js
+++ /dev/null
@@ -1,22 +0,0 @@
-export class Logins {
- constructor() {
- this.logins = {};
- }
-
- addLogin(id, name) {
- this.logins[id] = name;
- return this;
- }
-
- setLogins(logins) {
- this.logins = {};
- for (let { id, name } of logins) {
- this.addLogin(id, name);
- }
- return this;
- }
-
- get(id) {
- return this.logins[id];
- }
-}
diff --git a/ui/lib/store/messages.svelte.js b/ui/lib/store/messages.svelte.js
deleted file mode 100644
index dadade6..0000000
--- a/ui/lib/store/messages.svelte.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import { DateTime } from 'luxon';
-import { marked } from 'marked';
-import DOMPurify from 'dompurify';
-
-const RUN_COALESCE_MAX_INTERVAL = 10 /* min */ * 60 /* sec */ * 1000; /* ms */
-
-export class Messages {
- channels = $state({}); // Mapping<ChannelId, Message>
-
- inChannel(channel) {
- return this.channels[channel] || [];
- }
-
- addMessage(channel, id, { at, sender, body }) {
- let parsedAt = DateTime.fromISO(at);
- let renderedBody = DOMPurify.sanitize(marked.parse(body, { breaks: true }));
- const message = { id, at: parsedAt, body, renderedBody };
-
- // 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] };
- 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);
- }
- }
-
- 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 });
- }
- 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;
- }
-}