feat(Player Shortcuts): Add the shortcut control functionality to player controls - #594
Conversation
|
Looks good overall, but please keep the current left-click play/pause behavior and Escape-to-exit-fullscreen behavior. This PR currently removes the left-click toggle and makes Escape always go back. |
|
@KhooLy do still want to revert it. after my explanation why it changed. |
|
Please rebase onto current Dev and keep the existing left-click play/pause and Escape-to-exit-fullscreen behaviors. Those are currently regressed by this PR. |
I can revert the play/pause to left click but esc to go back should be as my PR is correct esc is correct behavior because when to exit fullscreen F and F11 can be used but to close the player window what is use there is no option in keyboad to close player via keyboard
|
|
Yes, please revert both. Escape is intentionally layered: it closes a modal first, exits fullscreen second, and goes back from the player when already windowed. So the player is still fully closable from the keyboard — from fullscreen, pressing Esc twice exits fullscreen and then leaves the player. F/F11 are additional fullscreen shortcuts, not a replacement for the standard Esc behavior. Please also keep left-click play/pause as requested. |
But my real Q. is what is the option to close the player via keyboard instead then. |
|
You should make exiting the player be the backspace key that way it doesn't conflict with esc and fullscreen |
|
The keyboard option to leave the player is still Escape when the player is windowed. In fullscreen, Escape first exits fullscreen, then a second Escape leaves the player. I don't want to add Backspace as a separate player-back shortcut just to bypass that layered behavior. |
|
But then how do you expect people with HTPC who use only the keyboard to efficiently use keys? Every time you'd want to exit the player you have to click esc and leave fullscreen first? That seems counterintuitive |
|
Nuvio Desktop isn't designed around HTPC-only keyboard navigation, and pressing Escape twice from fullscreen is not a significant usability burden. I don't want to change the standard Escape behavior for that edge case. |
this is the reason why I made the esc to go back as it is correct. |
I got it you always use the nuvio app in windowed mode and watch the video player in Fullscreen esc return to windowed is correct according to u but I use nuvio app in fullscreen not just player so esc means just close player is correct to me. so the people who use app in fullscreen not not esc to exit fullscreen because after close the player they have to toggle to fullscreen again form the windowed and visa versa for people who use app in windowed mode. I have new solution that please both kind of user.
@KhooLy what do u think? |
|
I understand the distinction now, but I don't want to add launch-state-dependent Escape behavior to this PR. Please keep the existing Escape behavior here. If preserving app fullscreen when leaving the player is a real issue, let's handle that separately as a dedicated fullscreen-state fix. |
Refactor speed boost handling and clear timers for improved performance.
reverted both sucessfully. |
|
The requested left-click and Escape behavior are fixed now, thanks. One remaining issue: plain F no longer toggles fullscreen, even though this PR says it fixes #456 and lists F as tested. Please restore the plain F shortcut without changing the current Escape behavior. Also please remove unrelated Fixes references for issues this PR does not actually implement. |
this PR indeed fixed issue #456 (just test again this "F" working on my debug build) this not fixes #91 that I removed form PR description. Recording.2026-09-05.181408.mp4 |
|
The video may be from a local/debug build, but the current pushed head still has no plain KeyF handler, it only handles F11 and Ctrl+Cmd+F. Please make sure the working F change is actually pushed to the PR. Also, #91 was removed, but there are still other unrelated Fixes references such as #311 and #451. (I tested "F" and didnt work.) |
this working on Windows the mac issue fixes via PR #608 |
#311 shortcut to change playback is added (not used X C Z but added batter YouTube style Shift+< or > added and for reset /) |
|
#311 and #451 still should not be marked as fixed. #311 specifically asks for X/C/Z bindings, 0.1x speed steps, and Z toggling between 1.0x and the last non-default speed. This PR adds different shortcuts, so it is related, but does not fully fix that issue. #451 is specifically about hardware media keys such as Play/Pause, Stop, Next and Previous. Regular keyboard shortcuts inside controls.js are not the same thing. Also I'm not sure how "F" key works for you, it doesnt work for me. i didnt see anything related to that in code too. |
F key is working as I show the evidence video. |
|
Thanks for the updates. I did another full pass over the current code and there are still a few keyboard navigation regressions I’d like fixed before merging. Please restore the text-entry guard so shortcuts don’t interfere with inputs, scope the arrow-key focus navigation to the active modal instead of moving through every focusable element in the whole player, and make Enter trigger Skip Intro only when the player/root has focus so it doesn’t override Enter on focused buttons. The source-list virtualization and F behavior can be handled separately if needed. Once those focus/input issues are fixed, I’m fine with merging this. |
that intentional to move focus for hands free use, |
|
I understand that moving focus is intentional, but the issue is the scope, not the idea itself. Right now the arrow handler can take over arrow keys even when a text input, slider, or unrelated player control has focus, so it changes existing seek/volume/input behavior. You can keep the hands-free focus navigation, just limit it to the active modal and keep the text-entry guard so normal controls still behave normally. The Enter/Skip Intro conflict is separate and should also be guarded so Enter still activates a focused button. |
No, this not affect to other key binding such as volume and seek the navigation arrow keys is just activate when the audio, subtitle, source episode and playback speed panel is visible Enter only triggers skip when the skip intro/recap/outro prompt is actually showing on screen. At all other times, Enter does nothing. |
|
@KhooLy all tested works as expected now its ready for merge. |
|
Thanks, most of the issues are fixed now. I checked the latest commit and there are just two things left: the generic arrow-key focus handler still has no activeModal guard, so it can still override seek/volume when a normal player control has focus, and Enter still overrides a focused button whenever the skip prompt is visible. Please scope the generic arrow navigation to an active modal and don’t intercept Enter when another interactive control has focus. After that I’m good to merge. |
|
One small localization thing: please don’t hardcode Muted, Volume, Volume up, or Volume down in controls.js. We already have localized compose_player_muted and compose_player_volume_level strings, and the actual volume percentage is available, so just pass those localized labels into the player state and show the percentage instead of using the English Volume up/down fallbacks. |
Refactor event handling for arrow keys and Enter key to check active element conditions.
Done. |
Done. |
|
The keyboard fixes look good now, but the localization change isn’t actually wired up yet. controls.js reads state.mutedLabel and state.volumeLevelLabelFormat, but this PR still only changes controls.js and those values are never passed from Kotlin, so it will always fall back to the hardcoded English Muted / Volume %s. Please pass compose_player_muted and compose_player_volume_level through PlayerControlsState/the player JSON state as well. Also please remove english hardcoded fallbacks. |
Updated volume toast label strings to empty defaults.
check now |
Done but please close them as completed. |
|
Two small things left: your newly added plain F shortcut should respect the text-input guard, and modal arrow navigation should query focusable elements inside the active modal instead of the whole document. |
Refine fullscreen toggle conditions and modal focus handling.
Done. |
Summary
This PR vastly expands the keyboard accessibility and shortcut functionality of the desktop video player, mirroring power-user features found in modern media players and smart TV interfaces. It implements over a dozen new hotkeys, adds intelligent smart-focus logic for side panels (episodes, sources, subtitles, audio, speed), introduces instant-apply navigation for specific modals, and fixes several focus clipping and asynchronous state-sync bugs.
PR type
Why
Desktop users lacked a comprehensive set of hotkeys to control playback, UI panels, and media settings seamlessly without reaching for the mouse. Navigating complex nested menus (like subtitles or episodes) purely via keyboard was cumbersome because focus didn't smartly track the active item, tabs required manual tabbing, and rapid shortcut inputs suffered from backend state-sync lag. This PR solves these issues to provide a fluid, fully keyboard-drivable desktop player experience.
Desktop scope
This PR is scoped purely to the desktop video player UI (controls.js, controls.css), running inside the desktop webview overlay. It does not affect mobile or core backend playback logic.
Issue or approval
Fixes #109, Fixes #170, Fixes #172, Fixes #207, Fixes #456
UI / behavior impact
Policy check
CONTRIBUTING.md.Scope boundaries
This PR focuses exclusively on keyboard event bindings, focus management, and local state debouncing for the player UI webview. It does not touch Kotlin-side media session routing, platform-specific media keys, or restructure the core DOM layout.
Testing
Manual Testing via Desktop App (Windows/Mac):
Screenshots / Video
Not a UI change
Breaking changes
None.
Linked issues
Fixes #109, Fixes #170, Fixes #172, Fixes #207, Fixes #456