Commit graph

13450 commits

Author SHA1 Message Date
Ömer Duran
75b007b502
Lightbox: Stop slideshow on sphere gestures 2026-06-18 05:19:31 +02:00
Michael Mayer
d52554fc50 Lightbox: Add 16K thumbnails and refine 360° viewer routing #5669 #5623 2026-06-17 04:12:41 +00:00
Michael Mayer
4ab00fa32d Config: Raise thumbnail and conversion size limits to 16K #5669 2026-06-17 04:12:40 +00:00
Michael Mayer
43506ad883 Thumbs: Add 16K (15360px) fit size for photos and videos #5669 #5623 2026-06-17 04:12:40 +00:00
Michael Mayer
f894157191 Docs: Update LICENSE notice files #352 #4718 #5623 2026-06-17 03:38:36 +02:00
Michael Mayer
6006e08a38 Frontend: Update deps in package.json and package-lock.json #352 #4718 #5623 2026-06-17 03:29:55 +02:00
Ömer Duran
3ea547a564
Lightbox: Add support for 360° photos and videos #352 #4718 #5623
* Lightbox: Add 360° photo and video sphere viewer support

Wires Photo Sphere Viewer v5 into the lightbox for equirectangular
media. Backend detects UsePanoramaViewer and IsPhotosphere markers
alongside ProjectionType, and exposes Panorama + Projection in the
viewer / search result DTOs so the frontend can dispatch on the
projection type. The renderer (ThreeJS + PSV core + video plugin +
equirectangular video adapter) is lazy-loaded into a dedicated
webpack chunk so the base bundle is unchanged for users with no
360° media. PhotoPrism's existing lightbox controls drive the
underlying HTMLVideoElement that the PSV adapter creates for 360°
videos. Includes Vitest coverage for the sphere helper and the
lightbox dispatch, plus a TestCafe smoke spec and three new
ExifTool metadata fixtures.

* Lightbox: Fix 360° controls leak, hide zoom button, add sidebar icon

* Lightbox: Fix 360° touch panning and navigation arrows

* Lightbox: Fix fast swipe switching photos on 360° slides

Suppress PhotoSwipe swipe/drag navigation at its source via the dispatched pointer hook while a sphere slide is active, since the per-element gesture trap is outrun by a fast swipe whose pointer leaves the sphere container (touch-capable Windows). UI controls stay excluded so buttons and arrows still navigate.

* Lightbox: Route only equirectangular media to the 360° viewer

Routing was based on the loose photo_panorama flag for videos, which is also
true for cubemap and merely-wide (aspect > 1.9) videos, so non-equirectangular
media wrongly opened, distorted, in the sphere viewer. Route strictly on the
equirectangular projection for both photos and videos. Surface the video file's
projection in the viewer DTO via Photo.MediaProjection() (the primary search row
is a poster JPEG with no projection). Add an MP4 metadata-detection test.

* Lightbox: Open tagless 2:1 360° videos in the sphere viewer

Many 360° videos carry no projection tag PhotoPrism can read, so strict
equirectangular-projection routing left them in the flat player. Fall back to
equirectangular's defining 2:1 frame for panorama-flagged videos without a
projection, via is360Equirectangular() in common/sphere.js, while cubemap and
ultrawide (~2.35:1) clips stay flat.

* Tests: Make the 360° sphere video test assert instead of skipping
2026-06-17 03:26:25 +02:00
Michael Mayer
bf081bd68b Users: Add canEnableLogin() to gate the Web Login toggle 2026-06-17 00:26:18 +00:00
Michael Mayer
a2e708e7ab Meta: Update go-mp4, regenerate NOTICE, fix XMP doc spelling #2260 #5563
Bump abema/go-mp4 to v1.7.1 (only outdated direct dependency) and tidy
go.sum, pruning stale checksums left by the XMP sidecar merge. Regenerate
the license NOTICE for the updated dependency.

Use US-English spelling in the new XMP sidecar comments and tests, and
drop a specs/ reference from internal/meta/README.md so the public package
doc has no link into the private subrepo. Regenerate dialect_mysql.go from
SQL.
2026-06-17 00:14:33 +00:00
Ömer Duran
86efc1c982
Index: Improve support for metadata in XMP sidecar files #2260 #2828 #5563
* Meta: Add XMP sidecar fixture corpus for reader rewrite #2260
* Meta: Replace XMP sidecar reader with antchfx/xmlquery #2260
* Meta: Add XMP sidecar reader test suite #2260
* Meta: Assert XMP GPS extraction on Apple/Adobe sidecars #2828
* Meta: Apply XMP sidecar metadata to photo and primary file #2260
* Meta: Resolve XMP sidecar time zone via shared helper #2260
* Meta: Derive panorama & caption keywords on XMP sidecar reads #2260
* Meta: Assert XMP sidecar GPS override and malformed-file handling #2260
* Meta: Tidy XMP sidecar reader comments and reuse logName local #2260
* Meta: Fix XMP sidecar capture-time priority OffsetTime handling #2260
* Meta: Address XMP sidecar review feedback #2260
2026-06-17 01:53:28 +02:00
Michael Mayer
ee0b1a616a Search: Sort geo "near" results by distance to the photo #5643
A "near=<uid>" geo search set the S2 cell but left the form lat/lng at
zero, so results sorted by distance from the (0,0) origin instead of
the referenced picture. Use the picture's own position in the ORDER BY,
falling back to time order when it has no usable coordinates.
2026-06-16 23:19:46 +00:00
Michael Mayer
50e1e595de Places: Group coincident map photos by screen proximity #5643
Past the cluster zoom threshold, group un-clustered photo features by
projected screen distance instead of exact coordinates, so pictures at
the same place stack into one counter marker even when their stored
coordinates differ slightly (GPS jitter, tile quantization). Key each
stack by a stable member UID and open it by its bounding box so the
panel lists exactly those pictures.
2026-06-16 23:19:37 +00:00
Michael Mayer
bad538e51b Index: Do not assign OriginalName to indexed files #5668
Stop deriving a file's OriginalName from cached metadata during indexing.
The ExifTool JSON cache is keyed by content hash, so a renamed file was
re-indexed against the old name and surfaced it as OriginalName, making
cards show a stale name while the sidebar showed the current one.

OriginalName is now set only from the explicit import original name, so
plain-indexed files no longer carry one and imported files are unaffected.
2026-06-16 17:21:56 +00:00
Michael Mayer
74a95fc748 ACL: Generate CLI role & auth-provider help from role tables #5667
Add pkg/txt.JoinOr plus acl.RolesCliUsageString and UserRoleUsageFor so the users/clients --role and --auth help derive from the role tables instead of hand-maintained literals, filtering the app/uploader aliases and visitor. Each edition lists its own roles; federatable contexts (LDAP, OIDC group-role, cluster grants) use ClusterInstanceRoles.
2026-06-16 11:57:44 +02:00
Cathie Integra
8e219a006c Setup: Remove pre-rendered pkg/linux/README.html
dl.photoprism.app now renders README.html on demand from README.md
(Caddy/goldmark), so the hand-maintained HTML copy is redundant.
2026-06-16 11:36:21 +02:00
Cathie Integra
f1d5ae2ba2 ACL: Add ClusterInstanceRoles source of truth for group-role help 2026-06-16 09:32:15 +02:00
Cathie Integra
d78966141a Build: Add tag-release.sh and tag-release Makefile target 2026-06-16 07:45:40 +02:00
Michael Mayer
f31db8a03b Tests: Add missing $util.shouldOpenOnHover mock to people-tab suite #5666
PActionMenu reads $util.shouldOpenOnHover() in data(); the suite only
passed because PActionMenu was stubbed. Complete the $util mock so the
tests no longer depend on that stub to hide the call, which otherwise
fails with "this.$util.shouldOpenOnHover is not a function".
2026-06-16 03:12:34 +00:00
Michael Mayer
2f94755af6 People: Seed type-ahead cache on name save to fix stale suggestions #5666
Naming faces in quick succession left the second new name out of the
people type-ahead until a manual reload, because eviction relied on the
subjects WS event, which can lag the next focus-triggered read.

Marker.setName() and Face.setName() now seed the shared people cache with
the saved name so it is suggestible immediately; the rename path seeds via
recognized.vue (Subject.update() also backs hide/show, so it can't host the
seed). Harden the cache itself: get() snapshots an epoch so a fetch that
resolves after an evict/upsert no longer clobbers the slot with stale data,
and upsertPeople merges idempotently. Reload new.vue suggestions on focus
to match the photo people tab.
2026-06-16 02:57:58 +00:00
Michael Mayer
cbc548d771 Frontend: Revert menu/action icons back to vertical dots
see c13c260

Signed-off-by: Michael Mayer <michael@photoprism.app>
2026-06-16 04:02:33 +02:00
Michael Mayer
bf14649ce4 Places: Stack photos at identical coordinates on the map #5643
Group un-clustered geo features by exact coordinates so that pictures
sharing a spot render as one stack marker with a counter instead of
overlapping, hidden duplicates once zoomed past the cluster threshold.
Clicking such a stack opens the location's collection panel rather than
a radius search that surfaced unrelated nearby photos.

Key the embedded photo list by latlng so an already-open panel re-runs
its search for the newly selected cluster or stack.
2026-06-16 01:56:03 +00:00
Michael Mayer
fe0a59a138 Users: Exclude remote LDAP accounts from canHavePassword() 2026-06-16 00:41:34 +00:00
Michael Mayer
85d58f7cbe Users: Add canHavePassword() to gate password change actions 2026-06-16 00:30:13 +00:00
Michael Mayer
75a5e1ee0b Auth: Log anonymous API requests at debug level instead of warning #5647
Only warn when a request presents a token that is rejected; requests
without any credentials (e.g. the web app loading public config before
login) are routine and now logged at debug level, reducing log noise.
2026-06-15 23:56:56 +00:00
Michael Mayer
c45ee6e54f Auth: Revoke derived sessions & gate app passwords by login state #5647
- Add scoped session revocation (RevokeSessions / RevokeDerivedSessions)
  shared by the user-update API and the CLI: a privilege-level change now
  revokes logins and app-password-derived sessions while keeping the app
  passwords themselves, so configured devices keep working.
- Identify app-password-derived sessions by auth_method "session".
- Deny app passwords on the REST API when the account cannot log in
  (DenyLogIn); WebDAV access stays governed by CanUseWebDAV.
- Reduce the WebDAV auth cache expiration to one minute.
- Add IsSystemOrInvalid; allow deleting the initial admin account and skip
  re-initializing a deactivated or deleted admin in InitAccount.
- Move session-revocation scopes to pkg/authn and extend tests.
2026-06-15 23:41:01 +00:00
Michael Mayer
aff25636b5 People: Fix name-save re-entry and avoid full-list refetch #5666
Guard recognized.vue onSave against re-submission while the people cache
resolves by setting busy before the async lookup. Drop updatePersonList so
Browse Pictures / Set Cover no longer evict and refetch the whole people
list; the name combobox reloads suggestions on focus and WS events keep
the cache current. Make the people-tab test seed via a mocked getPeople.
2026-06-15 16:50:35 +00:00
Michael Mayer
997ff2e70d People: Load name suggestions from typeahead cache #5666
Move the people name list out of the client config into the shared
typeahead cache (getPeople, backed by GET /api/v1/subjects), matching
labels and albums. Consumers load suggestions on demand and the cache
evicts on people.* / subjects.* events and clears on logout; the
config.js people machinery is removed and ClientConfig keeps only
count.people for the navigation badge.
2026-06-15 14:38:04 +00:00
Michael Mayer
6addeaa7a4 People: Scope client config people list to authorized roles #5666
Groundwork for the people type-ahead cache: include the people list and
count in the client config only for roles that may view or search people,
and omit the list from the global config.updated broadcast. Clients load
it via GET /config and keep it current through people.* events.
2026-06-15 13:45:38 +00:00
Michael Mayer
a3f9df12ca Tests: Fix cleanup album revert helper for deleted albums #5646
helperAfterEach reverted photos before restoring albums, so re-adding a
photo to an album a test soft-deleted targeted a dead UID, 404'd, and
cascaded into helperFailures. Determine album changes first so the photo
loop can skip albums revertAlbums restores (recreated foreign-owned ones
get a new UID), and tolerate 404 on add-to-album.
2026-06-15 13:04:25 +00:00
Michael Mayer
2fd0ed8631 Events: UID-only camera/lens/country payloads & people refetch #5663 #1307
Make the cameras/lenses/countries content-channel events publish only a
stable identity ([]string of slug or ISO code) instead of full entity
models, matching the UID-only invariant of every other content channel.
The update path no longer republishes count.* (an edit does not change
the count).

Restore surgical people updates: onPeople refetches only the affected
people by UID via Subject.search (refetchPeople) and upserts them in
place instead of forcing a full client-config reload (a #1307 regression).

Document the dormant folders.*/faces.* subscribers (no publisher, not
forwarded) and fix the misleading payload example in the event README.
2026-06-15 11:37:26 +00:00
Michael Mayer
1b2ce048b2 Frontend: Update axios, vitest, playwright & coverage-v8
Pin axios 1.18.0 (security-hardening minor: strips sensitive headers on cross-origin redirects, rejects malformed http/https URLs, tightens prototype-pollution defenses; no breaking changes). Bump vitest and coverage-v8 to 4.1.9, playwright to ^1.61.0. OSV-Scanner clean for both ecosystems.
2026-06-15 10:23:12 +00:00
Michael Mayer
0e79cf9eca Backend: Update golang/geo and refresh NOTICE
Bump golang/geo to 20260612074446 (same module license). go mod tidy also drops a stale golang.org/x/net v0.55.0 checksum.
2026-06-15 10:23:07 +00:00
Michael Mayer
2c278cbd96 Import: Fix data race in import destination settings #5607 #5652
GetDest() lazily wrote the shared ImportSettings.Dest on every call, so
parallel ImportWorker goroutines raced on it. Make GetDest side-effect
free and normalize an invalid stored pattern once in Settings.Propagate.

Also align the per-hash indexing lock added in #5652 with code style.
2026-06-15 09:58:52 +00:00
Kevin Nowald
4f341768e4
Index: Serialize indexing of byte-identical files to avoid duplicates #5607 #5652 2026-06-15 11:31:49 +02:00
Weblate
f88a870379 Weblate: Update backend translations 2026-06-15 11:28:47 +02:00
Michael Mayer
8422fb8ddd Locales: Regenerate backend translations for #5663 2026-06-15 09:25:44 +00:00
Michael Mayer
bc327016ad Metadata: Add Camera Make and Model updates via CLI & API #5663 #5656
Mirror the lens make/model editing surface for cameras: entity UpdateMakeModel/SaveForm, form validation, query, search, the GET/PUT /api/v1/cameras endpoints, and the cameras CLI command, plus a cameras ACL resource and scope.

Also tidy the lens surface for parity: self-validating SaveForm, empty make/model guard, X-Count search header, service-role grant, the empty-id/slug docs, and order cameras before lenses everywhere.
2026-06-15 09:25:44 +00:00
Keith Martin
7c6546ce19
API: Search X-Count header for Labels and Services #5649
* API: Add X-Count response headers for services and labels.
* API: update swagger annotations for response headers
2026-06-15 10:00:08 +02:00
Keith Martin
c3eda657fd
Metadata: Add Lens Make and Model updates via CLI & API #5644 #5656
Adds the ability to override a lens's Make/Model (e.g. fixing Pentax lenses that ExifTool decodes as `4 38`) via a new photoprism lenses update CLI command and a `PUT /api/v1/lenses/:id endpoint`, plus a `GET /api/v1/lenses` search endpoint, a new lenses ACL resource, and an lenses ls list command.
2026-06-15 09:37:32 +02:00
Michael Mayer
41369dd5ce Tests: Fix duplicate testIDs and inverted reversion logic #5646 2026-06-15 07:11:00 +00:00
Keith Martin
3a4140b686 Tests: add ability to run the reversion tests, remove outdated config, remove console.log and mark test as skipped due to inability to test 2026-06-15 08:53:33 +02:00
Keith Martin
389b361a25 Tests: Improve test logging (when SHOW_LOGS is true in environment 2026-06-15 08:53:33 +02:00
Keith Martin
541c554206 Tests: Fix issue with NotYetExisting being clicked due to middle of dialog box selection issue 2026-06-15 08:53:33 +02:00
Keith Martin
b8a2091e6c Tests: Performance improvements and utilisation of reversion capabilities 2026-06-15 08:53:33 +02:00
Keith Martin
592a9958e1 Tests: Implement beforeEach, afterEach and before for after each test change reversions 2026-06-15 08:53:33 +02:00
Keith Martin
9ca202b65a Tests: Add Reversion capability and tests thereof 2026-06-15 08:53:33 +02:00
Keith Martin
c7afdf09dd Tests: Enable elapsed time logging for each acceptance test 2026-06-15 08:53:33 +02:00
Michael Mayer
e88751a501 Config: Add bloom, flower, ring & shutter app icons #5662
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.
2026-06-15 06:29:43 +00:00
Michael Mayer
9605d87731 Tests: Isolate reaction redaction subtest from mutation fixtures 2026-06-14 16:38:34 +00:00
Michael Mayer
b24e84f5f5 Frontend: Upgrade Vitest to v4 and Vite to v8 to drop esbuild #5659 2026-06-14 16:15:51 +00:00