Commit Graph
116 Commits
Author SHA1 Message Date
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
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 8586bd26e1 Remove PWA/SW and fix blocking startup I/O
- Remove vite-plugin-pwa and all service worker code. The app no longer
  registers a service worker; legacy SWs are unregistered on load.
- Move snapshot parsing (thousands of sync Path.exists() calls) into a
  thread pool via asyncio.to_thread() so the health check responds
  immediately on startup.
- Wrap aiopathlib AsyncPath.iterdir() (sync os.scandir under the hood)
  in asyncio.to_thread() in scanner and scanning modules so directory
  walks do not monopolize the event loop.
2026-05-24 19:01:13 +00:00
LeoVasanko 94f2f10dcd Fix root path handling and release action menus 2026-05-24 17:40:55 +00:00
LeoVasanko 487e410a8f Remove scrollbar. 2026-05-24 02:49:57 +00:00
LeoVasanko 36fc2a77d9 feat: merge duplicate items across roots with combined releases
- Add root_id to Torrent type for per-torrent root tracking
- Merge movies: combine all torrents, keep best metadata, sort by quality
- Merge series: combine seasons/episodes/torrents across roots
- Torrents are quality-sorted (resolution, HDR, DV, Atmos) across all roots
- App.vue play/openFolder use torrent-specific root_id when available
2026-05-24 02:37:09 +00:00
LeoVasanko 06565f688c feat: deduplicate movies/series across roots in merged index
Items with the same content hash from multiple roots are now shown as a
single card. When duplicates exist, the item with the best metadata
(info, cover, backdrop, showreels, torrent count) is displayed.
2026-05-24 02:24:36 +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 0b5c47f4d1 Normalize path search separators 2026-05-23 17:28:47 +00:00
LeoVasanko 169eb122b5 Improve media search ranking 2026-05-23 17:23:57 +00:00
LeoVasanko 4ac40e3585 fix: more consistent synced row scrolling 2026-05-23 03:43:48 +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 0660b4e9d2 Use ffmpeg parsing for media probe metadata and remove ffprobe bundling 2026-05-22 03:08:36 +00:00
LeoVasanko 7eb81877fd Add Qt mac backend support, Safari/Chrome playback fixes, and AV1 reel updates 2026-05-22 01:39:28 +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