aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/messages.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-28 22:25:57 -0700
committerAdam Soltys <[email protected]>2026-09-28 22:25:57 -0700
commit2bbff9ac91bf310f63216523cb418474ca64db64 (patch)
tree03caa49b71681537be5d8a5ee08f7d1cdcadfaf3 /src/features/messages.js
parentb1397fc6b0c6b91a0835911b9dd52c0b09432d56 (diff)
downloadcoinosv3-2bbff9ac91bf310f63216523cb418474ca64db64.tar.gz
coinosv3-2bbff9ac91bf310f63216523cb418474ca64db64.zip
A reloaded thread paints whole, quoted posts included, with no spinner.
The thread cache kept the replies but not the posts quoted inside them, so every reload showed "Fetching note…" until a relay answered. Quotes (of any kind — the one that showed it was a poll) are now saved with the thread and restored before the first paint. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/features/messages.js')
-rw-r--r--src/features/messages.js20
1 files changed, 19 insertions, 1 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index 8c8bb15..bf3c9db 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -5310,6 +5310,9 @@ export function messagesFeature(ctx) {
const evs = await queryOn(relays, { ids: [ref.id] }, 4500).catch(() => []);
c.ev = (evs || [])[0] || c.ev || null;
c.status = c.ev ? 'ready' : 'missing';
+ // the open thread quotes it: keep it with the thread for the next reload
+ const th = c.ev && ui.noteThread && threadCache.get(ui.noteThread.rootId);
+ if (th && th.root) persistThread(th);
scheduleRepaint();
})();
return c;
@@ -6525,7 +6528,21 @@ export function messagesFeature(ctx) {
const p = profiles.get(ev.pubkey);
if (p && (p.name || p.picture)) faces[ev.pubkey] = p;
}
- threadStore.save(c, c.focusId, faces, c.counts);
+ // quoted posts inside the thread ride along, so a reload paints them
+ // instead of a "Fetching note…" spinner
+ const quotes = [];
+ for (const ev of [c.root, ...c.replies]) {
+ for (const m of (ev.content || '').matchAll(/nostr:((?:note|nevent)1[a-z0-9]+)/gi)) {
+ const ref = parseNostrRef(m[1].toLowerCase());
+ const q = ref && ref.type === 'event' && quoted.get(ref.id);
+ if (q && q.ev) {
+ quotes.push(q.ev);
+ const p = profiles.get(q.ev.pubkey);
+ if (p && (p.name || p.picture)) faces[q.ev.pubkey] = p;
+ }
+ }
+ }
+ threadStore.save(c, c.focusId, faces, c.counts, quotes);
};
function persistThreadProfile(pk) {
const c = ui.noteThread && threadCache.get(ui.noteThread.rootId);
@@ -6597,6 +6614,7 @@ export function messagesFeature(ctx) {
}
}
}
+ for (const q of stored?.quotes || []) if (!quoted.get(q.id)?.ev) quoted.set(q.id, { status: 'ready', ev: q, at: Date.now() });
const rootId = stored?.rootId || requestedRootId;
c = { status: stored ? 'ready' : 'loading', rootId, focusId: seed.id,
root: stored?.root || (seed.id === rootId ? seed : null), replies: stored?.replies || [], counts: stored?.counts || {} };