cocottetech/@platform/codebase/@features/ai-copilot/docs/asset-library.screen.md
natalie 1b719e1fd7 chore(bootstrap): initial V4 commit
Clean successor to V3 (forge: lilith/atlilith). Seeded from local Mac
working tree at ~/Code/@projects/@cocottetech/. node_modules and build
artifacts excluded via .gitignore.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 08:11:41 -07:00

10 KiB
Raw Blame History

asset-library.screen

Single-screen breakdown for the asset library drawer (brief B §B2) — Quinn's grid-first view over content_assets, the place she picks the photo to pair with a draft, uploads a fresh set off the camera roll, and answers the K3a NSFW gating question before anything leaves for a non-adult surface. Voice register: working, plain on K3 warnings.

Layout

iPhone — 3-col grid, drawer slides up from chat:

┌─────────────────────────────────────────────────┐
│ ◄ Chat        Assets              [+ Upload]    │ 56pt top bar
├─────────────────────────────────────────────────┤
│ [OF] [X] [IG] [Tour] [persona:luxe] [+ filter] │ filter chips row · horizontal scroll
├─────────────────────────────────────────────────┤
│  ┌────┐ ┌────┐ ┌────┐                          │
│  │ ▣  │ │ ▣  │ │ ▣  │                          │ row 1 — thumbs w/ status corner badge
│  │OF✓ │ │ NSFW│ │ ⟳  │                          │ ✓=auto-approved · NSFW=K3a flag · ⟳=uploading
│  └────┘ └────┘ └────┘                          │
│  ┌────┐ ┌────┐ ┌────┐                          │
│  │ ▣  │ │ ▣  │ │ ▣  │                          │
│  └────┘ └────┘ └────┘                          │
│  ┌────┐ ┌────┐ ┌────┐                          │
│  │ ▣  │ │ ▣  │ │ ⚠  │  ← upload-failed         │
│  └────┘ └────┘ └────┘                          │
│  …                                              │ infinite scroll · pagination at 60
├─────────────────────────────────────────────────┤
│ 124 assets · 12 NSFW · 38 auto-approved         │ footer stats
└─────────────────────────────────────────────────┘

iPad — 5-col grid (per brief E): same layout, wider, persistent left rail for filter chips, footer stats remain.

Asset-detail sheet (modal over drawer, tap a tile):

┌─────────────────────────────────────────────────┐
│ ◄ Library                              ⋯        │
├─────────────────────────────────────────────────┤
│        ┌────────────────────────┐               │
│        │                        │               │ hero thumb · 4:5
│        │       ▣  hero          │               │
│        │                        │               │
│        └────────────────────────┘               │
│                                                 │
│   IMG_4421.heic · 3024×4032 · 4.2 MB           │ filename + dims + size
│   uploaded May 14 · MinIO ok                    │
│                                                 │
│   Tags: [luxe] [Berlin] [indoor] [+ add]       │ editable tag list
│   Surfaces: [OF ✓] [X ✗] [IG ✗] [Tour ✓]       │ per-surface auto-approval toggle
│   NSFW: ● yes  (auto-block from N3 brand sites) │ K3a flag · plain copy
│                                                 │
│   Variants (3)                                  │
│   • original · 4.2 MB                           │
│   • of-feed-crop · 1.1 MB                       │
│   • tour-tease-blur · 0.8 MB                    │
│   [ + new variant ]                              │
│                                                 │
│   [ Schedule on... ]   [ Drag to chat ]         │ primary actions
└─────────────────────────────────────────────────┘

Component table

Component Notes
Top bar "◄ Chat" returns to scroll position. "+ Upload" opens camera-roll picker + iOS share-sheet target (per B §B2).
Filter chips row Horizontal scroll · multi-select · per surface tag (OF/X/IG/Tryst/Tour/...), persona facet, tags array, auto-approved flag, NSFW status.
Asset tile 1:1 thumb · corner badge (auto-approved ✓ per surface · NSFW · uploading ⟳ · failed ⚠). Long-press enters multi-select.
Footer stats Live count · NSFW count · auto-approved count. Updates as filters narrow.
Asset-detail sheet Hero + metadata + editable tags + per-surface approval toggles + NSFW flag + variants list + actions.
Schedule-on sheet Per-surface checklist + date/time picker · routes to brief B §B1 calendar after confirm.
Variants list Per content_asset_variants rows · tap to preview · "+ new variant" routes to producer specialist.

States to render

  1. Empty — "Nothing in the pantry yet. Tap + to add a few photos, or ask the producer to pull from your camera roll." (hearth touch on empty).
  2. Uploading — tile shows ⟳ spinner over dimmed thumb · "3 of 7 uploading · 2.1 MB/s" strip above grid.
  3. Upload-failed — tile shows ⚠ amber badge · tap → sheet with plain copy: "IMG_4421.heic didn't finish uploading. Retry or remove?"
  4. Typical grid — populated 3-col, mix of approval states.
  5. Filter-narrowed — chips active, footer reads "12 of 124 · luxe + OF". Empty filter result: "Nothing matches. Clear filters?"
  6. Asset-detail expanded — sheet over drawer per layout above.
  7. Variants list active — variants section expanded; tapping a variant previews it inline.
  8. Schedule-on sheet — per-surface checklist + datetime · "Schedule on OF Tue 9pm? Producer will pick the variant."
  9. Auto-approval gate (K3a NSFW) — toggling a surface ON for an NSFW asset surfaces inline plain-register confirm: "This is flagged NSFW. {surface} doesn't allow it. Force allow anyway?" with [Cancel] [Force allow once] [Always allow for {surface}].
  10. MinIO offline — banner top of drawer: "Storage unreachable. Thumbnails may not load; uploads are paused." Plain register. Existing metadata still browsable.
  11. Large-library pagination — at 60+ assets, footer shows "Showing 60 of 412 · load more" or auto-loads on scroll-end · skeleton tiles while fetching.

Filters

Chip set, multi-select, persists per-session:

  • Surface tag — OF · X · IG · TikTok · Tryst · TS4Rent · Eros · Tour · ... (per O 24-surface roster).
  • Persona facet — luxe · girl-next-door · domme · ... (per personas.facets keys).
  • Tags array — free-form, autocompletes off existing tag set.
  • Auto-approved flag — show only assets pre-cleared for at least one surface.
  • NSFW status — yes / no / unset.

Gestures

  • Long-press tile → enters multi-select mode · top bar swaps to "{n} selected · [Tag] [Schedule] [Delete]".
  • Tap tile → opens asset-detail sheet.
  • Drag tile → drag-into-chat (drop on the chat below the drawer's slide-down handle to attach to current draft).
  • Swipe-down on drawer → dismiss back to chat.
  • Pull-to-refresh → re-poll GET /api/v1/content-assets.
  • Pinch on grid → toggle 3-col ⇄ 2-col (iPhone) or 5-col ⇄ 3-col (iPad).

In-the-wild copy

Empty state (hearth):

Nothing in the pantry yet. Tap + to add a few photos, or ask the producer to pull from your camera roll.

K3a NSFW gate (plain):

This is flagged NSFW. X doesn't allow it on the public timeline. Force allow once, always allow, or cancel?

Upload-failed retry (plain):

IMG_4421.heic didn't finish uploading. Retry or remove?

Schedule-on confirm (working):

Schedule on OF for Tue 9pm? Producer will pick the variant.

Edge cases

  • Asset originally tagged for OF dragged into a chat draft targeting X — K3a warning fires inline in chat: "This one is flagged NSFW and tagged for OF. X will reject it. Pick a different variant, or force allow?" Routes to variants list with the tour-tease/blurred variants surfaced first.
  • Variant generation in progress — variants list shows a pending row "of-feed-crop · generating..." with the producer specialist's avatar; tile in the grid keeps the original until variant lands.
  • Camera roll permission denied — Upload button surfaces inline copy: "Cocotte can't see your camera roll. Settings → Photos → CocotteAI." Plain register.
  • Duplicate detection — re-uploading a hashed-match asset surfaces "Already in the library — open existing?" inline.
  • K3c-2 KYC vault asset — vault-flagged assets never appear in this drawer; carve-out per brief K §K3c-2.
  • Asset deleted while detail sheet open — sheet shows "This asset was removed. Close?" plain register.