Commit Graph
76 Commits
Author SHA1 Message Date
edde746 69fadc220d chore: clean up code comments 2026-08-10 20:28:41 +02:00
edde746 e3703892b3 fix(player): keep a keyboard Enter out of focus navigation
Pressing Enter over the player put the whole app into keyboard mode and
dropped focus onto Play/Pause, even with Video Player Navigation off. Two
independent paths did it. InputModeTracker promoted on any key satisfying
isNavigationKey, a set that unioned activation, dismissal and the menu key
with the arrows and consulted no setting at all; separately the surface's
Select handler always asked the chrome for focus. Escape had the same effect,
which on desktop reads as the mouse cursor vanishing mid-playback.

Both now ask one predicate. eventRequestsFocusNavigation decides whether the
app switches to keyboard mode and whether a key may hand focus to the chrome,
so the two cannot disagree and focus can never land on a control while focus
chrome is still suppressed. Activation and dismissal act on what already has
focus, so they answer no; Tab, the menu key, a remote's OK or BACK, and an
arrow that will really traverse answer yes. The one input the predicate cannot
read off the event, whether the focused feature owns arrow keys, rides on the
node as DirectionalShortcutFocusNode instead of on a subtree, so every sheet,
prompt and OSD button stays an ordinary traversal target with nothing to
re-enable.

playerDirectionalNavigationEnabled and videoPlayerNavigationPreference replace
five hand-copied pref-or-isTV expressions and a screen-level cache that
disagreed with the live getter after a toggle. Services whose input is
synthesized past HardwareKeyboard announce themselves through
InputModeTracker.reportNonPointerInput rather than two static callbacks and
three copies of a highlight-strategy write. That registration is now
identity-guarded: the bootstrap-to-app tree swap disposed the outgoing tracker
after the incoming one initialised and cleared both callbacks, so gamepad and
companion remote input had stopped switching to keyboard mode entirely.

Falling out of the same rule: a companion heartbeat no longer flips an idle
desktop host into keyboard mode, analog-stick drift promotes only past the
deadzone that actually navigates, Enter keeps toggling playback once the
chrome is up, Tab both reaches and traverses the OSD, and the player surface
claims the remote from mount rather than only when the chrome starts hidden,
so the first key on a desktop route is a playback shortcut instead of the
screen node's chrome-raising self-heal.

isNavigationKey becomes isReservedControlKey, since its real meaning is a
shell key rather than a text character and the old name is what invited the
conflation. The unreachable PlayerChromeFocusTarget.timeline goes with it.
2026-08-07 13:23:53 +02:00
edde746 4816e3928f fix(player): skip relative to the position a jump landed on
A coalesced key-repeat skip pins its target so a slow backend cannot make
the next press rebase off a position the seek has not reached yet. Nothing
retired that pin when something else moved the playhead, so for the ten
seconds it survived, a skip taken after a timeline tap, a chapter jump, an
OS media control or a peer sync resumed from the superseded target and threw
the user back across their own jump.

Publish every playhead movement on the player and retire the pin whenever
the announced destination is not the accumulator's own commit. Overlapping
seeks and backend-chosen relocations arbitrate by which operation the
backend accepted, so a request that was merely asked for cannot speak for
where the playhead ended up.

close #1819
2026-08-07 08:43:48 +02:00
edde746 352b88109b refactor: extract shared mixins and helpers, drop dead abstractions
Introduces shared seams for paginated views, D-pad reorder, media control
routing, async singletons and the device method channel, then points the
open-coded copies at them.

Also removes unused models and duplicated provider/server plumbing, folds
the twice-implemented artifact store in the server, and factors the
repeated Flutter toolchain prologue in CI into a composite action.
2026-07-26 06:09:48 +02:00
edde746 e0bf66eea8 fix(runtime): harden application service boundaries 2026-07-24 03:46:46 +02:00
edde746 d5f3e581df fix: eliminate cross-app consistency drift 2026-07-13 23:13:53 +02:00
edde746 e4db04fa62 fix: align UI focus and sheet behavior 2026-07-13 11:28:32 +02:00
edde746 d1c4ae83eb fix(review): resolve post-consolidation regressions 2026-07-12 17:31:16 +02:00
edde746 7ecadffdb1 refactor(features): consolidate shared feature primitives 2026-07-12 17:31:13 +02:00
edde746 8a8b4f3a61 refactor: remove unused convenience APIs 2026-07-12 08:42:20 +02:00
edde746 cdec9d1514 refactor(player): centralize chapter traversal 2026-07-12 08:42:20 +02:00
edde746 4443b76145 fix(player): respect visible chrome on back 2026-07-11 17:38:22 +02:00
edde746 f9abcd44fe fix(playback): hold timeline preview until playback settles at the target
The preview cleared unconditionally 2s after a committed seek; on a device
still buffering, the live position hasn't caught up yet, so the next key
press re-based off the stale position and re-targeted the same spot -
discarding the seek exactly on the slow hardware the coalescing targets.
Re-arm the clear until the live position is near the target, with a 10s
ceiling backstop (same settle pattern as LiveSeekAccumulator).
2026-07-04 22:58:19 +02:00
edde746 3cad91736b fix(playback): raise timeline scrub debounce above the key-repeat delay
350ms sits below the typical KeyDown-to-first-repeat gap (~400-500ms on
Android/TV), so every hold committed an intermediate seek before repeats
even began. 800ms matches Jellyfin ATV (media3's DefaultTimeBar uses 1s);
key release still flushes synchronously, so taps are unaffected.
2026-07-04 22:57:27 +02:00
Christian Tismer ed843b4b89 fix: coalesce held timeline seeks on direct play
A held fast-forward fired a real seek on every key-repeat for direct/
progressive streams, flooding the source with overlapping range requests and
wedging low-power devices (e.g. Fire TV Stick) in BUFFERING until the player
was restarted. Route direct play through the same preview/debounce path the
transcode case already uses: move only the timeline preview while the key is
held and commit a single seek on release or pause.

close #1424
2026-07-04 22:56:43 +02:00
edde746 7195702242 fix(player): repair Plex transcode seeking
close #1341
2026-06-14 23:39:05 +02:00
edde746 5e2bd4efa8 fix(video): release scrub chrome hold
close #1340
2026-06-14 18:34:12 +02:00
edde746 f74314bbf0 fix(livetv): debounce rapid time-shift skips to stop overshoot 2026-06-06 10:48:51 +02:00
edde746 74b8dc4561 refactor: type server identifiers 2026-06-01 11:06:03 +02:00
edde746 c93a266722 fix(plex): support no-burn transcode subtitles 2026-05-20 17:21:31 +02:00
edde746 3a6012cc21 fix(lifecycle): guard async state updates 2026-05-12 06:11:14 +02:00
edde746 5401b5005f perf(player): reduce timeline layout churn 2026-05-09 10:02:32 +02:00
edde746 1f09c07e96 feat(player): toggle chapter timeline markers
close #973
2026-05-06 05:26:47 +02:00
edde746 31d2d9dc98 feat: jellyfin 2026-05-01 01:20:36 +02:00
edde746 fd1d187ede feat: timeline thumbnail on dpad key-repeat
close #805
2026-04-19 12:24:14 +02:00
edde746 c6f2e949a7 fix: use configured skip setting for dpad/timeline seeking
close #751, close #790
2026-04-10 22:31:41 +02:00
edde746 627024bd13 fix: reduce spacing 2026-04-06 03:02:36 +02:00
edde746 16dd352231 fix: hide live badge when timeshifted
close #796
2026-04-02 17:35:52 +02:00
edde746 c57cbfb2f6 fix: live TV time-shift controls and timeline 2026-04-02 02:29:04 +02:00
edde746 3f1da5f289 feat: live TV time-shift 2026-04-01 12:20:07 +02:00
edde746 ac397f32a3 feat: redesign TV player controls
- BACK key dismisses layers (content strip → controls → exit) with
  early BackKeyCoordinator marking to prevent PopScope race condition
- Hide volume control and PiP button on TV
- Fix focus chain with mounted-node-aware navigation for live/non-live
- Fix focus reclaim on controls hide (hasPrimaryFocus vs hasFocus)
  to prevent screen-level self-heal from stealing timeline focus
- LEFT/RIGHT shows controls with timeline focused for seeking

Close #701
2026-03-15 03:10:51 +01:00
edde746 0fc64cdf81 fix: catch seek PlatformException at source, remove coordinator
Catch COMMAND_FAILED/NOT_INITIALIZED in PlayerNative.seek() and
PlayerAndroid.seek() directly, preventing unhandled PlatformException
crashes on macOS app resume. Remove the ~200-line
_PendingSeekCoordinator system and revert all callsites to direct
player.seek(clampSeekPosition(...)). Keep seekable property/stream
and media controls gating. Add ExoPlayer seekable emission.
2026-03-09 07:21:36 +01:00
edde746 5be7b43cb8 fix: improve content strip text visibility
close #656
2026-03-09 01:04:14 +01:00
edde746 c56e73eefe feat: add content strip for dpad navigation 2026-03-07 20:17:28 +01:00
edde746 c1e2bc36ea refactor: share Apple MPV core and media helpers 2026-03-06 10:16:33 +01:00
edde746 13b5d7bae8 feat: secondary subtitle tracks
close #625
2026-03-04 09:35:36 +01:00
edde746 94395feaba feat: implement sub-visibility toggle
Closes #597
2026-03-02 19:07:56 +01:00
edde746 5ab6af1b02 feat: respect system 24h time format setting
Closes #605
2026-03-02 18:19:52 +01:00
edde746 8d3f448fdf feat(macos): add picture-in-picture support 2026-03-02 18:19:36 +01:00
edde746 00667fe8b8 fix: add const constructors and remove unused imports 2026-02-27 15:43:34 +01:00
edde746 edb285a279 feat: cache BIF file for instant preview thumbnails
close #565
2026-02-27 15:30:29 +01:00
edde746 98776b40f5 fix: show sync controls as compact top bar
close #548
2026-02-26 03:41:19 +01:00
edde746 0159c18497 feat: discontinuous buffer ranges on timeline 2026-02-21 04:50:10 +01:00
edde746 756eb8d6f0 feat: add ambient lighting effect
close #477
2026-02-18 06:51:20 +01:00
edde746 04438c8e45 refactor: code quality & format 2026-02-15 04:07:09 +01:00
edde746 9184bb8d40 Merge branch 'live-tv'
# Conflicts:
#	lib/i18n/strings.g.dart
#	lib/i18n/strings_de.g.dart
#	lib/i18n/strings_en.g.dart
#	lib/i18n/strings_es.g.dart
#	lib/i18n/strings_fr.g.dart
#	lib/i18n/strings_it.g.dart
#	lib/i18n/strings_ko.g.dart
#	lib/i18n/strings_nl.g.dart
#	lib/i18n/strings_sv.g.dart
#	lib/i18n/strings_zh.g.dart
#	lib/screens/main_screen.dart
#	lib/services/plex_client.dart
#	lib/widgets/video_controls/desktop_video_controls.dart
2026-02-14 22:29:16 +01:00
edde746 426f6ab6ba fix(tv): misc improvements 2026-02-13 00:01:54 +01:00
edde746 eb644c0194 fix(tv): hide seek/skip controls during live playback 2026-02-12 14:21:21 +01:00
edde746 a1d78562d6 fix(tv): playback 2026-02-12 03:52:51 +01:00
Micah Morrison 2509cb8193 Show previous and next chapter names as tooltips 2026-02-11 17:43:25 -05:00