feat: enhance styling and layout for toolbar, map components, and editor
- Updated toolbar styles for improved layout and appearance, including padding and margin adjustments. - Introduced new styles for scale menu and compact dropdowns. - Enhanced map pin tooltips with better positioning and hover effects. - Added new styles for map sheet filters, including search and date range controls. - Improved editor styles for a more cohesive look and feel, including transport controls for video editing. - Expanded GeoLocation interface to include additional address fields and formatted address. - Updated MediaItem interface to include storage reference and uploadedBy fields. - Enhanced MediaComment interface with author details for better user identification. - Introduced GalleryUser interface to represent signed-in users in the host app.
This commit is contained in:
@@ -8,6 +8,11 @@ these files for full context. Keep them updated as work proceeds.
|
||||
- [requirements.md](requirements.md) — the COMPLETE requirements backlog (every request, tracked).
|
||||
- Human-facing docs live in [`/docs`](../../docs/) (ROADMAP / SETUP / ARCHITECTURE) and [`/CLAUDE.md`](../../CLAUDE.md).
|
||||
|
||||
> **Current focus (2026-07-23):** the SDK now **embeds into a host app** (LynkedUp CRM), not only the standalone demo —
|
||||
> `embedded` layout, `chrome` suppression, host identity (`currentUser`) + theming (`ThemeTokens`), server-backed
|
||||
> Recently-Deleted lock, and an **incremental** `StorageAdapter` (`applyChanges` + `putMedia`). See the latest
|
||||
> `status.md` session entry and `docs/ROADMAP.md` §11.
|
||||
|
||||
## Hard rules (do not violate)
|
||||
- **Never `git commit` / `git push`** — the user does that. Never commit secrets.
|
||||
- API keys live only in `apps/web/.env.local` (gitignored), read **server-side** only.
|
||||
|
||||
@@ -12,34 +12,50 @@ Status: ✅ done · 🚧 in progress · ⬜ planned · 🔑 needs key/creds. Cro
|
||||
- ✅ Info panel (full metadata + **mini-map**). Themes menu + `accentColor`/`borderRadius` props.
|
||||
- ✅ Gemini generative editor (Remove BG/Restore/Colorize/Replace Sky/prompt) — 🔑 needs billed key (free=429).
|
||||
|
||||
## Now / next (in user's priority order)
|
||||
1. 🚧 **Custom camera** (#1): getUserMedia preview; capture photo; record video; switch front/back; grid;
|
||||
## Now / next (in user's priority order) — all ✅ done
|
||||
1. ✅ **Custom camera** (#1): getUserMedia preview; capture photo; record video; switch front/back; grid;
|
||||
**live annotation + measurement**; geolocation on capture (permission); auto object-detect after capture.
|
||||
2. ⬜ **Supabase backend + storage** (#last, 🔑): Postgres data + Supabase Storage. **No localStorage reliance** —
|
||||
backend is the source of truth. Ask user for creds (URL, anon key, service-role key, bucket) with steps.
|
||||
3. ⬜ Face clustering → People; OCR (tesseract.js) → document search; semantic "show me beach photos"
|
||||
(transformers.js / Hugging Face CLIP) — all free, in-browser.
|
||||
4. ⬜ Video editor + annotations; macOS-parity player polish.
|
||||
2. ✅ **Supabase backend + storage** (🔑): Postgres data + Supabase Storage adapter (run `docs/supabase-setup.sql`
|
||||
once). Backend is the source of truth on load. The CRM host supplies its own **incremental** data-door adapter
|
||||
(`applyChanges` + `putMedia`); localStorage remains the zero-config dev default.
|
||||
3. ✅ Face clustering → People; OCR (tesseract.js) → Documents + searchable text; semantic search
|
||||
(transformers.js / CLIP) — all free, in-browser.
|
||||
4. ✅ Full video editor + annotations (timeline engine, no ffmpeg); ✅ macOS-parity **custom video player**.
|
||||
|
||||
## New requests (this session — must add)
|
||||
- ⬜ **Editor: straighten / tilt** (angle slider) — rotate by arbitrary degrees.
|
||||
- ⬜ **Crop: free-form AND fixed-ratio** — when a ratio (e.g. 1:1 square) is selected, dragging/stretching the
|
||||
crop box keeps that aspect ratio; also free crop.
|
||||
- ⬜ **Import sync of existing metadata**: if an imported/mobile image already has tags (IPTC/XMP keywords) +
|
||||
location + details, read and apply them (exifr supports XMP/IPTC). Keep object detection + object albums.
|
||||
- 🚧 **Web-meaningful UI** (deep pass): "All Projects" → **"All Albums"** (this is a web gallery, not iOS);
|
||||
remove "Open App Store" (meaningless on web); review sidebar tabs, **corner radius**, touch-ups so everything
|
||||
is meaningful for a web gallery and matches macOS more closely.
|
||||
- ⬜ **Search dropdown defaults**: show quick filters **Recently Viewed**, **Recently Edited** (+ Recently Shared)
|
||||
when the search field is focused.
|
||||
- ⬜ **Info → map click opens full Map** centered on that photo's location.
|
||||
- ⬜ **Map parity w/ macOS**: locations + images + tags; latest image shown for a tag; **click a tag → open
|
||||
that tag's images grouped by date** (date-wise). Tag = album-like view, date-grouped.
|
||||
- ⬜ **Local-model fallback**: if Gemini key missing/invalid, use a local model. Concretely wire
|
||||
`@imgly/background-removal` (free, in-browser) for Remove Background so it always works without a key.
|
||||
- ⬜ **Everything free**; build our own if no free option.
|
||||
## New requests (early sessions — now all done)
|
||||
- ✅ **Editor: straighten / tilt** (angle slider) — rotate by arbitrary degrees.
|
||||
- ✅ **Crop: free-form AND fixed-ratio** — a selected ratio (e.g. 1:1) is kept while dragging; also free crop.
|
||||
- ✅ **Import sync of existing metadata**: IPTC/XMP keywords + location read on import (exifr) alongside object detection.
|
||||
- ✅ **Web-meaningful UI** (deep pass): "All Projects" → **"All Albums"**; removed "App Store"; sidebar tabs / corner
|
||||
radius / touch-ups reviewed for a web gallery matching macOS.
|
||||
- ✅ **Search dropdown defaults**: Recently Viewed / Recently Edited / Recently Added when the search field is focused.
|
||||
- ✅ **Info → map click opens full Map** centered on that photo's location.
|
||||
- ✅ **Map parity w/ macOS**: click a tag → that tag's images grouped by date; thumbnail pins; location sheets.
|
||||
- ✅ **Local-model fallback**: `@imgly/background-removal` (free, in-browser) wired for Remove Background — no key needed.
|
||||
- ✅ **Everything free**; build our own where no free option (analysis/OCR/faces/semantic/bg-remove all run in-browser).
|
||||
- ✅ **Memory in project `.claude/` folder** (this folder) — done.
|
||||
- ⬜ More **advanced features** (open-ended; user will add more later).
|
||||
- ✅ More **advanced features** — versioning + audit log, comments, advanced video editor, sharing, password lock,
|
||||
glass design polish, custom video player (open-ended; new requests continue below).
|
||||
|
||||
## Host-app embedding & CRM integration (2026-07-23) — done
|
||||
> The SDK now embeds into a host product (LynkedUp CRM), not only the standalone demo. All of it is opt-in.
|
||||
- ✅ **Embedded layout** (`embedded`) + **chrome suppression** (`chrome`, `DEFAULT_CHROME`) + **`hiddenViews`** +
|
||||
**`keyboardShortcuts`** flag; live `setConfig` re-applies theme/tokens/identity/chrome without remount.
|
||||
- ✅ **Host identity** (`currentUser: GalleryUser`) → identity-stamped **comments** (`authorId/author/authorAvatar`,
|
||||
delete only own), **uploads** (`MediaItem.uploadedBy`, never overwritten), **versions** (author on each). Info panel
|
||||
shows "Uploaded by" + per-version author. `be-crm` still owns `owner_principal_id` (display-only here).
|
||||
- ✅ **`shareBaseUrl`** (host owns share-link base) + **full-screen** (`defaultFullscreen`, `.apg--fullscreen`,
|
||||
`setFullscreen`/`toggleFullscreen`).
|
||||
- ✅ **Full `ThemeTokens` map (52 keys)** → CSS vars (sanitized); floating glass toolbar + `.apg-scalemenu` dropdown.
|
||||
- ✅ **Incremental adapter**: `applyChanges(StateChanges)` (diff-based, serialized, rollback-on-reject) +
|
||||
`putMedia(id, blob, meta) → StoredBlob {ref,url}`; `MediaItem.storageRef`. Types `StateChanges`/`StoredBlob` exported.
|
||||
- ✅ **Server-backed Recently-Deleted lock** (`lockProvider { status, set, verify }`) replaces the device-local hash;
|
||||
`lockConfigured` = UI truth; `lockError` = wrong-password vs unavailable.
|
||||
- ✅ **Editable caption + multi-line `note`** in Info (searchable); **full-address reverse geocoding** (Nominatim,
|
||||
persisted); **map** fly-to / count badge / hover mini-slider / date-range location filter.
|
||||
- ✅ **UI fixes**: Info-panel inline `<video>` preview; comments as cards + spacing/divider; video-editor custom
|
||||
transport outside the transformed frame; map tooltip `user-select:none` + edge-clamping.
|
||||
- ⬜ Still open: real multi-user auth / permissions in the host (SDK identity is display-only; backend is the authority).
|
||||
|
||||
## Notes
|
||||
- getUserMedia needs HTTPS or localhost (dev OK). Permissions-Policy already allows camera/mic/geolocation=self.
|
||||
|
||||
@@ -3,9 +3,13 @@
|
||||
## Run
|
||||
`pnpm install && pnpm dev` → http://localhost:3000 (landing → Open Gallery → /gallery). `pnpm build` to ship.
|
||||
|
||||
## Current state (2026-06-29)
|
||||
Phases 1–3 complete & verified (see [requirements.md](requirements.md)). `pnpm build` passes; /gallery ~170 KB
|
||||
(TF.js + exifr lazy). Zero console errors. Default persistence = localStorage adapter (until Supabase wired).
|
||||
## Current state (2026-07-23)
|
||||
All phases + both big user batches + versioning/comments + advanced video editor + RunPod AI wiring + **host-app (CRM)
|
||||
embedding** complete & verified (see the session log below and [requirements.md](requirements.md)). `pnpm build` passes;
|
||||
/gallery ~199 KB (TF.js / exifr / face-api / tesseract / transformers all lazy). The SDK now **embeds into a host CRM
|
||||
shell** — `embedded` layout, `chrome` suppression, host identity + theming, incremental `applyChanges`/`putMedia`
|
||||
adapter, server-backed Recently-Deleted lock — not only the standalone demo. Default dev persistence = localStorage
|
||||
adapter; Supabase adapter included; the CRM host supplies its own data-door adapter.
|
||||
|
||||
## Session log
|
||||
- S1: monorepo + SDK + demo; full macOS Photos UI; albums/smart-albums/recycle/import/editor/lightbox; light+dark;
|
||||
@@ -344,7 +348,52 @@ Phases 1–3 complete & verified (see [requirements.md](requirements.md)). `pnpm
|
||||
REFUTED (correctly, no change): status-URL query-string, combined-body-cap rejecting masks, replace-sky client
|
||||
strength, 'mask' in op undefined-crash, mask-op has no UI button (all non-bugs / already-safe).
|
||||
|
||||
- S-crm-embed (2026-07-23): **Host-app (CRM) embedding + Info-panel / video-editor / map UI fixes.** The SDK became
|
||||
embeddable into a host product (LynkedUp CRM) instead of only the standalone macOS-Photos demo. (Docs-audit pass this
|
||||
session; the code below was landed across the CRM-integration rounds and is verified against the source.)
|
||||
EMBEDDING: `PhotoGalleryProps` + `GalleryConfig` gained `embedded`, `chrome { titlebar, sidebar, toolbar,
|
||||
themeSwitcher }` (+ exported `DEFAULT_CHROME`), `hiddenViews: ViewId[]`, `keyboardShortcuts`, `currentUser`,
|
||||
`shareBaseUrl`, `defaultFullscreen`, `lockProvider`. `setConfig` re-applies theme/tokens/identity/chrome live (no
|
||||
remount). Full `ThemeTokens` map (52 keys) → CSS vars via a `url()/expression()/javascript:/<>{}` guard. Floating
|
||||
glass toolbar + `.apg-scalemenu` library-scale dropdown (replaced the Years/Months/All segmented). `.apg--fullscreen`
|
||||
maximise (store `fullscreen`/`setFullscreen`/`toggleFullscreen`; toolbar button; Escape exits after
|
||||
lightbox/editor/camera/modal/menu).
|
||||
IDENTITY: `MediaItem.uploadedBy?: GalleryUser` (imports + camera; never overwritten on re-import); `MediaComment` and
|
||||
`MediaVersion` carry `authorId/author/authorAvatar`; comments identity-stamped from `currentUser` (delete only own —
|
||||
client mirror of the server rule); Info panel shows an "Uploaded by" block + per-version author. `be-crm` still owns
|
||||
`owner_principal_id`; `uploadedBy` is display-only.
|
||||
PERSISTENCE: `StorageAdapter.applyChanges(StateChanges)` (diff-based; called INSTEAD of save() on debounced change;
|
||||
serialized writes + rollback-on-reject; only non-system albums persisted) + `putMedia(id, blob, {name,mime}) →
|
||||
StoredBlob {ref,url}` (durable bytes preferred over putBlob; sets `MediaItem.src` = url, `storageRef` = ref). Types
|
||||
`StateChanges`/`StoredBlob` exported. Server-backed Recently-Deleted `lockProvider { status, set, verify }` replaces
|
||||
the device-local `apg:lock-hash` entirely (`lockConfigured` = UI truth; `lockError` = 'wrong-password' vs 'unavailable').
|
||||
METADATA/GEO: editable `caption` + new multi-line `MediaItem.note` in Info (save on blur/Enter via updateMedia; note
|
||||
in the search haystack). `GeoLocation` gained road/neighbourhood/suburb/city/county/state/postcode/country/countryCode/
|
||||
formatted; Info panel auto reverse-geocodes once via OSM Nominatim (`addressdetails=1`) + persists (host CSP must allow
|
||||
`nominatim.openstreetmap.org`). MAP: fly-to on pin click, per-location count badge, hover mini-slider strip, location
|
||||
sheet filter (object chips + single date-range control `.apg-daterange`).
|
||||
UI FIXES (latest round, verified in code): (1) Info-panel VIDEO items render a real inline `<video>`
|
||||
(`.apg-info__thumb--video`) not a frozen `<img>`; (2) extra spacing around "Uploaded by" / "Analyzing…" / between
|
||||
comments (now cards `.apg-comment`) + a divider before the compose form; (3) the VIDEO EDITOR no longer applies the
|
||||
rotate/flip/crop transform to a `<video controls>` — custom transport bar OUTSIDE the transformed frame
|
||||
(`.apg-vedit__transport` / `.apg-vedit__scrub` / `.apg-vedit__time`); (4) map hover tooltip got `user-select:none` +
|
||||
edge-clamping (`--tip-dx` + `.apg-pin__tip--below`) so it can't overflow/clip.
|
||||
COLLECTIONS TRIM (2026-07-23): `CollectionsView.tsx` stripped of the placeholder-only sections — Memories, Pinned,
|
||||
Featured Photos, People & Pets (removed entirely, incl. the interim "Pets"), Trips, Utilities. Remaining: Albums,
|
||||
Objects, Shared Albums, Recent Days. Removed the now-unused `first`/`featured`/`hiddenViews`/`hidden`/`shown` locals +
|
||||
dead `useState` import. (The sidebar's own Pinned/Utilities/People nav rows are separate and unchanged.)
|
||||
DOCS (this session, no source changed, no git commit): root `README.md` (props table + embedding-props block +
|
||||
incremental-adapter note + Platform "Embedding" row + reverse-geocode moved to done); `packages/photo-sdk/README.md`
|
||||
(added Info-panel media/comments, video-editor transport, map-pin notes — the embedding/token/adapter guide already
|
||||
existed); `docs/ARCHITECTURE.md` (Info-panel video preview + comment cards; map tooltip clamp); `docs/ROADMAP.md`
|
||||
(new §11 Embedding into a host app; moved editable metadata / reverse-geocode / date-range / fullscreen / identity →
|
||||
done); `docs/SETUP.md` (Supabase "planned adapter" → shipped); `CLAUDE.md` "What this is"; this memory.
|
||||
|
||||
## Key files
|
||||
- Host-app embedding (S-crm-embed): `packages/photo-sdk/src/components/PhotoGallery.tsx` (props) + `store/store.ts`
|
||||
(`GalleryConfig`/`ThemeTokens`/`GalleryChrome`/`DEFAULT_CHROME`/`LockProvider`/fullscreen/identity actions) +
|
||||
`adapters/types.ts` (`StateChanges`/`StoredBlob`/`applyChanges`/`putMedia`) + `components/{InfoPanel,AppShell}.tsx` +
|
||||
`components/views/MapView.tsx` + `components/editor/VideoEditor.tsx` + `styles/sdk.css`.
|
||||
- RunPod integration (S-runpod): `apps/web/src/lib/runpod/*` (server) + `apps/web/src/app/api/ai/{edit,classify}/route.ts` + `apps/web/src/lib/ai/{runpodYoloProvider,imageEncode}.ts` (client). Env: `RUNPOD_API_KEY` + `RUNPOD_*_URL`.
|
||||
- Advanced video editor (S-advanced): `packages/photo-sdk/src/lib/videoBake.ts` + `lib/videoTimeline.ts` + `components/editor/VideoEditor.tsx`.
|
||||
- AI edit backend (S-deploy-ai): `apps/web/src/app/api/ai/edit/route.ts` (env AI_EDIT_PROVIDER).
|
||||
|
||||
Reference in New Issue
Block a user