summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ui/lib/constants.js1
-rw-r--r--ui/lib/store.js6
-rw-r--r--ui/lib/store/channels.svelte.js60
-rw-r--r--ui/routes/(app)/ch/[channel]/+page.svelte12
4 files changed, 67 insertions, 12 deletions
diff --git a/ui/lib/constants.js b/ui/lib/constants.js
new file mode 100644
index 0000000..a707c4b
--- /dev/null
+++ b/ui/lib/constants.js
@@ -0,0 +1 @@
+export const STORE_KEY_CHANNELS_DATA = 'pilcrow:channelsData';
diff --git a/ui/lib/store.js b/ui/lib/store.js
index 47ebbc2..f408c0c 100644
--- a/ui/lib/store.js
+++ b/ui/lib/store.js
@@ -1,9 +1,13 @@
import { writable } from 'svelte/store';
+import { browser } from '$app/environment';
import { Channels } from '$lib/store/channels.svelte.js';
import { Messages } from '$lib/store/messages.svelte.js';
import { Logins } from '$lib/store/logins';
+// Get channelsList content from the local storage
+const channelsData = (browser && JSON.parse(localStorage.getItem('pilcrow:channelsData'))) || {};
+
export const currentUser = writable(null);
export const logins = writable(new Logins());
-export const channelsList = writable(new Channels());
+export const channelsList = writable(new Channels({ channelsData }));
export const messages = writable(new Messages());
diff --git a/ui/lib/store/channels.svelte.js b/ui/lib/store/channels.svelte.js
index c82f9aa..49cc31c 100644
--- a/ui/lib/store/channels.svelte.js
+++ b/ui/lib/store/channels.svelte.js
@@ -1,4 +1,5 @@
import { DateTime } from 'luxon';
+import { STORE_KEY_CHANNELS_DATA } from '$lib/constants';
const EPOCH_STRING = '1970-01-01T00:00:00Z';
// For reasons unclear to me, a straight up class definition with a constructor
@@ -10,24 +11,79 @@ const EPOCH_STRING = '1970-01-01T00:00:00Z';
// Emphasis on "simple object".
// --Kit
function makeChannelObject({ id, name, draft = '', lastReadAt = null, scrollPosition = null }) {
+ let lastReadAtParsed;
+ if (Boolean(lastReadAt)) {
+ if (typeof lastReadAt === "string") {
+ lastReadAtParsed = DateTime.fromISO(lastReadAt);
+ } else {
+ lastReadAtParsed = lastReadAt;
+ }
+ } else {
+ lastReadAtParsed = DateTime.fromISO(EPOCH_STRING);
+ }
return {
id,
name,
- lastReadAt: lastReadAt || DateTime.fromISO(EPOCH_STRING),
+ lastReadAt: lastReadAtParsed,
draft,
scrollPosition
};
}
+function mergeLocalData(remoteData, currentData) {
+ let currentDataObj = currentData.reduce(
+ (acc, cur) => {
+ acc[cur.id] = cur;
+ return acc;
+ },
+ {}
+ );
+ const ret = remoteData.map(
+ (ch) => {
+ const newCh = makeChannelObject(ch);
+ if (Boolean(currentDataObj[ch.id])) {
+ newCh.lastReadAt = currentDataObj[ch.id].lastReadAt;
+ }
+ return newCh;
+ }
+ );
+ return ret;
+}
+
export class Channels {
channels = $state([]);
+ constructor({ channelsData }) {
+ this.channels = channelsData.map(makeChannelObject);
+ // On channel edits (inc 'last read' ones), write out to localstorage?
+ }
+
+ writeOutToLocalStorage() {
+ localStorage.setItem(
+ STORE_KEY_CHANNELS_DATA,
+ JSON.stringify(this.channels)
+ );
+ }
+
+ 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();
+ }
+ }
+
getChannel(channelId) {
return this.channels.filter((ch) => ch.id === channelId)[0] || null;
}
setChannels(channels) {
- this.channels = channels.map(makeChannelObject);
+ // This gets called, among other times, when the page is first loaded, with
+ // server-sent data from the `boot` endpoint. That needs to be merged with
+ // locally stored data!
+ this.channels = mergeLocalData(channels, this.channels);
this.sort();
return this;
}
diff --git a/ui/routes/(app)/ch/[channel]/+page.svelte b/ui/routes/(app)/ch/[channel]/+page.svelte
index dbdb507..d64a8c9 100644
--- a/ui/routes/(app)/ch/[channel]/+page.svelte
+++ b/ui/routes/(app)/ch/[channel]/+page.svelte
@@ -33,16 +33,10 @@
}
function setLastRead() {
- const channelObject = $channelsList.getChannel(channel);
const lastInView = getLastVisibleMessage();
- if (!channelObject || !lastInView) {
- return;
- }
- const at = DateTime.fromISO(lastInView.dataset.at);
- // 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;
+ if (lastInView) {
+ const at = DateTime.fromISO(lastInView.dataset.at);
+ $channelsList.updateLastReadAt(channel, at);
}
}