diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-03 19:17:04 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-03 19:17:04 +0300 |
| commit | 30c2b0fe8232cc748ab2bded6ab4d76febe32425 (patch) | |
| tree | 985578b326a1ff8fe7af395bf08471857376b8fc /web/js/keyboard.js | |
| parent | 687b86cdeef2192272f0945ddd496322a9113f9e (diff) | |
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.
Diffstat (limited to 'web/js/keyboard.js')
| -rw-r--r-- | web/js/keyboard.js | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/web/js/keyboard.js b/web/js/keyboard.js index 8623a10..951e573 100644 --- a/web/js/keyboard.js +++ b/web/js/keyboard.js @@ -3,6 +3,42 @@ export function initKeyboard(handlers) { const tag = e.target.tagName; const editing = tag === 'INPUT' || tag === 'TEXTAREA' || e.target.isContentEditable; + // Lightbox keyboard navigation (overrides global keys while open) + if (handlers.isLightboxOpen?.()) { + if (e.shiftKey && e.code === 'KeyS') { + e.preventDefault(); + handlers.toggleSlideshow?.(e); + return; + } + switch (e.key) { + case 'ArrowLeft': + case 'h': + e.preventDefault(); + handlers.lightboxPrev?.(e); + return; + case 'ArrowRight': + case 'l': + e.preventDefault(); + handlers.lightboxNext?.(e); + return; + case 'Escape': + e.preventDefault(); + handlers.closeLightbox?.(e); + return; + case '+': + case '=': + e.preventDefault(); + handlers.zoomIn?.(e); + return; + case '-': + e.preventDefault(); + handlers.zoomOut?.(e); + return; + } + // Allow only Escape/Arrows/h/l/+/−/Shift+S inside the lightbox; ignore everything else + return; + } + // Shares modal keyboard navigation (overrides global keys while open) if (handlers.isSharesOpen?.()) { switch (e.key) { @@ -101,8 +137,15 @@ export function initKeyboard(handlers) { } if (e.code === 'KeyS') { e.preventDefault(); - if (e.shiftKey) handlers.share?.(e); - else handlers.sidebar?.(e); + if (e.shiftKey) { + if (handlers.isImageMode?.()) { + handlers.toggleSlideshow?.(e); + } else { + handlers.share?.(e); + } + } else { + handlers.sidebar?.(e); + } return; } @@ -174,8 +217,7 @@ export function initKeyboard(handlers) { case 'Escape': handlers.escape?.(e); break; case 'Backspace': handlers.backspace?.(e); break; case 'r': handlers.shuffle?.(e); break; - case 's': handlers.sidebar?.(e); break; - case 'S': handlers.share?.(e); break; + // Note: 's' / 'S' are handled above by the e.code === 'KeyS' block case '/': e.preventDefault(); handlers.search?.(e); |
