From 30c2b0fe8232cc748ab2bded6ab4d76febe32425 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 3 May 2026 19:17:04 +0300 Subject: fix(admin): fix rescan goroutine lifecycle and race on shared ScanProgress - Protect adminService scan state (cancel func + progress pointer) with sync.Mutex. - Allocate fresh ScanProgress per trigger and pass it to the scanner, eliminating races on the previously shared progress struct. - Cancel previous scan context before starting a new one. - Add tests for cancellation, fresh progress per scan, concurrent triggers, and empty progress when never started. - Fix race-prone tests by polling Running==true before waiting for completion. --- web/css/lightbox.css | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ web/css/player.css | 21 ++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 web/css/lightbox.css (limited to 'web/css') diff --git a/web/css/lightbox.css b/web/css/lightbox.css new file mode 100644 index 0000000..83bf946 --- /dev/null +++ b/web/css/lightbox.css @@ -0,0 +1,79 @@ +.lightbox-overlay { + position: fixed; + inset: 0; + z-index: 80; + background: var(--bg-overlay); + display: none; + place-items: center; +} +.lightbox-overlay.open { + display: grid; +} + +.lightbox-stage { + width: 90vw; + height: 85vh; + display: grid; + place-items: center; + overflow: hidden; +} +#lightbox-image { + max-width: 100%; + max-height: 100%; + object-fit: contain; + transition: transform 0.15s ease; + user-select: none; + cursor: zoom-in; +} + +.lightbox-nav { + position: absolute; + top: 50%; + transform: translateY(-50%); + background: var(--bg-surface); + border: 1px solid var(--border); + font-size: 2rem; + padding: 0.5rem 1rem; + cursor: pointer; +} +.lightbox-prev { + left: 1rem; +} +.lightbox-next { + right: 1rem; +} +.lightbox-close { + position: absolute; + top: 1rem; + right: 1rem; + background: var(--bg-surface); + border: 1px solid var(--border); + cursor: pointer; +} + +.lightbox-toolbar { + position: absolute; + bottom: 1rem; + left: 50%; + transform: translateX(-50%); + display: flex; + gap: 0.5rem; + align-items: center; + background: var(--bg-surface); + padding: 0.5rem 1rem; + border-radius: var(--radius-lg); + border: 1px solid var(--border); +} +.lightbox-meta { + font-size: 0.875rem; + color: var(--text-secondary); + margin-left: 0.5rem; + white-space: nowrap; +} +.lightbox-counter { + font-size: 0.875rem; + color: var(--text-secondary); + margin-left: 0.5rem; + white-space: nowrap; + font-variant-numeric: tabular-nums; +} diff --git a/web/css/player.css b/web/css/player.css index c6070f9..0f468f9 100644 --- a/web/css/player.css +++ b/web/css/player.css @@ -137,6 +137,27 @@ background: var(--player-stage-bg); } +/* Image viewer inside player */ +.player .media-image { + width: 100%; + height: 100%; + object-fit: contain; + display: block; + transition: transform 0.15s ease; + user-select: none; +} +.player .media-image.hidden { + display: none; +} + +/* Show/hide controls per media type */ +.player.has-image .video-only { + display: none !important; +} +.player:not(.has-image) .image-only { + display: none !important; +} + /* Overlay controls */ .player .controls { flex: 0 0 auto; -- cgit v1.2.3