Commit Graph
100 Commits
Author SHA1 Message Date
LeoVasanko 7a0247d78f Refine hover reel audio fades and idle behavior 2026-05-30 04:38:33 +00:00
LeoVasanko bb4bd3723f Improved serie episode preview video handling 2026-05-30 04:28:34 +00:00
LeoVasanko 7675940029 Implement JS-driven season poster sizing from episode grid remainder 2026-05-30 04:19:14 +00:00
LeoVasanko 613b516785 Fix series preview videos to render paused frames and stagger active season 2026-05-30 04:13:05 +00:00
LeoVasanko 2f72d1e7e2 Fix series full view vertical navigation to follow episode rows 2026-05-30 04:05:20 +00:00
LeoVasanko b51a7ea73d Separate scrolling for browse and details page even though they are laid out side by side on the layout (with one hidden out of screen). 2026-05-30 04:00:53 +00:00
LeoVasanko fe5be2087d Refine movie similar strip and desktop nav flow 2026-05-30 03:50:28 +00:00
LeoVasanko 46eecd8dbf Add related movies on Series page. Uses heuristics to show serie movies only. 2026-05-30 03:36:35 +00:00
LeoVasanko c2ee25ba3d Fix synced row deadzone behavior and isolate cast scroll metrics 2026-05-30 02:57:34 +00:00
LeoVasanko 649992a10a Align frontend with new cast and people wire format 2026-05-30 02:40:36 +00:00
LeoVasanko ada61e1400 Remove long hex root ids and use only friendly names 2026-05-30 02:28:58 +00:00
LeoVasanko 3551808351 Fix root-relative playable path normalization 2026-05-30 02:19:33 +00:00
LeoVasanko 0ef6896181 Refactor API to flat root routes and WS/meta structure 2026-05-30 02:09:24 +00:00
LeoVasanko 352835a664 Add logical root asset URLs and harden media path serving 2026-05-30 01:36:47 +00:00
LeoVasanko 900fcea638 refactor index schema and metadata format and directory tree 2026-05-30 01:05:27 +00:00
LeoVasanko 550f67531a Faster startup by loading existing index without any checks, then incremental scanning to update. 2026-05-29 22:25:13 +00:00
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 fe71e1be8b Remove search worker debug logging 2026-05-27 21:23:48 +00:00
LeoVasanko a0d1433154 Switch SPA navigation to history paths 2026-05-27 21:21:49 +00:00
LeoVasanko 02a89aee68 Use /search/:term path-based search routing 2026-05-27 21:15:58 +00:00
LeoVasanko 29cda926a2 Improve search-detail back navigation and focus restore 2026-05-27 21:12:39 +00:00
LeoVasanko 81be850e0c Sliding layout between details and category views. 2026-05-27 20:58:19 +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 79d3f40162 Unify gamepad repeat model with accelerating hold and analog scaling 2026-05-27 14:40:49 +00:00
LeoVasanko f982785850 Fix HexKeyboard X/Y gamepad keypress animations 2026-05-27 14:28:08 +00:00
LeoVasanko 4c33cee4ac Move frontend search to worker and improve people-name matching 2026-05-26 20:43:10 +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 8cb7ab5938 Adjust no search results label. 2026-05-26 04:49:28 +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 eee8c973ed fix: per-row tail padding for synced horizontal scroll
- Tail is now computed and applied per-row instead of globally.
- Right-side-only tail padding so item positions don't shift when tail grows.
- Removed anchor-row clamping from effectiveAnchorOffset and targetOffset;
  each row independently clamps the shared virtual offset.
- Rows that fit entirely on screen (maxOffset == 0) keep left alignment.
- Short rows retain their scrolled position when focus moves to longer rows.

Fixes erratic scrolling and zig-zag when navigating across rows of different
lengths in movie/series/search categories.
2026-05-25 17:30:06 +00:00
LeoVasanko a3f5ef5dac Smooth-scroll focused release items into view 2026-05-25 16:20:50 +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 5b57640949 fix: clicking search result no longer redirects to category page
When clicking a search result, showDetail navigates to the detail page.
The route.fullPath watcher then clears searchQuery, which propagates to
Header's localSearch watcher, which emits @search='', which calls
updateSearchQuery(''). This in turn called clearSearch(), which did a
router.replace() to the category page because it didn't check whether
the current route actually had a search query.

The fix: in clearSearch(), if there's no search query in the current
URL, just clear reactive state and return without navigating. This
breaks the circular flow that was overwriting the detail-page
navigation.
2026-05-25 15:32:33 +00:00
LeoVasanko f484ab2606 Clean up movie details metadata layout 2026-05-25 15:24:05 +00:00
LeoVasanko 598cef8926 Adjust media row edge spacing without section padding 2026-05-25 14:57:42 +00:00
LeoVasanko f39473e26e Link header logo to front page 2026-05-25 14:52:36 +00:00
LeoVasanko 31fedcea6c Disable browser fullscreen auto-toggle 2026-05-25 14:49:31 +00:00
LeoVasanko b8cdd460b6 Scroll to view only on mouseup to avoid erratic scrolling during clicks. 2026-05-25 14:43:16 +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 1d3d682b60 fix: don't steal focus from search input during focus restoration
When typing in the search bar on a detail page, navigating to search
results would trigger restoreFocusForPage(), which focused the 'last
viewed' card and interrupted typing. Skip focus restoration whenever
the search input is currently the active element.
2026-05-25 13:20:38 +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