mirror of
https://github.com/PR0M3TH3AN/Artstr-Studio.git
synced 2026-10-29 01:30:39 +00:00
Feed cards: rebuild when the author's profile arrives (so the Tip button shows)
Adam reported the ⚡ Tip button was missing from cards in the template browser even though the author had a Lightning address. Root cause: diffWallCards reuses an existing card by event id and never rebuilds it. The author's profile is fetched AFTER the template events in fetchFeedAndReactions (the enrichment step), so the first card render runs when _feedCache.profiles[author] is still undefined. makeFeedCardTipButton returns null in that case (no lud16 → no tip button). When the profile arrived later, notifyFeedProgress kicked off a rerender, but diffWallCards reused the tip-less DOM card unchanged, and the button never appeared. Fix - buildFeedCardForRow now stamps each card with a small string encoding the row's mutable view-state: profile-has-LN flag, reaction count, zap-total bucket, premium decrypted/locked state, broken-preview flag. - diffWallCards reads the stamp on the existing card and the fresh stamp on the new row. If they differ, it rebuilds the card and replaceWith() into place. Cards built through paths that don't set a stamp (legacy code paths) are reused as before — backwards-compatible. Same mechanism naturally handles other "card refreshes when…" cases that previously didn't: when zap receipts stream in (zap bucket changes), when a reaction count ticks up (rx changes), when a premium row gets unlocked (pd/pg flip), when a previously- broken image gets retried and works (b flips). Tested via CDP: card built with empty profiles cache → no tip button, stamp ln=0. Profile pushed into the cache with lud16 → rerender → stamp ln=1, card rebuilt, "⚡ Tip" button now present. The same root cause was theoretically present in the preview pane and profile page, but in practice those open AFTER the user has been on the feed for a few seconds (profiles already loaded), so this card-side fix is the user-visible one. If the preview pane ever lands first, the openDesignPreview path already reads the latest _feedCache.profiles every time, so it picks up the LN address from the next render. Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
34d5918002
commit
1ea611b44e
1 file changed
+31
@@ -21117,6 +21117,24 @@
|
||||
}
|
||||
|
||||
// Card factory used by both the initial render and the streaming-update diff.
|
||||
// Encode the bits of a row that affect what gets drawn into the card,
|
||||
// so diffWallCards can detect when an existing card needs to be
|
||||
// rebuilt rather than reused. Most importantly: the author's profile
|
||||
// (and therefore the Tip button's presence) arrives async AFTER the
|
||||
// initial card render — without this stamp, the card stays in its
|
||||
// tip-less state forever.
|
||||
function _feedCardStateStamp(row) {
|
||||
const pk = row?.e?.pubkey || '';
|
||||
const profile = _feedCache.profiles?.[pk] || null;
|
||||
const hasLn = !!(profile?.lud16 || profile?.lud06);
|
||||
const reactions = row?.reactions || 0;
|
||||
const zapBucket = Math.floor((zapTotalForEvent(row?.e?.id || '') || 0) / 1000);
|
||||
const premiumDecrypted = !!(row?.premium && row.premium.decrypted);
|
||||
const premiumGated = !!(row?.zapGate && row.zapGate.gated && !row.zapGate.unlocked);
|
||||
const broken = isPreviewBroken(row) ? 1 : 0;
|
||||
return `ln=${hasLn ? 1 : 0}|rx=${reactions}|z=${zapBucket}|pd=${premiumDecrypted ? 1 : 0}|pg=${premiumGated ? 1 : 0}|b=${broken}`;
|
||||
}
|
||||
|
||||
function buildFeedCardForRow(row) {
|
||||
const card = buildFeedCard(row, () => {
|
||||
if (tryDesignLayerImportRow(row)) return;
|
||||
@@ -21135,6 +21153,7 @@
|
||||
$('nostrModal').classList.remove('open');
|
||||
});
|
||||
card.dataset.eventId = row.e?.id || '';
|
||||
card.dataset.cardStamp = _feedCardStateStamp(row);
|
||||
return card;
|
||||
}
|
||||
|
||||
@@ -21158,6 +21177,18 @@
|
||||
let card = existing.get(id);
|
||||
if (card) {
|
||||
existing.delete(id);
|
||||
// Rebuild the card if its state stamp changed (e.g. the author's
|
||||
// profile finally arrived → tip button now applicable). The
|
||||
// stamp is set by buildFeedCardForRow; absent on cards built
|
||||
// through a different path → always reuse those, to preserve
|
||||
// legacy behaviour.
|
||||
const currentStamp = card.dataset?.cardStamp;
|
||||
const newStamp = (typeof _feedCardStateStamp === 'function') ? _feedCardStateStamp(row) : currentStamp;
|
||||
if (currentStamp && newStamp && currentStamp !== newStamp) {
|
||||
const fresh = buildCardFn(row);
|
||||
card.replaceWith(fresh);
|
||||
card = fresh;
|
||||
}
|
||||
} else {
|
||||
card = buildCardFn(row);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user