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

137 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.
## Related
- [Brief B §B2](./B-drawers.brief.md) — drawer roster + inputs (`GET /api/v1/content-assets`, `POST /api/v1/content-assets` with MinIO presigned URL).
- [Brief K §K3a](./K-safety-blocklist.brief.md) — NSFW cross-surface gating; the auto-approval gate is the asset-side enforcement point.
- [Brief K §K3c-2](./K-safety-blocklist.brief.md) — KYC vault carve-out (vault assets never surface here).
- [Brief R](./R-tours-events-hotels.brief.md) — tour-tease variants feed pre-tour announcements; "Tour" surface tag is set here.
- [`specialist-content-onlyfans.contract.md`](./specialist-content-onlyfans.contract.md), [`specialist-content-social.contract.md`](./specialist-content-social.contract.md) — the specialists that consume picked assets + produce variants.
- [`specialist-drawer.screen.md`](./specialist-drawer.screen.md) — structural pattern mirrored here.