Compare commits

..

6 Commits

Author SHA1 Message Date
Scai a17cacabf1
Merge 57fbee1490 into ff3727b1fe 2025-02-19 10:26:29 -05:00
Siyuan Miao ff3727b1fe chore: bump version to 0.3.7 2025-02-19 14:03:18 +01:00
Adam Shiervani d415afcea9
feat(ui): improve video playback and keyboard handling in WebRTCVideo (#176)
* feat(ui): improve video playback and keyboard handling in WebRTCVideo

* fix(ui): correct event handler naming in WebRTCVideo component
2025-02-19 14:00:15 +01:00
Adam Shiervani 368c1eea90
refactor(ui): simplify backlight settings handling (#175) 2025-02-19 11:38:11 +01:00
Aveline b38f899c84
fix(config): should return defaultConfig when config file doesnt exist (#174) 2025-02-19 10:27:24 +01:00
Siyuan Miao a3d21557c3 fix(config): should return defaultConfig when config file doesnt exist 2025-02-19 10:25:45 +01:00
4 changed files with 36 additions and 25 deletions

View File

@ -1,5 +1,5 @@
VERSION_DEV := 0.3.5-dev$(shell date +%Y%m%d%H%M) VERSION_DEV := 0.3.8-dev$(shell date +%Y%m%d%H%M)
VERSION := 0.3.4 VERSION := 0.3.7
hash_resource: hash_resource:
@shasum -a 256 resource/jetkvm_native | cut -d ' ' -f 1 > resource/jetkvm_native.sha256 @shasum -a 256 resource/jetkvm_native | cut -d ' ' -f 1 > resource/jetkvm_native.sha256

View File

@ -55,6 +55,9 @@ func LoadConfig() {
return return
} }
// load the default config
config = defaultConfig
file, err := os.Open(configPath) file, err := os.Open(configPath)
if err != nil { if err != nil {
logger.Debug("default config file doesn't exist, using default") logger.Debug("default config file doesn't exist, using default")

View File

@ -285,11 +285,6 @@ export default function WebRTCVideo() {
e.preventDefault(); e.preventDefault();
const prev = useHidStore.getState(); const prev = useHidStore.getState();
// if (document.activeElement?.id !== "videoFocusTrap") {
// console.log("KEYUP: Not focusing on the video", document.activeElement);
// return;
// }
setIsNumLockActive(e.getModifierState("NumLock")); setIsNumLockActive(e.getModifierState("NumLock"));
setIsCapsLockActive(e.getModifierState("CapsLock")); setIsCapsLockActive(e.getModifierState("CapsLock"));
setIsScrollLockActive(e.getModifierState("ScrollLock")); setIsScrollLockActive(e.getModifierState("ScrollLock"));
@ -336,6 +331,18 @@ export default function WebRTCVideo() {
[keyDownHandler, keyUpHandler, resetKeyboardState, sendKeyboardEvent], [keyDownHandler, keyUpHandler, resetKeyboardState, sendKeyboardEvent],
); );
const videoKeyUpHandler = useCallback((e: KeyboardEvent) => {
// In fullscreen mode in chrome & safari, the space key is used to pause/play the video
// there is no way to prevent this, so we need to simply force play the video when it's paused.
// Fix only works in chrome based browsers.
if (e.code === "Space") {
if (videoElm.current?.paused == true) {
console.log("Force playing video");
videoElm.current?.play();
}
}
}, []);
useEffect( useEffect(
function setupVideoEventListeners() { function setupVideoEventListeners() {
let videoElmRefValue = null; let videoElmRefValue = null;
@ -347,7 +354,7 @@ export default function WebRTCVideo() {
videoElmRefValue.addEventListener("mousemove", mouseMoveHandler, { signal }); videoElmRefValue.addEventListener("mousemove", mouseMoveHandler, { signal });
videoElmRefValue.addEventListener("pointerdown", mouseMoveHandler, { signal }); videoElmRefValue.addEventListener("pointerdown", mouseMoveHandler, { signal });
videoElmRefValue.addEventListener("pointerup", mouseMoveHandler, { signal }); videoElmRefValue.addEventListener("pointerup", mouseMoveHandler, { signal });
videoElmRefValue.addEventListener("keyup", videoKeyUpHandler, { signal });
videoElmRefValue.addEventListener("wheel", mouseWheelHandler, { signal }); videoElmRefValue.addEventListener("wheel", mouseWheelHandler, { signal });
videoElmRefValue.addEventListener( videoElmRefValue.addEventListener(
"contextmenu", "contextmenu",
@ -364,7 +371,13 @@ export default function WebRTCVideo() {
if (videoElmRefValue) abortController.abort(); if (videoElmRefValue) abortController.abort();
}; };
}, },
[mouseMoveHandler, resetMousePosition, onVideoPlaying, mouseWheelHandler], [
mouseMoveHandler,
resetMousePosition,
onVideoPlaying,
mouseWheelHandler,
videoKeyUpHandler,
],
); );
useEffect( useEffect(
@ -410,7 +423,7 @@ export default function WebRTCVideo() {
}, [sendKeyboardEvent, setDisableVideoFocusTrap, sidebarView]); }, [sendKeyboardEvent, setDisableVideoFocusTrap, sidebarView]);
return ( return (
<div className="grid w-full h-full grid-rows-layout"> <div className="grid h-full w-full grid-rows-layout">
<div className="min-h-[39.5px]"> <div className="min-h-[39.5px]">
<fieldset disabled={peerConnectionState !== "connected"}> <fieldset disabled={peerConnectionState !== "connected"}>
<Actionbar <Actionbar
@ -427,18 +440,18 @@ export default function WebRTCVideo() {
<div className="relative h-full"> <div className="relative h-full">
<div <div
className={cx( className={cx(
"absolute inset-0 bg-blue-50/40 dark:bg-slate-800/40 opacity-80", "absolute inset-0 bg-blue-50/40 opacity-80 dark:bg-slate-800/40",
"[background-image:radial-gradient(theme(colors.blue.300)_0.5px,transparent_0.5px),radial-gradient(theme(colors.blue.300)_0.5px,transparent_0.5px)] dark:[background-image:radial-gradient(theme(colors.slate.700)_0.5px,transparent_0.5px),radial-gradient(theme(colors.slate.700)_0.5px,transparent_0.5px)]", "[background-image:radial-gradient(theme(colors.blue.300)_0.5px,transparent_0.5px),radial-gradient(theme(colors.blue.300)_0.5px,transparent_0.5px)] dark:[background-image:radial-gradient(theme(colors.slate.700)_0.5px,transparent_0.5px),radial-gradient(theme(colors.slate.700)_0.5px,transparent_0.5px)]",
"[background-position:0_0,10px_10px]", "[background-position:0_0,10px_10px]",
"[background-size:20px_20px]", "[background-size:20px_20px]",
)} )}
/> />
<div className="flex flex-col h-full"> <div className="flex h-full flex-col">
<div className="relative flex-grow overflow-hidden"> <div className="relative flex-grow overflow-hidden">
<div className="flex flex-col h-full"> <div className="flex h-full flex-col">
<div className="grid flex-grow overflow-hidden grid-rows-bodyFooter"> <div className="grid flex-grow grid-rows-bodyFooter overflow-hidden">
<div className="relative flex items-center justify-center mx-4 my-2 overflow-hidden"> <div className="relative mx-4 my-2 flex items-center justify-center overflow-hidden">
<div className="relative flex items-center justify-center w-full h-full"> <div className="relative flex h-full w-full items-center justify-center">
<video <video
ref={videoElm} ref={videoElm}
autoPlay={true} autoPlay={true}
@ -454,14 +467,14 @@ export default function WebRTCVideo() {
{ {
"cursor-none": settings.isCursorHidden, "cursor-none": settings.isCursorHidden,
"opacity-0": isLoading || isConnectionError || hdmiError, "opacity-0": isLoading || isConnectionError || hdmiError,
"animate-slideUpFade border border-slate-800/30 dark:border-slate-300/20 opacity-0 shadow": "animate-slideUpFade border border-slate-800/30 opacity-0 shadow dark:border-slate-300/20":
isPlaying, isPlaying,
}, },
)} )}
/> />
<div <div
style={{ animationDuration: "500ms" }} style={{ animationDuration: "500ms" }}
className="absolute inset-0 flex items-center justify-center opacity-0 pointer-events-none animate-slideUpFade" className="pointer-events-none absolute inset-0 flex animate-slideUpFade items-center justify-center opacity-0"
> >
<div className="relative h-full max-h-[720px] w-full max-w-[1280px] rounded-md"> <div className="relative h-full max-h-[720px] w-full max-w-[1280px] rounded-md">
<LoadingOverlay show={isLoading} /> <LoadingOverlay show={isLoading} />

View File

@ -239,6 +239,7 @@ export default function SettingsSidebar() {
} }
setBacklightSettings(settings); setBacklightSettings(settings);
handleBacklightSettingsSave();
} }
const handleBacklightSettingsSave = () => { const handleBacklightSettingsSave = () => {
@ -362,7 +363,7 @@ export default function SettingsSidebar() {
if ("error" in resp) return; if ("error" in resp) return;
setUsbEmulationEnabled(resp.result as boolean); setUsbEmulationEnabled(resp.result as boolean);
}); });
}, [getCloudState, send, setDeveloperMode, setHideCursor, setJiggler]); }, [getCloudState, send, setBacklightSettings, setDeveloperMode, setHideCursor, setJiggler]);
const getDevice = useCallback(async () => { const getDevice = useCallback(async () => {
try { try {
@ -900,12 +901,6 @@ export default function SettingsSidebar() {
<p className="text-xs text-slate-600 dark:text-slate-400"> <p className="text-xs text-slate-600 dark:text-slate-400">
The display will wake up when the connection state changes, or when touched. The display will wake up when the connection state changes, or when touched.
</p> </p>
<Button
size="SM"
theme="primary"
text="Save Display Settings"
onClick={handleBacklightSettingsSave}
/>
<div className="h-[1px] w-full bg-slate-800/10 dark:bg-slate-300/20" /> <div className="h-[1px] w-full bg-slate-800/10 dark:bg-slate-300/20" />
<div className="pb-2 space-y-4"> <div className="pb-2 space-y-4">
<SectionHeader <SectionHeader