Commit Graph
55 Commits
Author SHA1 Message Date
LeoVasanko cac3348ec1 Fix detail-view focus scope and entry targets 2026-05-29 18:18:30 +00:00
LeoVasanko 0b3cd15589 feat: configurable media player selection with auto-detection
Backend:
- Add mediahive/players.py with cross-platform player detection:
  - Windows: MPC-BE, MPC-HC, VLC, PotPlayer, mpv (registry + known paths)
  - macOS: IINA, VLC (/Applications bundle scanning)
  - Linux: VLC, SMPlayer (PATH via which)
- Add GET /api/players endpoint returning detected players
- Extend POST /api/roots/{id}/play to accept player_id and player_custom_cmd
- Make MPC-BE web UI port configurable via ?port= query param

Frontend:
- Add player selection to settings (localStorage, per-client)
- Two-column layout: player list (9.5em) + contextual options panel
- Contextual options: Custom Command input, MPC Web UI Port input
- Empty MPC port disables all Web UI polling/connection attempts
- MPC-BE polling only runs when MPC family player is selected and port is set
2026-05-29 00:44:23 +00:00
LeoVasanko ed4a5b2900 Route settings dialog to /settings and fix worker null handling 2026-05-27 21:58:09 +00:00
LeoVasanko 1383fc8da3 Add preferred format settings and release preference sorting 2026-05-27 21:52:36 +00:00
LeoVasanko a0d1433154 Switch SPA navigation to history paths 2026-05-27 21:21:49 +00:00
LeoVasanko 29cda926a2 Improve search-detail back navigation and focus restore 2026-05-27 21:12:39 +00:00
LeoVasanko e78774613a More compact and consistent layout for the release badges. Bluer release group color. 2026-05-27 20:50:43 +00:00
LeoVasanko 96c2d52ee0 perf(frontend): fix resource leaks and disable deep reactivity on media index
- useMediaWebSocket: shallowRef mediaIndex/tasks/loading/error/connected
  to eliminate Proxy overhead on the entire library data structure.
- useMediaWebSocket: replace per-task setTimeout leak with single 3s
  sweep interval for completed task cleanup.
- App.vue: remove {deep:true} watcher on mediaIndex; shallow ref change
  is sufficient to trigger search worker sync.
- useGamepadNavigation: rAF only when gamepads are connected; idle
  fallback to 500ms setTimeout to stop permanent 60fps CPU drain.
- useKeyboardNavigation: deduplicate synced scroll rAF requests to
  prevent overlapping animation frames.
- MediaDetail/SeriesFullView/CollageHero: pause, clear src, and load()
  video elements on unmount and before ref replacement to release
  decoder/memory resources.
- MediaDetail/SeriesFullView: clear all volume fade intervals on
  unmount to stop interval timer leaks.
2026-05-27 20:28:51 +00:00
LeoVasanko f982785850 Fix HexKeyboard X/Y gamepad keypress animations 2026-05-27 14:28:08 +00:00
LeoVasanko cf2b90809a HexKeyboard: refactor to row-based flex layout
Replace 39 per-key absolute positioning CSS rules with 4 row divs
using flexbox. Rows overlap via negative margin-top to preserve
honeycomb staggering. Horizontal offsets via 4 margin-left rules.

- Add RowKeyDef with globalIndex for row-based rendering
- Add rows computed to group layoutKeys into 4 arrays
- Remove all .hex-key-N { top; left } positioning rules
- Keys are now flex children, position: relative, fixed width

Also includes prior changes:
- Row-based greyscale gradients (lighter top, darker home row)
- Per-key re-triggerable press animation (DOM reflow reset)
- Green-to-white exponential fade on keypress
- Gamepad repeat: 90ms horizontal/buttons, 140ms vertical
2026-05-26 16:37:12 +00:00
LeoVasanko 43ca8ea1d1 Implement OSD keyboard for gamepads. Using hex tiles of course. 2026-05-26 04:52:13 +00:00
LeoVasanko 7fa8ddad65 Fix movie details header layout and space division with cast display. 2026-05-25 19:21:21 +00:00
LeoVasanko f219840967 refactor(synced-scroll): rewrite with global metrics + per-row clamping
Replace the fragile per-row tail/maxVirtual state with a clean global-
metrics approach:

- Measure cardWidth, stride, paddingLeft, viewportWidth, rightDeadzone
  once from the first synced row; use the same values for all rows.
- Per-row max scroll computed purely from math:
    max(0, paddingLeft + (N-1)*stride - maxVisibleLeft)
  where maxVisibleLeft = viewportWidth - cardWidth - rightDeadzone.
- Global virtual offset (syncedRowsCurrentOffset/targetOffset) is shared
  across all rows; each row clamps independently in applySyncedRowScroll.
- Tail is a global constant (= rightDeadzone) applied to all rows.
- Fix scrolling-back bug: desiredOffset was stuck at currentOffset when
  moving left; now always computed from anchor column position.
- Avoid full animation sweep on view entry: init current/target offset
  from existing DOM scrollLeft on first use.

Also removes per-row --sync-row-max-virtual CSS var and simplifies
.media-row padding to use only --sync-row-tail.
2026-05-25 18:54:21 +00:00
LeoVasanko fbf35f7242 Refine movie detail cast rail and nav behavior 2026-05-25 16:18:35 +00:00
LeoVasanko ab1dfffdf3 Restore flex-based people layout in media cards 2026-05-25 15:45:13 +00:00
LeoVasanko f484ab2606 Clean up movie details metadata layout 2026-05-25 15:24:05 +00:00
LeoVasanko f39473e26e Link header logo to front page 2026-05-25 14:52:36 +00:00
LeoVasanko cfa1781192 refactor: hero featured item is a plain link like all other cards
Remove the separate Play and Info buttons from the CollageHero featured
item. All collage items (including the featured one) are now uniform
<a href> links that navigate to the detail page.

- CollageHero: remove hasResumePosition prop, play/info emits, and
  associated play button logic
- App.vue: remove @play and @info bindings from CollageHero
- Delete unused HeroSection.vue component and its styles
2026-05-25 14:25:58 +00:00
LeoVasanko 76c426546b refactor: media cards use proper <a href> links instead of JS navigation
MediaCard, MediaRow, CollageHero, HeroSection, and MediaDetail cast
cards now render as <a> tags with real hrefs. Modified clicks
(ctrl+click, middle-click) navigate natively, enabling open-in-new-tab
and link copying. Plain left-clicks continue through the existing
showDetail flow for side-effects like focus-state saving.
2026-05-25 14:21:13 +00:00
LeoVasanko 0330a3023a frontend: clamp series hero synopsis to 10 lines 2026-05-25 13:11:12 +00:00
LeoVasanko 1cf3e6a08f frontend: place releases beside poster on narrow movie detail 2026-05-25 13:11:08 +00:00
LeoVasanko 17f8f60f6e fix: constant slant angle for season poster collage hero
The clip-path slant on collage slices previously varied with the number
of posters (hard-coded 10% steps). Express the slant as a percentage
of each slice's own width so the horizontal offset always equals the
fixed 5% container overlap, giving a constant angle for any count >= 2.
2026-05-25 13:02:15 +00:00
LeoVasanko 23379dc2c1 frontend: reduce movie detail poster width under 900px 2026-05-25 03:31:35 +00:00
LeoVasanko f6a40babc9 frontend: add OXC lint/format setup and apply semicolon fixes 2026-05-25 02:54:30 +00:00
LeoVasanko 94f2f10dcd Fix root path handling and release action menus 2026-05-24 17:40:55 +00:00
LeoVasanko 4097c3c9ac ui: replace folder dropdown with full-screen settings view
- Change header icon from folder to settings cog
- Replace roots dropdown panel with full-screen settings overlay
- Keep media roots as the only setting section for now
2026-05-23 22:23:16 +00:00
LeoVasanko 9c75fa4569 refactor: remove legacy single-root APIs, defer filesystem I/O, enforce POSIX paths
- Remove legacy endpoints: /api/change-folder, /api/index, /api/scan, /api/status,
  /api/playback/resume-positions
- Remove legacy global scanner module-level API from hivescan/scanner.py
- Defer all filesystem validation to background task in server lifespan (macOS-safe)
- CLI and winmain pass raw paths via MEDIAHIVE_ROOTS; no pre-startup validation
- Enforce POSIX paths everywhere (as_posix(), no backslash leakage)
- Remove MEDIAHIVE_PATH and MEDIAHIVE_DEFER_INITIAL_ROOT env vars
- Update frontend api.ts to use per-root resume positions
- Update docs/API.md and docs/multi-index-plan.md
- Fix Python 2 style except clauses in hivescan/utils.py and scanning.py
2026-05-23 22:21:35 +00:00
LeoVasanko 2f83193ff4 fix: use html classes instead of :global() for input modality styles
The :global() pseudo-class in Vue scoped SFC styles was being mangled
by the Vue compiler, producing broken CSS that applied properties like
z-index and opacity directly to the <html> element and dropped the
intended component selectors entirely.

Replace the html[data-mouse-active] / html[data-pointer-visible] data
attribute approach with plain CSS classes (mouse-active, pointer-visible)
toggled on document.documentElement. In Vue scoped styles, prefixing a
selector with html.mouse-active or html:not(.mouse-active) compiles
correctly — the html part stays global while the component selector
receives the scoped attribute — avoiding :global() entirely.

This keeps all component styles inside <style scoped> and fixes the
layout breakage caused by the original commit.
2026-05-23 21:57:59 +00:00
LeoVasanko 79dc1b25cc Fix search exit flow and history behavior 2026-05-23 20:33:48 +00:00
LeoVasanko 0f404e5e53 Refine input modality to prevent hover/focus highlight conflicts 2026-05-23 18:58:53 +00:00
LeoVasanko 52ce50e548 style(ui): refine release badge order, spacing, and palette 2026-05-23 03:21:17 +00:00
LeoVasanko b8e23587b8 feat(ui): refine source logos and normalize TV/CAM quality badges 2026-05-23 03:01:40 +00:00
LeoVasanko fbfe05588d feat(ui): show WEB provider logos from PTN network metadata 2026-05-23 02:41:08 +00:00
LeoVasanko 6820937a4b feat(ui): add DVD disc icon and strict disc-file logo rules 2026-05-23 02:17:45 +00:00
LeoVasanko 00454f0929 fix(hivescan): prefer MovieObject and probe Blu-ray streams 2026-05-23 01:08:07 +00:00
LeoVasanko 6b74a6d308 feat(ui): add Blu-ray disc logo badge for disc releases 2026-05-23 00:38:27 +00:00
LeoVasanko 04aa858338 feat(ui): refine detail navigation and cast row layout 2026-05-22 21:20:05 +00:00
LeoVasanko 491e707b6f refactor(ui): anchor detail header darkening to reel geometry 2026-05-22 19:20:59 +00:00
LeoVasanko c3dee9bed9 feat(series): improve release popup navigation and controls 2026-05-22 18:48:34 +00:00
LeoVasanko a748adf87e feat(ui): redesign release card presentation 2026-05-22 18:26:29 +00:00
LeoVasanko eeed9f3ef7 Implement Safari video startup fixes and range streaming support 2026-05-21 04:06:44 +00:00
LeoVasanko 2e9928a411 Scope reel poster fallback to browser cards 2026-05-21 02:38:39 +00:00
LeoVasanko e40c953617 Movie details layout
- Grid layout: poster/releases left, cast spanning center+right top, versions center, metadata right
- Cast gallery moved to wider center column with photo-card grid (2:3 aspect, text overlay)
- Full cast now stored in index (removed 10-item truncation)
- Cast gender field added to metadata model, TMDB client, indexer, and frontend types
- Gender-specific cast placeholder SVGs (male suit silhouette, female portrait)
- Synopsis text moved from left poster box into right metadata card
- Format badge backgrounds made opaque (res/qual/codec/audio solid colors)
- Releases list moved under poster image in left column
- Cast photo and character font sizes reduced for compact display
2026-05-21 00:43:09 +00:00
LeoVasanko 7aeec90e4f Add slash key to access search. 2026-05-20 04:11:52 +00:00
LeoVasanko 5bb46c162e Implement synced category row scrolling. 2026-05-16 23:00:54 +00:00
LeoVasanko 81fbfee5d3 Fix hero gamepad focus activation. 2026-05-16 22:35:31 +00:00
LeoVasanko c405ea98b3 Add MPC-BE remote control and resume support. 2026-05-16 22:25:54 +00:00
LeoVasanko 5063bbc8c8 Add Windows GUI
- mediahive/winmain.py: pywebview launcher with threaded uvicorn backend,
- scripts/winbuild.py: build script — downloads ffmpeg, runs PyInstaller, makes zip
- mediahive/config.py: TOML config persistence in %APPDATA%/mediahive/
- server.py: POST /api/change-folder switches media root
- showreel.py: suppress console windows for ffmpeg subprocesses on Windows
- protocol.py: add ChangeFolderRequest struct
2026-05-14 04:27:46 +00:00
LeoVasanko 903e9f0c24 Fix newlines (LF only). 2026-05-04 02:07:44 +00:00
LeoVasanko e533931048 Fix navigation downwards from hero section that was leaving a focus marker on the bottom row tile. 2026-05-04 02:03:22 +00:00