Commit Graph
32 Commits
Author SHA1 Message Date
thePR0M3TH3AN 7383b98cf9 docs(book): fold reflowable text + markdown + NIP-23 into the spec
Third revision pass adds reflowable prose as a first-class part of
the Book Designer, without giving up the fixed-layout design pages.

Architecture:
- Prose chapters live as NIP-23 long-form articles (kind-30023,
  markdown body). One source, two presentations: same article event
  is readable standalone on Habla.news AND laid out as designed
  pages inside a book on Artstr Studio.
- Book manifest's `pages` becomes a discriminated union:
  `{ type: 'design', ref }` for fixed-layout pages, and
  `{ type: 'reflow', textRef, masterRef, … }` for chapter segments
  that paginate dynamically.
- New `text-frame` layer kind, lives on masters. The pagination
  engine pours markdown tokens into copies of the master until the
  chapter is exhausted.
- New `spec.textStyles` block — a book-level stylesheet mapping
  each markdown element (h1-h6 / body / blockquote / code / list /
  link / hr) to typography (font, size, weight, leading, alignment,
  margins, plus keepWithNext / keepTogether flow controls).
- Anchored designed pages: designed entries on the manifest use
  `anchor.mode: 'before-chapter' | 'after-chapter'` so their
  semantic position survives reflow-driven page-count changes.

Tradeoff mitigations baked in:
- Pagination is fiddly → tight v1 markdown subset documented;
  pure-function engine for testability; "Preview pagination" before
  publish; overflow toasts for too-long words / wide code blocks.
- Text drift breaks pagination → chapters pin to a specific event
  id by default (safe for print); opt-in "Live" mode for
  always-latest with re-paginate notices showing page-count delta;
  anchor-based positioning for designed pages.
- PDF text fidelity → reflowed prose exports as real PDF text via
  pdf-lib font subsetting; font allowlist with vector-path
  fallback + per-export warning.
- Editor scope → plain textarea + live preview for v1; CodeMirror
  upgrade deferred to Phase I; WYSIWYG never in scope.

New tokens: `{chapter-title}`, `{chapter-number}` resolve per
chapter context (useful for running headers on masters).

Phases updated:
- Phase C grows `text-frame` layer kind (structural).
- New Phase C.5 — vendor `marked`, implement pagination engine,
  markdown editor pane, anchoring, pin/live tracking. Slots in
  before PDF export because PDF needs it.
- Phase D1 expanded to include chapter publish as kind-30023.
- Phase E updated for real PDF text on reflowed prose.
- New Phase I — extended markdown subset (tables, footnotes,
  auto-TOC via `{toc}`, cross-references) + CodeMirror editor.

Pages overview tile UX expanded: designed-page tiles show a
rendered thumbnail; reflow tiles show a stack-of-pages icon with
chapter title, master name, paginated page count, and a tiny
first-page preview.

Acceptance criteria for Phases C, C.5, D1, E updated to match.

TODO.md summary rewritten to reflect the new shape.
2026-06-02 10:47:42 -04:00
thePR0M3TH3AN 33ee2b7ec5 docs(book): rewrite spec around Nostr-native sidecar architecture
Apply twelve Nostr-driven revisions to the Book Designer spec:

1. **Sidecar architecture.** Pages, masters, and the cover spread
   are now separate addressable kind-30078 events
   (`casewrap-page`, role-discriminated). The book is a thin
   `casewrap-book` manifest that references them by
   `{ kind, pubkey, dTag }` — the same shape Linked Designs
   already speaks. Edit one page → that page event replaces; the
   manifest only changes when order / list / spec moves.
2. **Masters as Nostr objects.** Each master is its own event; one
   "Body pages" master can be referenced by many books and forked
   by other authors. Default master lives on the manifest spec.
3. **Cover as a sidecar event** with `role: 'cover-spread'` so it
   can iterate independently and be republished as standalone
   marketing art.
4. **Linked Designs is the precedent.** The resolver IIFE,
   progressive fetch, localStorage disk cache, batched relay
   queries, upstream-update notifications, and attribution chain
   all transfer verbatim. Call this out explicitly so we don't
   reinvent the wheel.
5. **Addressable refs everywhere.** Manifest entries use the
   existing `{ kind, pubkey, dTag }` form (convertible to naddr at
   the UI layer), not local UUIDs.
6. **Premium gating + tips.** New "Premium, tipping, gating"
   section covers whole-book paywall (gate the manifest),
   per-chapter paywall (gate individual page events via
   PREMIUM_DESIGNS), and NIP-57 zaps at any granularity.
7. **Reader Mode** added as Phase G — the Slide Decks' Presenter
   Mode counterpart, with progressive page fetch, TOC sidebar,
   page-flip nav, and inline zap-to-unlock.
8. **Embed integration.** EXTERNAL_EMBED learns `?book=<naddr>`
   for a flip-book iframe player; same transport + CSP rules.
9. **Per-page reactions / comments** work for free because each
   page is its own addressable event (NIP-25 + kind-1). One-liner
   in product goals + Reader Mode acceptance.
10. **`{page-count}` semantics pinned.** Defaults to *numbered*
    pages; new `{physical-page-count}` exposes the raw total.
    Plus `{book-author}` for the manifest pubkey.
11. **NIP-23 distinction.** Explicit non-goal — Book mode is
    fixed-layout design, not reflowable prose; for prose use
    NIP-23 long-form articles directly.
12. **Manifest schema.** Pages now carry
    `{ ref, label?, inheritsMasterRef, skipNumber, gating? }`;
    page-side fields that vary per-book (master, skipNumber,
    label) moved off the page event onto the manifest entry.

Phase D split into D1 (publish individual page / master / cover
events) and D2 (publish the manifest); new Phase G (Reader Mode +
embed); new Phase H (premium gating). Acceptance summary,
cross-surface reactivity, and risks updated to match.

TODO.md's Book Designer summary rewritten to reflect the
sidecar plan.
2026-06-02 10:36:40 -04:00
thePR0M3TH3AN 50eed8c017 docs: spec the Book Designer (unified cover + pages + PDF export)
New BOOK_DESIGNER_FEATURE.md drafts a top-level templateMode: 'book'
that orchestrates the existing cover designer, deck overview, and
custom-art canvas around a shared document spec (trim size, page
count, paper thickness, bleed). Spine width derives from page count
× paper thickness; the cover view goes read-only on the spine
column when in derived mode. Pages reuse the deck-sorter UI for
reordering; the per-page editor is the custom-art canvas bound to
a book-page:<id> target with prev / next page nav. Masters render
underneath each inheriting page and support {page-number} /
{page-count} / {book-title} token substitution.

PDF export ships in its own phase (E), backed by a vendored
pdf-lib (~80 KB). Single-file (cover + interior) and split (cover
PDF + interior PDF) output modes; bleed + crop-mark options;
v1 flattens text to vector for font-fidelity, with vector PDF
text as a follow-up.

Phased: A (spec + skeleton) → B (pages + editor) → C (masters) →
D (publish) → E (PDF export) → F (templates + deck-to-book
import). Non-goals: reflowable text, footnotes, automatic TOC,
CMYK / ICC, imposition, mixed page sizes in one book.

Linked from README's "Drafted-but-unbuilt" list and TODO.md.
2026-06-02 10:29:01 -04:00
thePR0M3TH3AN 5b0eec1a1a docs: log the Illustrator parity arc + follow-ups
PEN_TOOL_FEATURE.md gets a 2026-06-02 status block documenting
everything that landed on top of Phase D — Direct Selection split,
auto-add/auto-delete, click-vs-drag convert, Alt-click curved ↔
pointed, multi-anchor select / marquee / arrow nudge, drag-segment
bow, continue-endpoint, spacebar reposition, Alt mid-draw, handle
break, Cmd+J / Cmd+Alt+J, Path Actions side panel — plus the
adjacent design-tool features that shipped in the same arc
(Eyedropper, Align & distribute, Free Transform rotation,
Pathfinder, marquee box-select, dive-into-edit on dbl-click).

TODO.md gets a "Design-tool follow-ups" section listing the gaps:
Smart Guides, Gradients + shadows, Scissors / Outline text /
Command palette, Flip H / V (needs renderer scaleX/scaleY),
Pathfinder rotation support, pixel-art frame timeline.
2026-06-02 09:53:06 -04:00
thePR0M3TH3AN 59ae0e32ec TODO: refresh for Linked Designs kick-off
The list had drifted from reality across the last ~30 commits.
Cleaning up so "what's next?" decisions stand on accurate ground.

Moved out of "Drafted-but-unbuilt" / polish sections and into
"Shipped (recent)":

- Native chart import phases 1–4 (bar + pie + line + polish layer).
  The old "Native chart support" follow-up text under PPTX polish
  was outdated — chart import is now its own arc with its own
  CHART_IMPORT_FEATURE.md spec.
- PPTX Phase 7 per-run rich text spans — listed as a follow-up;
  actually shipped in commit b6cf4f3.
- Premium deck publishing + multi-slide preview pager.
- Self-author auto-unlock.
- Pixel-art layer animation when embedded.
- One-click PNG / GIF download on pixel-art preview pages.
- Auto-pick category metadata via defaultCategoryForMode.
- Locked-premium UI gating (Print / Save PDF, Start Presentation,
  Import-into-Disc-1/2).
- Vault durability fixes (receipt re-derive, synchronous upsert,
  multi-relay union).

Fixed the stale "Branch still needs a merge into `main` once we're
done testing" line under PPTX import polish — the merge happened
ages ago.

Added a new "Chart import polish" section listing the open chart
follow-ups (stacked variants, combo charts, 3D approximations).

Added Linked Designs to "Drafted-but-unbuilt features" so the new
spec at docs/LINKED_DESIGNS_FEATURE.md surfaces for future
"what should we do next" decisions.
2026-05-31 16:33:07 -04:00
thePR0M3TH3AN 24338c4f12 TODO: move PPTX import out of unbuilt, capture remaining follow-ups
Phases 0–6 of the PPTX import arc shipped on pptx-import (deck
shell + slide backgrounds + text + notes + image / chart / table /
SmartArt placeholders + preset shapes with fills/strokes + group
flattening + theme color resolution + master/layout bg inheritance
+ line flip handling). Move the entry out of "Drafted-but-unbuilt
features" and add a "PPTX import polish" section listing what's
still open:

- Phase 7 per-run rich text spans (today the first run's style
  applies to the whole text box; mid-paragraph styling is lost).
- Richer import report modal (per-slide warning summary, group
  counts).
- Native chart support — render OOXML chart XML into Artstr layers
  rather than placeholder images. Its own multi-phase arc.
- Phase 6+ inheritance gaps: gradient / picture backgrounds, font
  scheme (+mj-lt → real font), placeholder geometry inheritance.
- a:custGeom → custom SVG-path conversion for arbitrary shapes
  (currently fall back to rect + warning).
- Test deck library under test/pptx/ to catch future-phase
  regressions automatically.
- Eventual merge of pptx-import → main.
2026-05-30 07:56:56 -04:00
thePR0M3TH3AN 467fbcf5e4 Draft PPTX import spec
Adds docs/PPTX_IMPORT_FEATURE.md as the canonical plan for the next
big arc: a phased editable .pptx importer that lands PowerPoint decks
as editable Artstr deck JSON.

Key decisions baked in:

- Images and unsupported objects (charts / SmartArt / tables / video)
  import as placeholder image layers pointing at a hardcoded URL
  (postimg.cc for now). Original PowerPoint media filenames carry
  over into the layer name so the user can correlate placeholders
  with their source deck.
- fflate (~10 KB) vendored as src/vendor/fflate.min.js. JSZip is too
  heavy for the single-file ethos.
- Importer code lives in src/pptx-importer.js as an IIFE that
  exposes window.ArtstrPptxImporter. The Import PPTX button
  dynamically injects both scripts on first click, so the main
  index.html bundle does not grow for the 90 % of users who never
  import a PPTX.
- Notes folded into Phase 2 alongside text (single extra relationship
  lookup, Presenter Mode already renders slide.notes).
- No Blossom / NIP-96 prereq, no base64 bloat, no publish-size guard.
  Imported decks are normal Artstr deck payloads with remote URLs.
- Import-only for this arc. PPTX export (Artstr -> .pptx) is a
  separate later arc with its own complexity.

TODO.md gets a Drafted-but-unbuilt entry pointing at the new spec.
2026-05-29 11:21:54 -04:00
thePR0M3TH3AN 3b47a314c0 Catch up TODO + README + spec banner on the premium-templates arc
Pre-merge docs sweep before zap-gated lands on main:

- TODO.md: move Premium out of "Drafted-but-unbuilt" into "Shipped
  (recent)" with a full summary of what landed (soft-gate, watermarked
  previews, NWC split-zap with 30% platform fee, purchase vault with
  auto-split, profile menu, login picker, Settings, mobile polish).
  Leave Phase 4 E2E + a few confirm()-modal replacements as a new
  "Premium-templates polish" section.
- docs/PREMIUM_DESIGNS_FEATURE.md: flip the status banner to
  "Shipped on zap-gated, merged into main 2026-05-29" and map each
  spec step (0-4) to where it lives in src/.
- README.md: add a Premium encrypted designs section; mention NWC,
  vault, login picker, profile dropdown, and Settings modal in the
  Nostr / Lightning sections; drop "NWC zaps / zap-gated templates"
  from the unbuilt list in the Files section.
2026-05-29 10:37:27 -04:00
thePR0M3TH3ANandClaude Opus 4.7 7da0c9d97c Adopt static soft-gate + buyer purchase vault spec as canonical premium model
In live testing, the tag-only gate shipped in Phases 0–3 turned out
to be too leaky: the design payload was published in plaintext, three
separate import paths (feed-card Use/Fork, preview-pane Use/Fork,
preview-pane Save JSON) bypassed the lock, and any non-Artstr client
could ignore the tag entirely. Adam pulled back the original detailed
spec he wrote earlier — the static soft-gate + buyer purchase vault
model — which solves the protection gap WITHOUT requiring a creator-
online bot (the route I was about to build).

Key idea: the AES key derives deterministically from
HKDF-SHA256(softGatePepperForEpoch(epoch), publicDesignSalt, info =
"artstr-softgate-v1" + epoch + creatorPubkey + premiumAddress +
schemaVersion). The pepper lives in the static client (obfuscated,
not secret). The client refuses to derive the key until valid kind-
9735 receipts confirm the split zap. Same key for every buyer; no
creator-online requirement; cross-device unlock via a NIP-44 self-
encrypted purchase vault (kind-30078, d=artstr:purchase-vault:v1).

Files:

  - docs/PREMIUM_DESIGNS_FEATURE.md (new, canonical) — the full
    soft-gate + split-zap + purchase-vault spec. Sections 1–17 are
    the original spec verbatim. Section 18 maps the shipped Phases
    0–3 to the spec's implementation-plan items (10.0–10.6) so the
    next contributor sees what's done. Section 19 lists the
    remaining work in build order: soft-gate crypto primitive →
    watermarked preview → premium publish event → premium consume
    → receipt fast-path by address → purchase vault → My Purchases
    UI → hardening + copy.

  - docs/ZAP_GATED_PREMIUM_FEATURE.md — banner now points at
    PREMIUM_DESIGNS_FEATURE.md as the canonical going-forward doc.
    The obsolete Phases 5/6 (DM-delivery key flow) I sketched
    earlier today are removed; the "Content model (CORRECTED)"
    section is trimmed and points at the new spec. The file is
    kept for Phases 0–3 history, the NWC/tip integration notes,
    and the threat model that still applies.

  - docs/ZAP_GATED_TEMPLATES_FEATURE.md and ZAPS_NWC_FEATURE.md
    keep their "superseded" banners pointing at
    ZAP_GATED_PREMIUM_FEATURE.md (which itself now points at
    PREMIUM_DESIGNS_FEATURE.md) — chain of provenance preserved.

  - TODO.md: drafted-but-unbuilt entry rewritten to describe the
    final shape (encrypted + vault + honest soft-gate framing) and
    point at the new spec; references the older docs for the
    shipped foundation.

No code changes yet — the spec adoption is the gate. Next commits
implement the soft-gate crypto primitive, the watermarked preview,
and the premium publish path.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-28 15:20:31 -04:00
thePR0M3TH3ANandClaude Opus 4.7 419d816212 Draft zap-gated + NWC + platform-split merged spec; supersede the two old drafts
The original ZAP_GATED_TEMPLATES_FEATURE.md said "no platform fee, no
backend" — that's exactly the opposite of what we actually want to
ship. ZAPS_NWC_FEATURE.md was scoped as a general tip upgrade,
listing splits as a "future enhancement." For our purposes the two
are a single arc, with NWC being the only thing that gives the
mandatory creator/platform split a tolerable UX.

ZAP_GATED_PREMIUM_FEATURE.md is the new canonical plan:
  - 5 phases (0 crypto bundle, 1 NWC, 2 platform-fee plumbing,
    3 zap-gated UI, 4 E2E + edge cases). ~16-23h total.
  - 30% platform fee, single-constant for easy adjustment later.
  - PLATFORM_NPUB hard-coded; lud16 resolved dynamically from the
    npub's kind-0 each session (so the lightning address can change
    later without a code update).
  - CoinOS recommended via a guided "Set up with CoinOS" path in
    the wallet-connection modal; generic "paste any NIP-47 URI"
    fallback for Alby Hub, Mutiny, Phoenix, Cashu.me, etc.
  - Idempotent retry of partial unlocks via localStorage receipt
    tracking — creator-leg pays first so a half-failed unlock at
    least pays the creator.
  - Explicit threat model + non-goals (no creator-only fallback,
    no refunds, no bolt11-QR fallback path).

The two old specs are marked superseded with a banner at the top so
historical context is preserved without future contributors getting
crossed wires. TODO.md drops them from the drafted-but-unbuilt list
and points to the merged doc; it also fixes the stale Private
Publishing entry — Phases 1 & 2 already shipped in 3e6e89e, only
Phases 3 & 4 remain.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-28 12:49:52 -04:00
thePR0M3TH3ANandClaude Opus 4.7 809e0f8fae Pixel editor: fix dropdown clipping when toolbar wraps near the sidebar
The pixel-art canvas-size dropdown (and the PNG-export dropdown that
shares the same class) used `position: absolute; right: 0` relative to
its toolbar wrap. The wrap lives inside `.pixelEditorBar`, which has
`flex-wrap: wrap`. When the bar wrapped and the trigger button landed
on the LEFT of its row, the menu's right-anchor pushed it 260px to the
LEFT — straight under the main sidebar.

Fix:
  - Switched .pixelExportMenu to `position: fixed` (only when open).
  - Added a `placeFlexMenu(menu, btn)` helper that anchors the menu's
    right edge to the button's right edge by default, flips to the
    button's left edge if anchoring right would push the menu past the
    sidebar (using the aside's actual right edge as the safe-left
    boundary, not just the viewport edge), and finally clamps to the
    viewport on both sides.
  - Added a fixed width (260px) + box-sizing border-box to keep the
    menu from expanding to its natural content width once it's freed
    from the previous absolute-positioning constraint.
  - Window-resize handler auto-closes any open menu — the fixed coords
    were computed against the previous layout, so resizing would
    otherwise strand the menu away from its button.

Verified via CDP across 920px / 1000px / 1100px / 1440px viewports and
in both sidebar-open and sidebar-collapsed states. Also exercised the
specific failure scenario (button moved to the leftmost slot of the
bar, simulating the worst-case wrap layout) — menu now opens to the
right of the button, fully inside the canvas area.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-28 09:44:29 -04:00
thePR0M3TH3ANandClaude Opus 4.7 733d123edc Top-right action strip: pin undo/redo + canvas-size readouts under Nostr widget
The undo/redo pair and the trim/sheet canvas-size pills lived inside
.topbar's flex row, which wraps at narrow widths. Adam wanted them in a
permanent, predictable place so muscle memory works regardless of
editor mode or sidebar state.

Changes:
  - .status is now `position: fixed; top: var(--top-strip-height);
    right: 0; flex-wrap: nowrap` with the same panel/border styling as
    the Nostr widget — a second strip directly below it.
  - Reordered the markup so the canvas-size pills come first and the
    undo/redo group last, so undo/redo end up hugging the viewport edge
    and the pills sit to their left (matching the requested layout).
  - Dropped the `body.app-designer .status` override (full-width
    left-aligned), since the new positioning is universal across modes.
  - updateNostrWidgetSpace() now measures the wider of the Nostr widget
    or the new strip and reserves topbar right padding accordingly, so
    the project title can't slide under the strip.

Verified via CDP at 1440px (cover, customart, pixelart modes) and at
900px narrow — strip stays pinned top-right with undo/redo on the
outside edge in every case.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-28 08:59:40 -04:00
thePR0M3TH3ANandClaude Opus 4.7 0688fc1e93 TODO: clean Adam's list — all 7 items shipped this session
Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-27 19:10:46 -04:00
thePR0M3TH3ANandClaude Opus 4.7 cfd42dd92a TODO: mark JPEG P1 shipped; refine P2/P4 + selection-chrome scope
Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-27 10:04:36 -04:00
thePR0M3TH3ANandClaude Opus 4.7 d95acfaf17 TODO: queue one-click JPEG export via direct canvas rasterizer
Current JPEG flow makes the user save a PDF, then re-pick it from
disk for PDF.js to convert. We can't cache the PDF in between
because window.print() doesn't expose the generated bytes to JS.

Log the proper fix: write a direct canvas rasterizer that walks
the layer model (image / text / shape / color / qr / pixelart),
draws each layer onto an off-screen canvas at the artboard's design
dims, then toBlob('image/jpeg'). Same approach the pixel-art PNG
export already uses, generalised across all layer types. CORS-
tainted remote images fall back to the existing PDF round-trip,
with a toast explaining why. ~300–500 LoC, no new dep.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-27 09:14:08 -04:00
thePR0M3TH3ANandClaude Opus 4.7 1c6a239f5a TODO: queue 5 new editor-UX items + CORS quick-reply
Five items added to Adam's working list:

- Click canvas background → deselect everything in vector editor.
- Toggle crop marks for export previews (so they stay out of PDF /
  JPEG output).
- Auto-size Custom Art canvas to match an imported background image's
  natural dimensions (clamped to CUSTOM_ART_MAX, with the Slide
  16:9-locked case skipped).
- JPEG export: hide layer-selection outlines before the raster snapshot.
- Independent-axis corner-node resize so a mostly-horizontal drag
  scales width a lot and height a little — applies to all layer
  resize handles, not just text.

Plus a "CORS for remote-image raster export" subsection noting that
the PDF and JPEG paths both go through window.print() / PDF.js (so
CORS doesn't actually bite today) and listing what to consider if it
ever does — Blossom / CORS-friendly hosts, an optional same-origin
proxy if we ever stand up a backend, or a direct canvas-taint
workaround.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-27 09:10:03 -04:00
thePR0M3TH3ANandClaude Opus 4.7 7439bc12b2 Slide deck PDF export: one page per slide
The Print / Save PDF button is now context-aware. In the Deck Builder
(deck mode, no slide open in the editor) it builds a hidden print-only
DOM container with one page per slide, each rendered via the same
renderCustomArtPreviewDOM the sorter thumbnails use:

- Themed at render time via composeSlideForDeck so the deck's font /
  background applies (and per-slide ignoreDeckTheme is honoured).
- Each page sized to the preview's native dimensions
  (PREVIEW_BASE_PX / 96 inches wide, aspect-matched from the first
  slide) so the @page directive is the exact slide size and the
  slide content fills the page edge-to-edge without scaling.
- `page-break-after: always` between slides; no trailing blank.
- Print-only CSS hides every other top-level element on body so
  the editor chrome doesn't bleed through.
- document.title is set to "<save-stem>_deck" so the browser
  defaults the saved PDF's filename helpfully.
- A `window.afterprint` listener tears the print container, the
  injected stylesheet, and the title override back down — so
  cancelling the dialog leaves no residue.

Inside a single-slide editor (deck mode, a slide is open), the
Print button still calls printWithCurrentFilename for the existing
single-page slide print.

TODO.md: move Slide deck PDF export and Copy / paste transform
consistency into "Shipped (recent)". Adam's working list is empty.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-26 14:18:11 -04:00
thePR0M3TH3ANandClaude Opus 4.7 3b9415e4c4 TODO: log pixelsB64 size-fallback as future pixel-art polish
Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-26 14:13:29 -04:00
thePR0M3TH3ANandClaude Opus 4.7 c82267c6a1 Fix copy/paste transform consistency — group-uniform scale + translate
Before: pasteLayersFromClipboard clamped each item's w / h individually
to the target bounds, then re-centred any item whose box landed
out-of-bounds. With multiple copied items, this:

- Collapsed every out-of-bounds item onto the same centred position
  (lost their relative positions).
- Gave each item a different effective scale (lost their relative
  sizes).

So a "Copy All" → cross-mode paste turned a tidy 4-layer composition
into a pile of overlapping clamped boxes.

Now: compute the bounding box once across every clipboard item, pick
a single scale (only shrinks — never enlarges — so a paste into a
larger target keeps items at their original size), and apply one
shared translation that centres the (possibly scaled) bbox in the
target. Both axes use the same scale, preserving the group's aspect
ratio. Items missing w / h fall back to 70%-of-target uniformly, so
the default-size path can't desync either.

Result:
- Two items copied with their original gap and a 2:1 size ratio
  retain that gap and ratio after paste, regardless of target size.
- A wide cover → narrow disc paste shrinks everything proportionally
  rather than collapsing edges onto the centre.
- Same-mode paste with everything already in-bounds is unchanged
  (scale stays at 1; translation is identity).

TODO.md: move the resolved colour-picker work to "Shipped (recent)".

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-26 13:46:33 -04:00
thePR0M3TH3ANandClaude Opus 4.7 27074b9fb6 QR layer: add Insert npub + Insert share link buttons (Phase B)
Two convenience buttons under the QR data textarea:

- Insert npub — async; pulls the signed-in pubkey via the Nostr
  extension (window.nostr.getPublicKey), encodes it to bech32
  npub, writes it into the QR data field. Toasts an error if no
  extension is present.
- Insert share link — async; only valid once the design has been
  published (checks state.editingDTag). Builds the same naddr /
  nevent shape that shareIdForRow produces for the community-
  browser Copy-share-link button:
    * naddr for replaceable events (kind 30000-39999) with a
      mode-prefixed d-tag (cover: / disc: / jewel: / customart: /
      disc-design: / slide: / deck: / pixelart:)
    * nevent fallback otherwise, using state.editingEventId
  Then wraps it as `${location.origin}/#/share/<id>` and writes
  it into the data field.

Both writes go through updateQrField('data', value) so undo /
history / the live preview pick them up the same way typing in
the textarea does.

TODO.md: mark QR Phase B as shipped.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-26 11:38:34 -04:00
thePR0M3TH3ANandClaude Opus 4.7 6a1352904e Docs: ship pixel-art Phases A–D, prune stale TODOs, update README
PIXEL_ART_FEATURE.md: rewrite Implementation status to reflect that
Phases A–D all shipped (embedded layer, standalone design, raster
export + editor extras, animation, image → pixelize), with the
backlog (WebP/APNG, Blossom offload, animated pixel layers driving
Stack actions) called out as deferred.

TODO.md: drop stale items now that they're resolved —

- Pixel Art (moved to a "Shipped (recent)" section pointing at the
  spec doc).
- Pixel editor layout expansion (subsumed by the collapsible
  sidebar — both the pixel editor and vector canvas can now use
  the full viewport width).
- Print / Save event ID wrapping (the `<dd>` already uses
  `overflow-wrap: anywhere; word-break: break-word`).
- TMDB auto-fill cleanup (the doc was already deleted).

The Color picker fixes item is kept but narrowed to the vector
tools — the pixel editor's in-app HSV picker shipped in Phase A.

README.md: add Pixel Art everywhere it's relevant —

- One-liner mention in the intro paragraph.
- New "Pixel art" Designer-tab layout entry alongside Slide / Disc
  design.
- `pixelart` layer type added to the Layers list.
- New dedicated "Pixel art" section before Editor canvas, covering
  tools / transforms / animation / export / import / undo /
  animated previews.
- Editor canvas section mentions the new sidebar collapse toggle.
- Schema section lists `pixelart` template mode and layer type,
  documents the `pixelArt` data-model shape, and notes that the
  inline GIF89a encoder lives in `index.html` (not a vendored dep).

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-26 10:54:10 -04:00
thePR0M3TH3AN 237e6ffbf4 Add multi-layer transform box 2026-05-24 15:29:14 -04:00
thePR0M3TH3AN 5e2f98ecd7 Add editable design object layers 2026-05-23 13:22:27 -04:00
thePR0M3TH3AN 6fc0fc8a98 Trim duplicate pixel art TODOs 2026-05-23 13:13:22 -04:00
thePR0M3TH3AN e26025f679 Add working TODO list 2026-05-23 13:09:12 -04:00
thePR0M3TH3ANandClaude Opus 4.7 a0ebd9c9e2 Mark editor / tool UX TODO items as shipped
The on-canvas resize handles, text-box-resize behaviour, and expanded
Text tool panel all shipped in 1a517c9; collapse the section to a
shipped note and keep it open for future editor-UX items.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-22 07:49:20 -04:00
thePR0M3TH3ANandClaude Opus 4.7 cf006ce1aa Add editor / tool UX improvements to TODO
On-canvas resize handles for all layer types, a constraint that text-box
resize never rescales the point size, and expanding the existing
#textToolOptions panel like the pen-tool panel.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-22 07:33:30 -04:00
thePR0M3TH3ANandClaude Opus 4.7 5e44c9e2e4 Draft Pixel Art feature plan with event-size budgeting
Spec for a Nostr-native pixel-art editor: an editable `pixelart` layer
type (palette-indexed + RLE grid stored in JSON, raster as export-only),
a dedicated Pixel Editor canvas-area view, a standalone casewrap-pixelart
Designer-tab design importable into any design as a layer, PNG export,
and a phased path to animation frames + GIF.

Includes a Size limits section: relays cap event size (commonly 64 KB),
so publishing is gated on a measured event-size budget derived from the
relays' NIP-11 max_event_size (min across the user's set, 64 KB
fallback) — soft warning at ~50%, hard block at ~90%, with a live size
readout in the editor. Encoder stores the smaller of RLE / base64 to
bound the worst case; rough size table per grid dimension included.

Also index the spec in TODO.md under drafted-but-unbuilt features.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-22 07:29:14 -04:00
thePR0M3TH3ANandClaude Opus 4.7 22256182d2 Draft Artstr Stacks (interactive pages) feature plan
Spec for "HyperCard for Nostr" — fullscreen interactive card stacks built
as a focused extension of the Slide Deck: a new templateMode 'stack'
reusing the deck card-container engine, with a per-stack aspect ratio,
optional per-layer actions (goto-card / open-url), transparent hotspots,
and a fullscreen interactive viewer with click routing. Declarative
safe schema only — no HTML/JS. Phased A-D plus a /p/<naddr> viewer route.

Also index both PRIVATE_PUBLISHING_FEATURE.md and STACKS_FEATURE.md under
the drafted-but-unbuilt features in TODO.md.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-21 22:37:51 -04:00
thePR0M3TH3ANandClaude Opus 4.7 9bf99f1abb Add Slide Decks & Presenter Mode (v1: Phases A–D)
Build a Nostr-native presentation system on top of the existing canvas
editor:

- Slide (templateMode 'slide') — a 16:9 Custom Art canvas with speaker
  notes; publishes/forks/loads as casewrap-slide.
- Deck Builder (templateMode 'deck') — a Template-tab container with an
  inline ordered slide list. Slide-sorter view: add blank, import from
  Nostr or file (non-16:9 imports letterboxed), duplicate, delete,
  drag-reorder, inline-rename; edit a slide in the canvas editor with
  write-back. Self-contained save/load/publish/fork as casewrap-deck;
  deck feed-card and publish previews show the first slide + count badge.
- Deck theme — deck-level font + background, render-time composition,
  per-slide ignoreDeckTheme opt-out.
- Presenter Mode — full-screen runtime: themed slide, notes, next
  thumbnail, counter; keyboard/click/on-screen nav; Presenter ⇄ Audience
  view toggle (slide-only full-screen with auto-hiding chrome). Launches
  from the deck tool palette and a deck's community-browser preview.

Supporting changes:
- New categories: slide ("Slide design") and slide-deck ("Slide deck");
  both use the free-form Custom tag field, not media identifiers.
- Swap the Template/Designer tab icons; 50% larger.
- Remove the IMDb/OMDb metadata import (button, handler, omdbApiKey);
  the imdbId field stays.
- Update README, SLIDE_DECK_FEATURE.md status, and TODO.md.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-21 22:10:06 -04:00
thePR0M3TH3ANandClaude Opus 4.7 ef7d4803f7 Text/Shape/Hand tools, Designer-tab restructure, rename to Artstr Studio
- New left-palette tools: Hand (pan), Shape (drag to draw a primitive),
  Text (click to place). Removed the redundant sidebar add-buttons.
- Pencil strokes now keep a constant on-screen thickness (pixel-space
  viewBox) instead of scaling with stroke length/aspect.
- Restructured tabs: "Disc Designer" -> "Designer", which now hosts a
  Layout panel with Custom Art (default) + Disc Design; Custom Art moved
  off the Template tab. Underlying appMode/save-format unchanged.
- Renamed the app from CaseWrap Studio to Artstr Studio (brand text only;
  Nostr tags and localStorage keys kept for compatibility); smaller
  one-line logo wordmark.
- README updated for the new tabs, tools, and keyboard shortcuts.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-20 15:30:46 -04:00
thePR0M3TH3ANandClaude Opus 4.7 162da4b9e4 QR code layers, combined-wrap panel, profile-close fix, TODO
QR code layer (Phase A):
- New `qr` layer type. Add QR button alongside Image / Text / Color /
  Shape in every layer panel. Spawns 1:1 with a placeholder URL.
- Controls: data textarea, error-correction level (L/M/Q/H), quiet
  zone, module + background colors, transparent-background toggle.
- Renders as crisp SVG on the editor and all five preview surfaces
  (dark modules merged into one path); canvas/PDF/JPEG export draws
  it cell-by-cell. Round-trips through JSON and Nostr publish/fork;
  old clients skip the unknown type. Works with drag / resize /
  rotate / opacity / aspect-lock / clip / clipboard / undo-redo.

Combined-wrap layer panel:
- In cover mode with Artwork mode "One combined wrap image", the
  layer panel collapses the separate Back / Spine / Front panels
  into a single "Cover trim area" panel — the wrap is one open
  canvas, so the sub-regions aren't meaningful. The combined panel
  still lists any pre-existing back/spine/front layers via a
  matchKeys set so they aren't orphaned from the UI.

Profile modal close fix:
- closeProfilePage used history.back(), which navigated the browser
  out of the app entirely when the profile was cold-loaded from a
  shared /u/<npub> link (that entry being first in the tab's
  history). Switched to history.replaceState to "/" — cleans the
  URL in place without navigating or firing popstate. Matches how
  closeNostrPreview already handles the /share/ URL.

Docs:
- Add TODO.md tracking deferred work: QR Phase B/C, IMDb-import
  removal, profile-page polish, edit-flow polish, and the unbuilt
  badges / collections / zap-gated / NWC-zaps features.
- Remove docs/UNDO_REDO_FEATURE.md and docs/QR_CODE_LAYER_FEATURE.md
  (shipped) and docs/TMDB_AUTOFILL_FEATURE.md (declined).
- README: document QR layers, undo/redo, fit-to-view + zoom toolbar,
  and the off-canvas veil; refresh the schema and docs references.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-19 22:09:15 -04:00