From 4a5930fe2942586055ae804312b92d986eeefe1d Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sun, 31 May 2026 00:01:16 -0400 Subject: [PATCH] Deck preview: Prev/Next pager on unlocked decks too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous commits added paginated previews for the LOCKED premium state (creator-side multi-slide watermarked previews, buyer-side Prev/Next viewer). Adam reasonably asked for the same flippability after unlocking — there's no good reason a buyer who's paid (or a creator looking at their own work) should suddenly lose the ability to flip through slides. renderDeckPreviewDOM now branches: - compact OR <= 1 slide: keep the existing single-slide-1 + "N slides" badge render. This is the path feed cards, profile grids, and anything else passing { compact: true } take. - non-compact AND >1 slide (i.e. the community-browser preview pane): emit a Prev / Next pager that re-renders the chosen slide via composeSlideForDeck + renderCustomArtPreviewDOM, with a "Slide N of M" counter between the buttons. Same UX as the locked-premium pager so the transition pre- vs post-unlock feels continuous. Applies to every deck — premium or free, self-authored or someone else's — that lands in the preview pane. --- src/index.html | 67 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/src/index.html b/src/index.html index e4069c8..841b105 100644 --- a/src/index.html +++ b/src/index.html @@ -23230,16 +23230,63 @@ // reads as a deck at a glance. function renderDeckPreviewDOM(container, payload, opts = {}) { const slides = payload?.deck?.slides || []; - const first = slides[0]; - const composed = first - ? composeSlideForDeck(first, payload?.deck?.theme) - : { slide: { width: 1920, height: 1080, background: '#ffffff' }, layers: [] }; - renderCustomArtPreviewDOM(container, composed, opts); - if (!container.style.position) container.style.position = 'relative'; - const badge = document.createElement('div'); - badge.className = 'deckCountBadge'; - badge.textContent = slides.length === 1 ? '1 slide' : `${slides.length} slides`; - container.appendChild(badge); + const compact = !!opts.compact; + + // Compact thumbnails (feed cards, profile grid, etc.) keep the + // old single-slide-1 + badge render — pagination would be too + // fiddly at small size. Single-slide decks also use the simple + // path since there's nothing to page through. + if (compact || slides.length <= 1) { + const first = slides[0]; + const composed = first + ? composeSlideForDeck(first, payload?.deck?.theme) + : { slide: { width: 1920, height: 1080, background: '#ffffff' }, layers: [] }; + renderCustomArtPreviewDOM(container, composed, opts); + if (!container.style.position) container.style.position = 'relative'; + const badge = document.createElement('div'); + badge.className = 'deckCountBadge'; + badge.textContent = slides.length === 1 ? '1 slide' : `${slides.length} slides`; + container.appendChild(badge); + return; + } + + // Multi-slide deck in the preview pane → paginated viewer so the + // user (creator or buyer) can flip through every slide in the + // unlocked deck. Mirrors the locked-premium pager UX. + container.style.position = container.style.position || 'relative'; + const stage = document.createElement('div'); + stage.style.cssText = 'width:100%;display:flex;justify-content:center'; + const bar = document.createElement('div'); + bar.style.cssText = 'display:flex;align-items:center;justify-content:center;gap:10px;font-size:.9rem;color:var(--ink);padding:6px 0'; + const prev = document.createElement('button'); + prev.type = 'button'; + prev.textContent = '‹ Prev'; + prev.style.cssText = 'padding:4px 12px;cursor:pointer'; + const counter = document.createElement('span'); + counter.style.cssText = 'min-width:10em;text-align:center;font-variant-numeric:tabular-nums'; + const next = document.createElement('button'); + next.type = 'button'; + next.textContent = 'Next ›'; + next.style.cssText = 'padding:4px 12px;cursor:pointer'; + bar.append(prev, counter, next); + container.append(stage, bar); + let idx = 0; + function renderSlide() { + stage.innerHTML = ''; + const entry = slides[idx]; + const composed = composeSlideForDeck(entry, payload?.deck?.theme); + renderCustomArtPreviewDOM(stage, composed, { compact: false }); + counter.textContent = `Slide ${idx + 1} of ${slides.length}`; + } + prev.addEventListener('click', () => { + idx = (idx - 1 + slides.length) % slides.length; + renderSlide(); + }); + next.addEventListener('click', () => { + idx = (idx + 1) % slides.length; + renderSlide(); + }); + renderSlide(); } // Preview a standalone pixel-art design — the grid rendered crisp.