* Frontend: Add settings for albums, favorites, folders, and media features
* Frontend: Enhance download settings for files and albums #848
* Frontend: Enhance download settings for files and albums #848
* Frontend: Update album download settings to restrict access to super admins
* Frontend: Add album sorting options to settings for super admins
* Frontend: Update download settings visibility
* Frontend: Refine download settings access control for user roles
* Tests: Add album, folder, moment, state, and month order selection options to page-model
* Frontend: Update access control for super admins in settings to include scope check
* Tests: Add new tests for download name and album order settings persistence
* Tests: Implement new tests for default album sort order persistence in settings
* Frontend: Move default album order settings
* Frontend: Add zoom accessibility option in settings #799
* Frontend: Update download name from "Share Identifier" to "Share Friendly" and refine hints for download options in settings
* Tests: Add new acceptance test for disabling album downloads while allowing file downloads in settings
* Frontend: Improve download options layout and hints
* Frontend: Refactor download options condition in settings page
* Frontend: Implement native zoom control in lightbox component
* Settings: Add Collections tab and move Services to its own page #848#5429
- Add a super-admin Collections tab after Content holding the album
Download and Sort Order settings; remove those cards from Content.
- Move Services from a settings tab to a dedicated page
(page/services.vue) with a search toolbar and a Reload / Learn More
action menu; link it from the navigation settings menu.
- Implement server-side services search (acc_name filter) with tests.
- De-duplicate the picture sort-order options into a shared
SortOrderOptions builder in options.js.
- Update acceptance/unit tests and page models to match.
* Frontend: Regenerate translation catalogs #848#5429
Ran `make gettext-extract` to pick up the new settings strings
(Collections, Features, Disable Downloads, and related messages) so
Weblate can translate them. Existing translations are preserved.
* Frontend: Move lightbox viewport-zoom handling into the view helper
- Move the viewport pinch-zoom lock/restore (disableNativeZoom /
restoreNativeZoom + savedViewportContent) from lightbox.vue onto the
View singleton in common/view.js.
- Drive it passively from View.apply() via a disableViewportZoom flag in
the PLightbox case, alongside hideScrollbar / disableScrolling /
disableNavigationGestures; lightbox.vue no longer references zoom.
- Make save/restore idempotent and extract the viewport constants.
- Cover the helpers and the apply() wiring in view.test.js.
* Settings: Add Accessibility section to General with Reduce Motion #848#5429
- Move the page-zoom checkbox out of the feature-flags grid into a
dedicated Accessibility card (super-admin only) with four toggles:
Open on Hover, Reduce Motion, Hide Scrollbar, and Allow Page Zoom.
- Add a UI.ReduceMotion flag (defaults false) that toggles an
html.reduce-motion class via config.setReduceMotion and suppresses map
fly-to animations non-destructively (util.mapAnimateDuration).
- Make Open on Hover apply live by reading shouldOpenOnHover() through a
reactive computed in the action/auth/lightbox menus; Zoom and Hide
Scrollbar reload since they are baked into the server-rendered HTML.
- Reword two feature-grid hints to the "pictures" convention and cover
the new helpers with Go and Vitest tests.
* Frontend: Regenerate translation catalogs #848#5429
Ran `make gettext-extract` to pick up the new Accessibility settings
strings (Accessibility, Allow Page Zoom, Open on Hover, Hide Scrollbar,
Reduce Motion, and their hints) and the reworded feature-grid hints.
Existing translations are preserved.
---------
Co-authored-by: Michael Mayer <michael@photoprism.app>
Route JPEG XL through the native libvips path (govips jxlload) like
HEIC/AVIF, keeping the external "djxl" decoder as an automatic fallback
for runtimes whose libvips lacks JPEG XL support.
Decouple format enablement from "djxl": DisableJpegXL now stays enabled
when either the decoder is present or libvips can decode JPEG XL natively.
The libvips capability probe (thumb.JpegXLSupported) is cached and runs
only when no decoder is present, so config introspection on standard
installs (which ship "djxl") does not start libvips.
Add a shared assets/samples/dice.jxl fixture and focused tests for the
native conversion path, the djxl fallback command, and the capability
decision table.
Rename the i18n notification/error envelope fields from id/params to messageId/messageParams across the WS notify Data and the i18n.Response body, so they are unambiguous next to session, log, and correlation ids. Updates the frontend consumers (notify.vue, api.js), tests, swagger, and the event/locales READMEs.
Describe the event *Msg structured payload and frontend per-user rendering in the event and backend-locales READMEs; fix a stale go-generate path (/internal/i18n to /pkg/i18n).
Adds four selectable app-icon variants with optimized SVGs and full PNG size sets. bloom and ring use a round canvas like logo; flower and shutter use the rounded-square canvas. Updates the frontend icon resolver, app-icon help text, and config tests, and strips editor data-name attributes from the existing icons.
Implements three OIDC follow-ups from specs/portal/cluster-oidc.md:
- Zero-touch instance OIDC RP config: PHOTOPRISM_CLUSTER_OIDC derives the
OIDC RP client_id/secret from the node client credentials and defaults
the issuer to the instance's own origin (scheme.OriginURL), so a single
boot reaches a working Portal login. Explicit oidc-client/secret/uri win.
- Human-friendly authorize errors: redirectable errors 302 back to the
validated redirect_uri; non-redirectable ones content-negotiate a
branded HTML page (oauth-error.gohtml) vs JSON via shared helpers in
internal/api/oauth_error.go. The RP callback surfaces inbound ?error=.
- Cluster-wide Sign-Out (Tier 2): session.logoutEverywhere fans out a
best-effort DELETE per peer session, clears their storage, then signs
out locally; session-delete clears the OP cookie on any shared-domain
OIDC-against-Portal node (OIDCSessionCookieClearPath).