mirror of https://github.com/jetkvm/kvm.git
Compare commits
6 Commits
d3f13286d5
...
79b2e94473
Author | SHA1 | Date |
---|---|---|
|
79b2e94473 | |
|
ff3727b1fe | |
|
d415afcea9 | |
|
368c1eea90 | |
|
87f36167f3 | |
|
508ea65fae |
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "JetKVM",
|
||||
"name": "JetKVM Default",
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1-1.23-bookworm",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "JetKVM Podman",
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1-1.23-bookworm",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
// Should match what is defined in ui/package.json
|
||||
"version": "21.1.0"
|
||||
}
|
||||
},
|
||||
"runArgs": [
|
||||
"--userns=keep-id",
|
||||
"--security-opt=label=disable",
|
||||
"--security-opt=label=nested"
|
||||
],
|
||||
"containerUser": "vscode",
|
||||
"containerEnv": {
|
||||
"HOME": "/home/vscode"
|
||||
}
|
||||
}
|
4
Makefile
4
Makefile
|
@ -1,5 +1,5 @@
|
|||
VERSION_DEV := 0.3.7-dev$(shell date +%Y%m%d%H%M)
|
||||
VERSION := 0.3.6
|
||||
VERSION_DEV := 0.3.8-dev$(shell date +%Y%m%d%H%M)
|
||||
VERSION := 0.3.7
|
||||
|
||||
hash_resource:
|
||||
@shasum -a 256 resource/jetkvm_native | cut -d ' ' -f 1 > resource/jetkvm_native.sha256
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Exit immediately if a command exits with a non-zero status
|
||||
set -e
|
||||
|
||||
|
|
|
@ -285,11 +285,6 @@ export default function WebRTCVideo() {
|
|||
e.preventDefault();
|
||||
const prev = useHidStore.getState();
|
||||
|
||||
// if (document.activeElement?.id !== "videoFocusTrap") {
|
||||
// console.log("KEYUP: Not focusing on the video", document.activeElement);
|
||||
// return;
|
||||
// }
|
||||
|
||||
setIsNumLockActive(e.getModifierState("NumLock"));
|
||||
setIsCapsLockActive(e.getModifierState("CapsLock"));
|
||||
setIsScrollLockActive(e.getModifierState("ScrollLock"));
|
||||
|
@ -336,6 +331,18 @@ export default function WebRTCVideo() {
|
|||
[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(
|
||||
function setupVideoEventListeners() {
|
||||
let videoElmRefValue = null;
|
||||
|
@ -347,7 +354,7 @@ export default function WebRTCVideo() {
|
|||
videoElmRefValue.addEventListener("mousemove", mouseMoveHandler, { signal });
|
||||
videoElmRefValue.addEventListener("pointerdown", mouseMoveHandler, { signal });
|
||||
videoElmRefValue.addEventListener("pointerup", mouseMoveHandler, { signal });
|
||||
|
||||
videoElmRefValue.addEventListener("keyup", videoKeyUpHandler, { signal });
|
||||
videoElmRefValue.addEventListener("wheel", mouseWheelHandler, { signal });
|
||||
videoElmRefValue.addEventListener(
|
||||
"contextmenu",
|
||||
|
@ -364,7 +371,13 @@ export default function WebRTCVideo() {
|
|||
if (videoElmRefValue) abortController.abort();
|
||||
};
|
||||
},
|
||||
[mouseMoveHandler, resetMousePosition, onVideoPlaying, mouseWheelHandler],
|
||||
[
|
||||
mouseMoveHandler,
|
||||
resetMousePosition,
|
||||
onVideoPlaying,
|
||||
mouseWheelHandler,
|
||||
videoKeyUpHandler,
|
||||
],
|
||||
);
|
||||
|
||||
useEffect(
|
||||
|
@ -410,7 +423,7 @@ export default function WebRTCVideo() {
|
|||
}, [sendKeyboardEvent, setDisableVideoFocusTrap, sidebarView]);
|
||||
|
||||
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]">
|
||||
<fieldset disabled={peerConnectionState !== "connected"}>
|
||||
<Actionbar
|
||||
|
@ -427,18 +440,18 @@ export default function WebRTCVideo() {
|
|||
<div className="relative h-full">
|
||||
<div
|
||||
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-position:0_0,10px_10px]",
|
||||
"[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="flex flex-col h-full">
|
||||
<div className="grid flex-grow overflow-hidden grid-rows-bodyFooter">
|
||||
<div className="relative flex items-center justify-center mx-4 my-2 overflow-hidden">
|
||||
<div className="relative flex items-center justify-center w-full h-full">
|
||||
<div className="flex h-full flex-col">
|
||||
<div className="grid flex-grow grid-rows-bodyFooter overflow-hidden">
|
||||
<div className="relative mx-4 my-2 flex items-center justify-center overflow-hidden">
|
||||
<div className="relative flex h-full w-full items-center justify-center">
|
||||
<video
|
||||
ref={videoElm}
|
||||
autoPlay={true}
|
||||
|
@ -454,14 +467,14 @@ export default function WebRTCVideo() {
|
|||
{
|
||||
"cursor-none": settings.isCursorHidden,
|
||||
"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,
|
||||
},
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
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">
|
||||
<LoadingOverlay show={isLoading} />
|
||||
|
|
|
@ -239,6 +239,7 @@ export default function SettingsSidebar() {
|
|||
}
|
||||
|
||||
setBacklightSettings(settings);
|
||||
handleBacklightSettingsSave();
|
||||
}
|
||||
|
||||
const handleBacklightSettingsSave = () => {
|
||||
|
@ -362,7 +363,7 @@ export default function SettingsSidebar() {
|
|||
if ("error" in resp) return;
|
||||
setUsbEmulationEnabled(resp.result as boolean);
|
||||
});
|
||||
}, [getCloudState, send, setDeveloperMode, setHideCursor, setJiggler]);
|
||||
}, [getCloudState, send, setBacklightSettings, setDeveloperMode, setHideCursor, setJiggler]);
|
||||
|
||||
const getDevice = useCallback(async () => {
|
||||
try {
|
||||
|
@ -900,12 +901,6 @@ export default function SettingsSidebar() {
|
|||
<p className="text-xs text-slate-600 dark:text-slate-400">
|
||||
The display will wake up when the connection state changes, or when touched.
|
||||
</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="pb-2 space-y-4">
|
||||
<SectionHeader
|
||||
|
|
Loading…
Reference in New Issue