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:
2026-07-23 07:34:20 +05:30
parent bc8bf2007d
commit 7673fc63ea
35 changed files with 3130 additions and 394 deletions
+5
View File
@@ -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.
+41 -25
View File
@@ -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 sessionsnow 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.
+52 -3
View File
@@ -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 13 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 13 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).