Reverts 0182c46bb. The webpack 5.107.2->5.108.0 bump changed prod-bundle
scope-hoisting so option-builders in src/options/options.js (Languages,
TimeZones, StartPages, MapsAnimate) threw "Cannot read properties of
undefined", breaking the login and Settings pages on all editions.
Re-apply the photo-sphere-viewer/tar patch bumps separately.
The babel-plugin-istanbul coverage plugin was only wired into the retired karma.conf.js; Vitest measures coverage via @vitest/coverage-v8 (.babelrc has no plugins). Dropping it removes the orphaned @istanbuljs/load-nyc-config -> js-yaml@3 subtree and clears the GHSA-h67p-54hq-rp68 DoS advisory; npm audit now reports 0 vulnerabilities.
* 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
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.
Security-hardening and bug-fix minor release; no breaking changes for
our usage. Keeps the exact pin (no caret) per the high-risk-package
policy. Verified with make audit, OSV-Scanner, build-js, and test-js.
- Refactor `meta.css` face-marker palette to consume theme tokens (Path A):
default rect → `on-surface`; named-marker stroke → `primary`; draft →
`accent`; hover → `primary-darken-1`; handle → `primary-darken-1` fill +
`primary` stroke; Confirm pill → `primary-darken-2`; Cancel pill →
`highlight-lighten-1`; Remove pill → `remove`; Back button → `surface`.
- Retune the `lightbox` theme block to support the rebind: `primary
#F2F3F3 → #9E8FC9` (muted purple), `accent #2D2E2E → #BDAFE4` (lavender),
`surface #151515 → #181818`, `surface-bright → #1c1c1c`, `button →
#242424`, `highlight #424041 → #3c3c3c`, `remove → #cd4645`. Effectively
reverts the `surface-variant ↔ on-surface-variant` swap and re-introduces
an explicit `.v-tooltip.v-theme--lightbox` override in `lightbox.css`.
- Bump `variations.darken` to 2 so `--v-theme-primary-darken-2` resolves.
- Swap the in-template button order in `markers.vue` to Cancel-left /
Confirm-right for both the pending-add and remove-confirm popovers.
- Add inline comments to the `default.add` and updated `lightbox`
entries so each color's purpose stays documented at the source.
- Drop `eslint-plugin-prettier` (its `prettier/prettier` rule was already
`"off"`, making the plugin inert). Replace `plugin:prettier/recommended`
with a direct `eslint-config-prettier` extend; keep ESLint's own
`indent` / `quotes` / `brace-style` rules as the JS formatter.
- Tell ESLint to ignore `*.{css,scss,sass}` so Prettier owns CSS
unambiguously; wire `npm run fmt-css` / `npm run lint-css` Prettier
passes into `npm run fmt` / `npm run lint` so `make fmt-js` and
`make lint-js` cover stylesheets too.
- Drop `eslint-plugin-prettier` from the dev-container global install
list and the `frontend/tests/README.md` dependency table; regenerate
`NOTICE` files.
Removes the top-level "escape-string-regexp" dependency, which has no
direct consumer in our source. The v4 line lives on as a transitive
dep of "eslint" and "sanitize-html"; "webpack-bundle-analyzer" keeps
its nested v5 copy. Net dep-tree shape is unchanged.
Also bumps "@vue/language-server" to ^3.3.0, adds "vuln" and "tools"
phony aliases in the Makefile, and aligns the frontend "audit" target
with the root one (--no-fund --no-audit).
Signed-off-by: Michael Mayer <michael@photoprism.app>
Both were added during the Vitest framework integration (#4990) but
never referenced in any source file or test config — npm ls confirms
zero transitive consumers. PhotoPrism is Vue, so the React testing
library is not applicable; @testing-library/jest-dom (the actually
used helper) stays. The TS-paths resolver was speculatively added
when the Vite config was first stubbed and was never wired up.
README's "Known Unused" table is replaced with a short "Auditing for
Orphaned Dependencies" section so the sweep pattern (rg + npm ls)
is documented for future cleanups.
Cheerio was originally pulled in alongside easygettext@2.17.0 in May
2022 (commit d600d5faf), where easygettext declared cheerio@^1.0.0-rc.3
as a runtime dep for HTML parsing in the gettext-extract flow. When
easygettext was replaced by vue3-gettext / vue-gettext-extract in
October 2025 (commit ab9a0a969 / #1152), cheerio was overlooked and
left as a top-level dep with no consumers.
The exact pin to 1.0.0-rc.12 was set in September 2024 (commit
ab9e156c9, bundled into an unrelated UX commit) after an August 2024
bump to ^1.0.0 broke easygettext's ^1.0.0-rc.3 peer constraint. That
rationale evaporated when easygettext was removed; the lockfile
reverse-search confirms zero current consumers.
npm ls cheerio --all returns only the direct top-level entry; no
source files import it. make audit, make build-js, make test-js
(1055 passed / 13 skipped) all stay clean after removal.
The supply-chain compromise that drove the original 1.14.0 quarantine
(malicious 1.14.1/0.30.4 from a hijacked maintainer account) was fully
remediated upstream weeks ago, so 1.16.0 is safe. Keeps the exact-pin
style recommended for high-risk packages.
Removes two stale dependencies that have no code references in any
frontend/, plus/frontend/, pro/frontend/, or portal/frontend/ tree.
postcss-url was a 2019 leftover and is the only consumer of the
unpatched minimatch <=3.1.3 ReDoS chain (GHSA-3ppc-4f35-3m26,
GHSA-7r86-cg39-jmmj, GHSA-23c5-xmqv-rm74); npm audit now reports
zero vulnerabilities.
Vuetify 3.12.3 added an onFocusout handler to VAutocomplete, VSelect,
and VCombobox (commit 3d33e2f, fixing Vuetify upstream #22697) that
flips isFocused=false on any blur whose relatedTarget is outside the
textfield. The handler closes long dropdowns on open because the
virtual scroller unmounts the focused list item during the scroll-to-
selected-index pass that runs right after the menu opens, producing a
transient blur with relatedTarget=null. Pinning Vuetify to 3.12.2 (the
last release without the regression) is the cleanest fix; explored
workarounds (list-props navigation-strategy=track, capture-phase
focusout suppression with activator refocus, menu-props attach=true)
all had unacceptable side effects.
The pin is documented inline in three places that cross-reference each
other: package.json (//vuetify field), frontend/CODEMAP.md (Runtime &
Plugins), and frontend/src/common/view.js (sibling-menu gate comment
block). The original GitHub issue #5538 has been updated with the full
root-cause analysis. A separate follow-up issue #5556 tracks the minor
.v-field--focused linger that 3.12.2 still has (PhotoPrism is currently
unaffected because the relevant inputs aren't on screen together).
Includes incidental cssnano (7.1.8 -> 7.1.9) and postcss (8.5.13 ->
8.5.14) patch bumps from \`make -C frontend update\` after the pin.