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>
137 lines
10 KiB
Markdown
137 lines
10 KiB
Markdown
# 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.
|