From 5d63c58f2c2832d13a283127cc0f764fc1bf9080 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Wed, 9 Apr 2025 08:46:27 -0600 Subject: [PATCH] UI tweaks (#17615) * Ensure that text field doesn't zoom on iOS * Add keyboard shortcut support to generic video player --- web/src/components/input/TextEntry.tsx | 2 +- .../components/player/GenericVideoPlayer.tsx | 55 ++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/web/src/components/input/TextEntry.tsx b/web/src/components/input/TextEntry.tsx index 92867f5e3..85445b110 100644 --- a/web/src/components/input/TextEntry.tsx +++ b/web/src/components/input/TextEntry.tsx @@ -55,7 +55,7 @@ export default function TextEntry({ diff --git a/web/src/components/player/GenericVideoPlayer.tsx b/web/src/components/player/GenericVideoPlayer.tsx index c8405b11a..ed4427740 100644 --- a/web/src/components/player/GenericVideoPlayer.tsx +++ b/web/src/components/player/GenericVideoPlayer.tsx @@ -1,7 +1,8 @@ -import React, { useState, useRef, useEffect } from "react"; +import React, { useState, useRef, useEffect, useCallback } from "react"; import { useVideoDimensions } from "@/hooks/use-video-dimensions"; import HlsVideoPlayer from "./HlsVideoPlayer"; import ActivityIndicator from "../indicators/activity-indicator"; +import useKeyboardListener from "@/hooks/use-keyboard-listener"; type GenericVideoPlayerProps = { source: string; @@ -36,6 +37,58 @@ export function GenericVideoPlayer({ checkSourceExists(source); }, [source]); + const onSeek = useCallback( + (diff: number) => { + const currentTime = videoRef.current?.currentTime; + + if (!currentTime) { + return; + } + + videoRef.current!.currentTime = Math.max(0, currentTime + diff); + }, + [videoRef], + ); + + useKeyboardListener( + ["ArrowDown", "ArrowLeft", "ArrowRight", "ArrowUp", " ", "f", "m"], + (key, modifiers) => { + if (!modifiers.down || modifiers.repeat) { + return; + } + + switch (key) { + case "ArrowDown": + onSeek(-1); + break; + case "ArrowLeft": + onSeek(-10); + break; + case "ArrowRight": + onSeek(10); + break; + case "ArrowUp": + onSeek(1); + break; + case " ": + if (videoRef.current?.paused) { + videoRef.current?.play(); + } else { + videoRef.current?.pause(); + } + break; + case "f": + videoRef.current?.requestFullscreen(); + break; + case "m": + if (videoRef.current) { + videoRef.current.muted = !videoRef.current.muted; + } + break; + } + }, + ); + return (