aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-25 23:16:14 -0700
committerAdam Soltys <[email protected]>2026-09-25 23:16:14 -0700
commit1c388b3897ddd36c07f70b2b7f28467fd169e924 (patch)
tree8b28f79721b7a3cbabf0e69cd601102b2f464dfa /src
parent5511a1504e6496e8a2a100b6a6913c5e1eacf0de (diff)
downloadcoinosv3-1c388b3897ddd36c07f70b2b7f28467fd169e924.tar.gz
coinosv3-1c388b3897ddd36c07f70b2b7f28467fd169e924.zip
Feed: cached posts paint at once, never a spinner over them; the chat home prefetches the feed.
The boot gate hid everything, cached posts included, until the opening page's faces and pictures had decoded — seconds of spinner on a feed we already held. Cached rows now paint immediately as they are and take their prepared presentation once the warm-up lands (the container carries data-booting meanwhile). The relay fetch starts at once instead of after the warm-up; arrivals still wait at the door. Opening the chat home warms and refreshes the current feed, so the Feed tap opens on the latest posts. Co-Authored-By: Claude Fable 5.1 <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/features/messages.js19
1 files changed, 14 insertions, 5 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index 7af2259..7cd8ce3 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -4154,7 +4154,7 @@ export function messagesFeature(ctx) {
// An already warmed feed can paint synchronously on entry.
if (!c.booting) c.presentations.clear();
watchFeed();
- c.boot.then(() => refreshFeed({}, c));
+ refreshFeed({}, c);
try { window.scrollTo({ top: 0 }); } catch {}
render();
}
@@ -4374,7 +4374,8 @@ export function messagesFeature(ctx) {
// beat after the page painted, moving what you had started reading. Only
// a first load (nothing to disturb) or a rebuilt follow list goes straight in.
async function refreshFeed(opts = {}, c = feedNow()) {
- if (c.booting) await c.boot;
+ // the relays are asked at once; what they answer waits for the warm-up
+ // at the door (mergeFeed), not the asking
if (!feedHasQuery(feedDef(c.id))) { c.status = 'ready'; return; }
if (!opts.force && Date.now() - c.at < 30_000) return;
c.at = Date.now();
@@ -6759,13 +6760,18 @@ export function messagesFeature(ctx) {
const authors = feedAuthors(def);
const hasQuery = feedHasQuery(def);
prepareFeedAhead(c);
- const visible = c.booting ? [] : c.notes.filter((ev) => !hidden(ev));
+ // Never a bare spinner over posts we already hold: while the opening
+ // page's faces and pictures are still being decoded, the cached rows
+ // paint as they are (live profiles, pictures as they load) and take
+ // their settled presentation once the warm-up lands. The spinner is
+ // for a feed with nothing cached at all.
+ const visible = c.notes.filter((ev) => !hidden(ev));
// Every child keyed by its post, hairlines included, so the morph
// reconciles the list by post: a new one at the top is inserted as its
// own node; the rest keep theirs.
const rows = visible.slice(0, c.shown || FEED_PAGE).flatMap((ev, i) => [
i ? h('div', { 'data-key': 'hr:' + ev.id, style: 'height:1px;background:var(--border,rgba(128,128,128,.18));margin:0 -14px' }) : null,
- feedRow(c, ev),
+ c.booting ? keyed(noteRow(ev.pubkey, ev, displayName(ev.pubkey)), ev.id) : feedRow(c, ev),
]);
// Posts that went in above you while you were reading. A floating pill
// that says how many are up there; the tap takes you up to them.
@@ -6808,7 +6814,7 @@ export function messagesFeature(ctx) {
? h('div', { class: 'row gap6', style: 'justify-content:center;padding:12px 0' }, h('span', { class: 'spinner sm' }))
: !visible.length
? h('div', { class: 'small faint', style: 'text-align:center;padding:12px 0' }, t('feedEmpty'))
- : h('div', { class: 'card col notes-feed', style: 'gap:0' }, ...rows),
+ : h('div', { class: 'card col notes-feed', style: 'gap:0', 'data-booting': c.booting ? '1' : undefined }, ...rows),
// Older posts prepare offscreen; a background fetch should not add
// a spinner to an already readable feed.
@@ -7280,6 +7286,9 @@ export function messagesFeature(ctx) {
function homeView() {
if (myPubkeys().length) syncFollowSets().catch(() => {}); // lists made elsewhere join the feeds (throttled inside)
+ // The feed is a tap away from here: have it warmed and asked for before
+ // the tap, so it opens on the latest posts rather than a spinner.
+ if (myPubkeys().length) { try { const c = feedNow(); if (!c.booting) refreshFeed({}, c); } catch {} }
syncReports().catch(() => {}); // your follows' flags (throttled inside)
startDMs();
// Threads you've since replied to should stop being strangers to the