diff options
| author | Adam Soltys <[email protected]> | 2026-10-07 08:34:13 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-07 08:34:13 -0700 |
| commit | 6d288aeb194d2765282cf9fd72bd1f5fdd747a71 (patch) | |
| tree | 9ea340ae990af7e675d0871a80d4d3cdd9b0ac4a /src/features | |
| parent | a6bae186071e7e07136a37f63864d0bf578edd16 (diff) | |
| parent | d04f10db5e3c007db2cd8a5f9e12eff55bc1c653 (diff) | |
| download | coinosv3-6d288aeb194d2765282cf9fd72bd1f5fdd747a71.tar.gz coinosv3-6d288aeb194d2765282cf9fd72bd1f5fdd747a71.zip | |
Merge branch 'worktree-agent-ab051145d709af327'
Diffstat (limited to 'src/features')
| -rw-r--r-- | src/features/messages.js | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index 899ee1d..bbec23e 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -645,7 +645,13 @@ export function messagesFeature(ctx) { if (!wallet.mnemonic && !wallet.xprv && !wallet.xpub) return; profilesWarmed = true; const cached = profilesDisk(); - for (const [pk, p] of Object.entries(cached)) if (!profiles.has(pk)) profiles.set(pk, p); + // (a row asked for before the cache opened — still loading, or a miss + // while offline — gives way to the remembered face; a kind 0 that + // really named nothing keeps its say) + for (const [pk, p] of Object.entries(cached)) { + const cur = profiles.get(pk); + if (!cur || (!cur.name && !cur.picture && !cur.eventAt)) profiles.set(pk, p); + } // someone known to have no face paints their punk from the first frame, // instead of a blank circle that turns into one when the relays answer for (const [pk, t] of Object.entries(facelessDisk())) { @@ -1176,6 +1182,10 @@ export function messagesFeature(ctx) { folded: null, controlEntries: [], guestEntries: [], + // the wraps this room opened: a room rebuilt with fresher keys hands + // them back to seenWraps, or its new subscription would skip the + // replay and fold without them + wrapIds: new Set(), members: new Map(), byChannel: new Map(), edits: new Map(), @@ -1251,6 +1261,7 @@ export function messagesFeature(ctx) { subscribeOn(room.relays, { kinds: [1059], authors: [room.control.pk], limit: 500 }, (wrap) => { if (seenWraps.has(wrap.id)) return; seenWraps.add(wrap.id); + room.wrapIds.add(wrap.id); openWrapBg(wrap, room.control, (opened) => { if (!opened || opened.rumor.kind !== 3308) return; room.controlEntries.push(opened); @@ -1260,6 +1271,7 @@ export function messagesFeature(ctx) { subscribeOn(room.relays, { kinds: [1059], authors: [room.guestbook.pk], limit: 500 }, (wrap) => { if (seenWraps.has(wrap.id)) return; seenWraps.add(wrap.id); + room.wrapIds.add(wrap.id); openWrapBg(wrap, room.guestbook, (opened) => { if (!opened) return; room.guestEntries.push(opened); @@ -1286,6 +1298,7 @@ export function messagesFeature(ctx) { const u = subscribeOn(room.relays, { kinds: [1059, 21059], authors: [stream.pk], limit: 200 }, (wrap) => { if (seenWraps.has(wrap.id)) return; seenWraps.add(wrap.id); + room.wrapIds.add(wrap.id); openWrapBg(wrap, stream, (opened) => { if (!opened) return; onChat(room, id, opened); @@ -2140,7 +2153,11 @@ export function messagesFeature(ctx) { // public data, and Back lands on the app's own front door. if (urlFeed) { ui.pubProf = true; ui.chatOpen = true; ui.msgView = 'feed'; + // hold the frame until the URL's feed is chosen: painted a tick early, + // the feed view would open (and fetch) the default feed first + ui.pubFeedPending = true; setTimeout(() => { + ui.pubFeedPending = null; if (openFeedUrl(urlFeed.path, urlFeed.search)) return; ui.pubProf = null; ui.chatOpen = false; ui.msgView = null; // not a feed we know: the front door render(); @@ -2506,7 +2523,11 @@ export function messagesFeature(ctx) { if (!newer && !fill) continue; Object.assign(have, jmSubset(jm), { name: have.name || jm.name, relays: have.relays && have.relays.length ? have.relays : jm.relays }); const stale = rooms.get(have.community_id); // rebuilt with the new keys on next open - if (stale) { for (const u of stale.unsubs || []) { try { u(); } catch {} } rooms.delete(have.community_id); } + if (stale) { + for (const u of stale.unsubs || []) { try { u(); } catch {} } + for (const id of stale.wrapIds || []) seenWraps.delete(id); + rooms.delete(have.community_id); + } changed = true; continue; } @@ -4789,8 +4810,9 @@ export function messagesFeature(ctx) { const curateFeed = (evs) => { const lang = getLang(); return evs.filter((e) => !isMachinePost(e.content) && inLanguage(e.content, lang)); }; async function popularPass(extra, merge, c, def) { // Only the default public feed shares a snapshot. Custom relays and older - // pages keep their own queries. A static/offline install falls back quickly. - if (extra.until == null && !feedRelays(def)) { + // pages keep their own queries. A static/offline install falls back quickly; + // the single file opened from a disk has no server to ask at all. + if (extra.until == null && !feedRelays(def) && /^https?:$/.test(location.protocol)) { try { const response = await fetch('/api/feed', { signal: AbortSignal.timeout(1500) }); if (!response.ok || !response.headers.get('content-type')?.includes('application/json')) throw new Error('No feed cache'); @@ -12816,6 +12838,7 @@ export function messagesFeature(ctx) { ctx.brandHeader(false), h('div', { class: 'card row gap6', style: 'justify-content:center;align-items:center;padding:16px' }, h('span', { class: 'spinner sm' }), h('span', { class: 'small faint' }, t('noteRefLoading')))); + if (ui.pubFeedPending) return h('div', { class: 'col', style: 'gap:16px' }, ctx.brandHeader(false)); if (ui.pubProfPending) return h('div', { class: 'col', style: 'gap:16px' }, ctx.brandHeader(false), h('div', { class: 'card col', style: 'gap:12px' }, |
