aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-28 22:53:37 -0700
committerAdam Soltys <[email protected]>2026-09-28 22:53:37 -0700
commit86d5609a188ce4dae248d1b56c4563bae299af31 (patch)
treeba9dd36426a724a3bc3b56ac631d34b0700eca56 /src
parent06df23884d69bb2f46a6deeb9b05722d5ba45b53 (diff)
downloadcoinosv3-86d5609a188ce4dae248d1b56c4563bae299af31.tar.gz
coinosv3-86d5609a188ce4dae248d1b56c4563bae299af31.zip
A thread that starts from a poll (or any non-kind-1 post) is cached too, so a reload paints its replies at once.
The thread store accepted only kind 1 and silently skipped saving a thread rooted in a kind 1068 poll — every refresh then waited on the relays behind a spinner. Also guard the profile Back listener for window-less tests. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Du1qT1wbkYwYK6zkGH79Rp
Diffstat (limited to 'src')
-rw-r--r--src/features/messages.js2
-rw-r--r--src/thread-cache.js7
2 files changed, 6 insertions, 3 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index dd31f46..2a3b400 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -3025,7 +3025,7 @@ export function messagesFeature(ctx) {
// reader deep in that person's posts, which read as a thread. Back (a
// popstate) puts them where they were on the page they left.
const profReturn = []; // [{ pk, y }] per profile opened, newest last
- window.addEventListener('popstate', () => {
+ if (typeof window !== 'undefined') window.addEventListener('popstate', () => {
const top = profReturn[profReturn.length - 1];
if (!top || ui.profilePk === top.pk) return;
profReturn.pop();
diff --git a/src/thread-cache.js b/src/thread-cache.js
index 0606f12..fca64e6 100644
--- a/src/thread-cache.js
+++ b/src/thread-cache.js
@@ -6,13 +6,16 @@ const MAX_THREADS = 12;
const MAX_EVENTS = 160;
const MAX_QUOTES = 24; // posts quoted inside the thread, so a reload paints them too
const MAX_BYTES = 1_000_000; // JSON code units; at most about 2 MB in storage
-const validNote = (e) => e?.kind === 1 && typeof e.id === 'string'
+// Any kind: a thread can hang off a poll (1068), a picture (20), a comment
+// (1111)… — requiring kind 1 left those threads uncached, so every reload
+// sat on a spinner while the relays answered.
+const validNote = (e) => Number.isSafeInteger(e?.kind) && e.kind >= 0 && typeof e.id === 'string'
&& /^[0-9a-f]{64}$/.test(e.id) && typeof e.pubkey === 'string'
&& /^[0-9a-f]{64}$/.test(e.pubkey) && typeof e.content === 'string'
&& Number.isFinite(e.created_at) && Array.isArray(e.tags)
&& e.tags.every((t) => Array.isArray(t) && t.every((v) => typeof v === 'string'));
// A quote can be any kind of event (a poll, an article…), not only a note.
-const validQuote = (e) => Number.isSafeInteger(e?.kind) && e.kind >= 0 && validNote({ ...e, kind: 1 });
+const validQuote = validNote;
const savedNote = ({ id, pubkey, kind, created_at, content, tags }) => ({ id, pubkey, kind, created_at, content, tags });
const savedProfile = (p) => {
if (!p || typeof p !== 'object') return null;