diff options
| author | Adam Soltys <[email protected]> | 2026-09-25 23:16:14 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-25 23:16:14 -0700 |
| commit | 1c388b3897ddd36c07f70b2b7f28467fd169e924 (patch) | |
| tree | 8b28f79721b7a3cbabf0e69cd601102b2f464dfa /src/features | |
| parent | 5511a1504e6496e8a2a100b6a6913c5e1eacf0de (diff) | |
| download | coinosv3-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/features')
| -rw-r--r-- | src/features/messages.js | 19 |
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 |
