diff options
| author | Adam Soltys <[email protected]> | 2026-10-05 10:07:30 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-05 10:07:30 -0700 |
| commit | 0611d3b3b3e94089218da867e4530234f9248d3f (patch) | |
| tree | b823ab750741c1c88a1b03e99559aa5e4b016c15 | |
| parent | 3208a406171f88eb151b95ad8755ed2d847dcc24 (diff) | |
| download | coinosv3-0611d3b3b3e94089218da867e4530234f9248d3f.tar.gz coinosv3-0611d3b3b3e94089218da867e4530234f9248d3f.zip | |
Article cards: a dead cover falls back to the body's first picture, else no cover (no grey box)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YRC6aKhwAud231ot9FPmhi
| -rw-r--r-- | src/features/messages.js | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index 490ac6f..d18a0b2 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -6856,11 +6856,23 @@ export function messagesFeature(ctx) { h('div', { class: 'small muted' }, title || alt || t('noteForeignKind', { kind: ev.kind }))); } // An article as a card: its cover, title and summary; a tap opens it to read. + // Its cover: the image tag, else the first pictures in its body. Covers + // die (a Blossom host drops the file and no other server has it): a dead + // one is remembered for the session and the next candidate takes its + // place, or the card goes without — never a grey box with a broken icon. + const deadCovers = new Set(); + function articleCover(ev) { + const cands = [tagStr(ev, 'image').trim(), ...noteMediaUrls(ev.content).slice(0, 3)]; + return cands.find((u) => /^https:\/\/\S+$/.test(u) && !deadCovers.has(u)) || null; + } function articleCard(ev) { - const img = tagStr(ev, 'image'); + const img = articleCover(ev); const summary = tagStr(ev, 'summary'); return h('div', { class: 'quote-card clickable addr-article', onClick: (e) => { e.stopPropagation(); openNoteThread(ev); } }, - /^https:\/\//.test(img) ? h('img', { class: 'addr-cover', src: img, alt: '', loading: 'lazy' }) : null, + img ? h('img', { + class: 'addr-cover', src: img, alt: '', loading: 'lazy', 'data-key': 'cover:' + img, + onError: (e) => { deadCovers.add(img); e.target.style.display = 'none'; scheduleRepaint(); }, + }) : null, h('div', { class: 'row gap6', style: 'align-items:center;min-width:0' }, avatar(ev.pubkey, 'chat-avatar mini', false), h('span', { class: 'quote-name' }, displayName(ev.pubkey)), |
