Per-folder memory + per-share recursive (v1.3.1)#66
Merged
Conversation
V1.3.1 erstes Feature. Speichert pro Folder-Pfad das zuletzt gewählte
recursive/depth-Setting in localStorage. Beim Wiederbesuch desselben Folders
landet der User wieder im gleichen View — ohne URL-Manipulation, ohne in
die Personal Settings zu gehen.
Hierarchie der Werte-Quellen (höchste Priorität zuerst):
1. URL-Query (?recursive=… / ?depth=…) — Sharing/Bookmarking
2. Per-Folder-Memory (localStorage) — Convenience NEU
3. Personal Settings Default — globaler Fallback
Geschrieben wird NUR bei expliziter UI-Interaktion (FilterBar-Toggle/
Stepper); reine URL-Aufrufe (z.B. von Share-Links) hinterlassen keine
Spuren im localStorage. Damit shar't sich der Persistenz-State nicht
versehentlich über externe Links.
Mechanik:
- Util src/utils/folderRecursiveState.js mit read/write/clear-Funktionen
- Single localStorage-Key 'starrate_folder_recursive_v1', JSON-Map
{ path: { recursive, depth } }
- Cap 50 Einträge — älteste Insertion-Order-Eintrag wird beim Überlauf
gedroppt
- Defensiv gegen kaputte/manipulierte Werte: depth wird auf 0-4 geclamped,
recursive zu Boolean coerced, JSON-Parse-Fehler liefern null
- 14 Util-Tests + 4 neue Gallery-Tests für die End-to-End-Verkabelung
Verkabelung in Gallery.vue: recursive/depth Computeds checken nach URL-
Query gegen folderRecursiveState; setRecursive/setDepth schreiben nach
URL-Update auch in den localStorage.
Macht aus 'Neuer Share' ein universelles Anlegen+Bearbeiten-Modal, ersetzt die kleinen Toggles in ShareList, gibt jedem Share eine recursive/depth-Konfig. Backend: - ShareService.createShare/updateShare akzeptieren recursive, depth, nc_path - Bestandsshares ohne Felder via ?? false / ?? 0 als flach - getImagesForShare ruft bei share.recursive den neuen Helper listImagesRecursiveForShare auf — bewusste Kopie von GalleryController::listImagesRecursiveFromDb mit Security-Comment (Drift = Privilege-Escalation, Doppelung erzwingt synchrone Pflege) - Bei recursive ignoriert die Guest-API ?path= (kein Folder-Drill) - ShareController validiert depth 0-4 - 3 neue PHPUnit-Tests Frontend: - ShareModal: editShare-Prop schaltet auf Edit-Mode (Title, Submit, PUT vs POST, Pfad-editierbar) - Recursive-Felder nur wenn settings.recursion_enabled - Path-@blur löst die folderRecursiveState→Settings-Auflösung aus (Sarah-Use-Case) - Passwort: leer=behalten, gefüllt=ändern, neue Remove-Checkbox - ShareList: Stift-Button ersetzt alle Toggles, Read-only Badges zeigen Status (Pick, Export, Comment, Recursive, Password) - Active-Toggle bleibt inline - Gallery: editingShare verdrahtet ShareList → ShareModal
1) Guest-Thumbs neu generiert beim ersten Besuch: Owner-Frontend nutzt /core/preview?mode=cover, NC speichert die gecroppten Vorschauen unter MODE_COVER. Unsere ShareService rief getPreview() ohne Mode-Argument auf — NC-Default ist MODE_FILL, also andere Cache-Datei. Folge: jeder Gast triggerte eine komplette Neugenerierung der Thumbs, die schon im NC-Cache lagen. Fix: bei Thumbs (crop=true) explizit MODE_COVER setzen, bei Previews (crop=false) MODE_FILL. Damit teilen Owner und Gast denselben NC-Preview-Cache, Gast-Erstbesuch ist instant. 2) ShareList kompakter: Pfad und Empfängername jetzt in einer Zeile (statt zwei), getrennt mit Em-Dash. Empfängername in helleres Grau (#a1a1aa statt #d4d4d8) — der Pfad ist die primäre Identität des Shares, der Name sekundär. Spart eine Zeile pro Share, gerade bei vielen Freigaben relevant.
Quick-Win für den 'zweite Bewertungsrunde'-Use-Case. Vorher musste der Browser des Gasts nach 1h alle Thumbs neu vom Server holen — auch wenn sich nichts geändert hat. NC liefert dann zwar aus dem Server-Cache, aber der HTTP-Roundtrip pro Tile summiert sich auf merkliche Wartezeit. 7 Tage Browser-Cache deckt typische Mehrfachbesuche durch Guest und Bewertungs-Iterationen ab. FileDisplayResponse setzt ETag automatisch: nach Ablauf revalidiert der Browser via If-None-Match, Server antwortet 304 (kein Body) wenn die Datei sich nicht geändert hat. Bei mtime- Änderung wird komplett neu geladen. private/nicht-immutable als Default — kein CDN/Proxy-Caching (Share- spezifische URLs), aber Revalidation möglich.
Vorher rief PUT /api/share/{token} updateShare() ohne Body-Validation auf.
Update-Endpunkt verließ sich auf inline-Clamping (depth/min_rating) und
throw-on-bad-permissions. Folge: Bad-Body führte zu HTTP 500 statt 422
mit klarer Fehlermeldung — schlechte UX und inkonsistent zu create.
Fix: validateShareBody um $isCreate-Flag erweitert. nc_path ist nur bei
create Pflicht (weil ein neuer Share einen Pfad braucht), bei update
optional (Teilfelder-Updates ändern den Pfad nicht zwingend). Update
nutzt validateShareBody(false) und gibt 422 mit ordentlichen Fehlern
zurück.
Inline-Clamping in updateShare bleibt als Defense-in-Depth — falls die
Validation jemals umgangen würde, sind die Werte trotzdem sane.
16 neue Vitests für die V1.3.1-ShareModal-Erweiterung. Decken die im Code-Review als Lücke identifizierten Pfade ab: Recursive-Felder: - Hidden wenn recursionEnabled=false (Default) - Sichtbar bei recursionEnabled=true - Tiefe-Dropdown nur wenn recursive UND recursionEnabled - recursiveDefault wird beim Anlegen vorbefüllt Edit-Mode: - Title 'Freigabe bearbeiten' - Submit-Label 'Speichern' - Pfad-Input editierbar (kein readonly) - Felder aus Share vorbefüllt (Permissions, Pick, Recursive, GuestName) - Passwort-Feld leer + Remove-Checkbox sichtbar bei has_password=true - Remove-Checkbox versteckt bei has_password=false - Submit ruft PUT, nicht POST - recursive + depth landen im PUT-Body - Leeres Passwort + Remove=false → kein password-Key (behalten) - Remove=true → password=null (entfernen) - 'updated'+'close' Events nach erfolgreichem Submit Path-Blur Re-Resolve (Sarah-Use-Case): - Mit recursionEnabled: Pfad-Wechsel löst folderRecursiveState/Settings- Hierarchie neu aus, Felder werden aktualisiert - Ohne recursionEnabled: Pfad-Wechsel ändert recursive-Wert nicht
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v1.3.1
Two new features building on the recursive folder view from v1.3.0, plus a ShareList refactor that makes share configuration cleaner.
What's new for users
Per-folder memory for recursive view — when you flip recursive on (or change the depth) for a folder, the next time you visit that same folder it remembers your choice. Works without URL params, without changing personal settings — just stays per folder. Cap at 50 folders, oldest rotates out.
Per-share recursive view — when creating or editing a share, you can now choose whether the guest sees a recursive view (all images from subfolders in one grid) and the group depth. The share carries its own configuration; the photographer's personal setting only seeds the defaults when the share is created. Guests have no way to override — they see exactly what the photographer chose.
Edit existing shares — instead of multiple small toggle buttons in the share list, each share now has a pencil icon that opens the same modal you used to create it, prefilled with the current values. Change permissions, password, recursive view, or even the shared folder path — all in one place. The status of each share (password set, pick allowed, export allowed, etc.) is still visible at a glance via small read-only icons in the share row.
Faster guest revisits — guest thumbnails and previews are now cached in the browser for 7 days. When the same recipient comes back for a second rating round, the gallery loads instantly from local cache. ETag revalidation kicks in if the underlying files have changed.
Smarter prefill when changing share path — if you edit a share and change the folder path, the recursive settings reset to your default for the new folder (matching what you'd see opening that folder yourself). One less manual step for "I want to repurpose this share for a different shoot".
Compact share list layout — folder path and recipient name share one line now (separated with
—), saving vertical space in the share list.Notes for testers
Recursive view enabled) still gates everything — defaults to off for existing users.Notes on architecture
The guest-side recursive listing is a deliberate code copy of the owner-side listing (with explicit security comment), kept that way to make any divergence loud in code review — a drift between the two would be a privilege-escalation risk.
Closes nothing standalone but extends what was delivered for #35.