fix: the keyboard shortcuts the player has always advertised
The transport buttons have said "Play (space)" and "Full screen (f)" since they were built, with nothing listening for either key. Pressing f did nothing, which is exactly what a broken fullscreen button looks like. Both now work, verified in the running app: f enters and leaves fullscreen, space plays and pauses. Space is prevented from also pressing whichever button has focus, and neither fires while typing in a field or alongside a modifier. Escape now asks to leave fullscreen before the player considers closing, so one keypress cannot drop you all the way back to the feed. The button itself was never broken: it was checked on a downloaded video, on a stream, and inside a window already in macOS fullscreen, entering and leaving each time.
This commit is contained in:
@@ -299,8 +299,9 @@ export default function Player({
|
|||||||
// Escape backs out, as it does everywhere else in the app.
|
// Escape backs out, as it does everywhere else in the app.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onKey = (e: KeyboardEvent) => {
|
const onKey = (e: KeyboardEvent) => {
|
||||||
// In fullscreen the browser already handles Escape; closing the player
|
// In fullscreen, Escape is the transport bar's to handle: it leaves
|
||||||
// as well would drop you all the way back to the feed.
|
// fullscreen. Closing the player as well would drop you all the way back
|
||||||
|
// to the feed in one keypress.
|
||||||
if (e.key === "Escape" && !document.fullscreenElement) leave();
|
if (e.key === "Escape" && !document.fullscreenElement) leave();
|
||||||
// Arrow keys only when the video does not own them for seeking.
|
// Arrow keys only when the video does not own them for seeking.
|
||||||
if (e.key === "ArrowLeft" && e.shiftKey) onPrev?.();
|
if (e.key === "ArrowLeft" && e.shiftKey) onPrev?.();
|
||||||
|
|||||||
@@ -253,6 +253,38 @@ export default function PlayerControls({
|
|||||||
}
|
}
|
||||||
}, [stageRef, onActivity]);
|
}, [stageRef, onActivity]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shortcuts the buttons advertise. Their tooltips have promised
|
||||||
|
* "(space)" and "(f)" all along with nothing listening, and Escape left
|
||||||
|
* fullscreen nowhere: WebKit does not handle it for an element made
|
||||||
|
* fullscreen this way, so pressing it did nothing and the only way out was
|
||||||
|
* to find the button again.
|
||||||
|
*/
|
||||||
|
useEffect(() => {
|
||||||
|
const onKey = (e: KeyboardEvent) => {
|
||||||
|
// Never while typing, and never over a shortcut of the system's own.
|
||||||
|
const t = e.target as HTMLElement | null;
|
||||||
|
if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)) return;
|
||||||
|
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
||||||
|
|
||||||
|
if (e.key === " " || e.code === "Space") {
|
||||||
|
// Or the space would also press whichever button has focus.
|
||||||
|
e.preventDefault();
|
||||||
|
const v = videoRef.current;
|
||||||
|
if (!v) return;
|
||||||
|
if (v.paused) void v.play().catch(() => {});
|
||||||
|
else v.pause();
|
||||||
|
onActivity?.();
|
||||||
|
} else if (e.key === "f" || e.key === "F") {
|
||||||
|
void toggleFull();
|
||||||
|
} else if (e.key === "Escape" && document.fullscreenElement) {
|
||||||
|
void document.exitFullscreen();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener("keydown", onKey);
|
||||||
|
return () => window.removeEventListener("keydown", onKey);
|
||||||
|
}, [videoRef, toggleFull, onActivity]);
|
||||||
|
|
||||||
const pct = duration > 0 ? (time / duration) * 100 : 0;
|
const pct = duration > 0 ? (time / duration) * 100 : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user