From 40c0df6fee7c706c7d4c38878a2bc8290aff45e1 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Mon, 18 May 2026 17:35:04 -0400 Subject: [PATCH] Publish-confirm modal, in-app toasts, Zapped tab fix, dc-designer layers, sticky-meta fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Publish confirm modal: - Replaces the bare confirm() before posting to Nostr. Shows a live preview of the design (uses the same renderers as the design browser), a metadata table (Type, Title, Category, Language, IMDb / UPC / TheTVDB / MusicBrainz when filled, Author), and an inline edit warning when the user is updating an existing design. - Pre-flight validation surfaces missing title/category/artwork before opening the modal; publish errors render inline so the user can retry without losing context. - ESC / × / backdrop close it; same modal-z-stack treatment as the other overlays so it lands on top. Toast system: - Replaces every native alert() across the app (41 callsites) with in-app toasts. toastError flags failures with a red border; toastSuccess paints publish/copy confirmations with the accent color. Toasts auto-dismiss (~3.5 s info/success, ~5.5 s error) and stack at the bottom-right with a manual close button. Project metadata stickiness: - Clear all images, Clear disc, and Clear jewel handlers now also reset state.meta (preserving the user's omdbApiKey) and re-sync the input fields. Previously, title / IMDb / UPC / TheTVDB / MusicBrainz carried over from a cleared project into the next one. - The two existing reset helpers were missing the newer identifier fields (UPC, TheTVDB, MusicBrainz). All three call sites now use a single blankMeta() helper as the source of truth. Disc Designer layers panel: - Designer mode now has the same Add image / Add text / Add color controls as the template editor — a single panel since discs are one target. URL input + Copy button + the three add buttons. Previously the panel showed the layer list but no way to add layers in the first place. Zapped tab fixes: - _feedPagination was only initialised for New and Popular, so the Zapped rerender threw "Cannot set properties of undefined" on every paint and the panel never populated. Added the Zapped pagination state. - fetchZapsForEvents now batches chunks in parallel instead of sequentially, and streams a debounced rerender on every ingested receipt, so zap totals appear within a second or two instead of taking up to ~28 s for a 200-design feed. - invalidateFeedCache now also clears the zap cache (byEvent / byAuthor / receiptIds / fetchedFor* sets). Without that, hitting Refresh never re-queried receipts because every event id was already marked "fetched". Co-Authored-By: Claude Opus 4.7 --- src/index.html | 465 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 387 insertions(+), 78 deletions(-) diff --git a/src/index.html b/src/index.html index e0d598b..58e67fb 100644 --- a/src/index.html +++ b/src/index.html @@ -1593,6 +1593,24 @@ .previewActionsRow > #nostrPreviewActions[data-visible="false"] { display:none; } .previewActionsRow button { font-size:.78rem; padding:5px 10px; line-height:1.2; white-space:nowrap; } + .toastStack { position:fixed; bottom:20px; right:20px; z-index:2000; display:flex; flex-direction:column; gap:8px; pointer-events:none; max-width:calc(100vw - 40px); } + .toast { background:var(--panel); color:var(--ink); border:1px solid var(--line); border-radius:8px; padding:10px 36px 10px 14px; max-width:380px; box-shadow:0 6px 18px rgba(0,0,0,.3); font-size:.85rem; pointer-events:auto; position:relative; line-height:1.35; animation:toastIn .18s ease-out; } + .toast.toast-error { border-left:3px solid var(--warn); } + .toast.toast-success { border-left:3px solid var(--accent); } + .toast.toast-info { border-left:3px solid var(--muted); } + .toast .toastClose { position:absolute; top:6px; right:6px; width:22px; height:22px; border:0; background:transparent; color:var(--muted); cursor:pointer; font-size:16px; line-height:1; padding:0; border-radius:4px; } + .toast .toastClose:hover { background:rgba(127,127,127,.15); color:var(--ink); } + .toast.toastOut { opacity:0; transition:opacity .2s; } + @keyframes toastIn { from { transform:translateY(8px); opacity:0; } to { transform:translateY(0); opacity:1; } } + + .publishConfirmPreview { background:var(--bg); border:1px solid var(--line); border-radius:8px; padding:10px; margin:0 0 12px; display:flex; justify-content:center; align-items:center; max-height:280px; overflow:hidden; } + .publishConfirmPreview > * { max-width:100%; max-height:260px; } + .publishConfirmMeta { margin:0 0 12px; font-size:.82rem; } + .publishConfirmMetaRow { display:flex; gap:10px; padding:5px 0; border-bottom:1px solid var(--line); } + .publishConfirmMetaRow:last-child { border-bottom:0; } + .publishConfirmMetaRow dt { min-width:108px; font-weight:600; color:var(--muted); margin:0; } + .publishConfirmMetaRow dd { margin:0; flex:1; word-break:break-word; color:var(--ink); } + .editingBanner { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:8px 14px; background:rgba(251,191,36,.12); border-bottom:1px solid rgba(251,191,36,.4); font-size:.85rem; color:#92400e; flex-wrap:wrap; } body.dark .editingBanner { background:rgba(251,191,36,.1); color:#fbbf24; } .editingBannerText { flex:1; min-width:0; } @@ -2807,6 +2825,24 @@ +
+ + +