diff options
Diffstat (limited to 'src/features/messages.js')
| -rw-r--r-- | src/features/messages.js | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index 030d9fa..a35c0da 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -9309,7 +9309,7 @@ export function messagesFeature(ctx) { }; return h('div', { class: 'col live-page', style: 'gap:12px' }, ctx.brandHeader(!ui.pubProf && wallet.loaded), - h('div', { class: 'card col', style: 'gap:10px' }, + h('div', { class: 'card col live-main', style: 'gap:10px' }, h('div', { class: 'row gap6', style: 'align-items:center' }, mine ? h('button', { class: 'iconbtn chat-back', onClick: () => { if (confirm(t('goLiveEndAsk'))) endBroadcast(); } }, '‹') : backBtn(() => { ui.liveStream = null; }), @@ -9361,7 +9361,7 @@ export function messagesFeature(ctx) { watchersRow(w), liveSummary(ev) ? h('div', { class: 'small muted', style: 'white-space:pre-wrap;overflow-wrap:anywhere' }, liveSummary(ev).slice(0, 600)) : null, ui.liveReport && ui.liveReport.a === s.a ? liveReportPanel(ev) : null), - h('div', { class: 'card col', style: 'gap:8px' }, + h('div', { class: 'card col live-chat-card', style: 'gap:8px' }, h('div', { class: 'small muted' }, t('liveChat')), h('div', { class: 'live-chat', 'data-key': 'live-chat:' + s.a, @@ -13498,7 +13498,9 @@ export function messagesFeature(ctx) { const key = mediaIdxKey(feedId); let r = mediaIdx.get(key); if (r) return r; - r = { key, replies: !!(feedDef(feedId) || {}).replies, images: new Map(), videos: new Map(), articles: new Map(), art: { until: 0, end: 0, empty: 0, head: 0 }, checked: new Set(), until: 0, end: false, empty: 0, loaded: false }; + const order = () => ({ seq: new Map(), top: 0, bottom: 0, newest: 0 }); + r = { key, replies: !!(feedDef(feedId) || {}).replies, images: new Map(), videos: new Map(), articles: new Map(), art: { until: 0, end: 0, empty: 0, head: 0 }, checked: new Set(), until: 0, end: false, empty: 0, loaded: false, + order: { images: order(), videos: order() } }; mediaIdx.set(key, r); loadMediaIndex(key).then(async (rec) => { if (rec) { @@ -14037,7 +14039,27 @@ export function messagesFeature(ctx) { out.push({ ev, url }); } } - return out; + return settledOrder(r, kind, out); + } + // The grid's order holds for the session (Adam, 2026-10-23: clips the + // crawl found landed in the middle of the grid, above an older tail the + // index had from before, and the tiles already there jumped): what it + // shows first is newest first, and whatever turns up after goes under what + // is already there, in its own date order. Only a post newer than the top + // tile goes above it. Nothing is settled until the kept index is in, so + // the first paint is one date order, not two batches. + function settledOrder(r, kind, out) { + if (!r.loaded) return out; + const o = r.order[kind]; + const key = (it) => it.ev.id + '|' + it.url; + const fresh = out.filter((it) => !o.seq.has(key(it))); + if (fresh.length) { + const above = o.seq.size ? fresh.filter((it) => it.ev.created_at > o.newest) : []; + for (const it of above.reverse()) o.seq.set(key(it), --o.top); + for (const it of fresh) if (!o.seq.has(key(it))) o.seq.set(key(it), ++o.bottom); + for (const it of fresh) if (it.ev.created_at > o.newest) o.newest = it.ev.created_at; + } + return out.sort((a, b) => o.seq.get(key(a)) - o.seq.get(key(b))); } // The feed's pictures (or clips) in reading order — every one of a post // before the next post's — for the pager opened from one in the feed: the |
