some changes to the play route

This commit is contained in:
AquaWolf
2025-03-03 17:39:38 +01:00
parent 05aa177681
commit 805a8a6115

View File

@@ -1,8 +1,8 @@
import { Text } from "@nestri/www/ui/text";
import { createSignal, createEffect, onCleanup, onMount } from "solid-js";
import { createSignal, createEffect, onCleanup, onMount, Show } from "solid-js";
import { useParams } from "@solidjs/router";
import { Modal } from "@nestri/ui";
import { Keyboard, Mouse, WebRTCStream } from "@nestri/input";
import { Container, FullScreen } from "@nestri/www/ui/layout";
export function PlayComponent() {
const params = useParams();
@@ -15,6 +15,7 @@ export function PlayComponent() {
const [leftStickX, setLeftStickX] = createSignal(0);
const [leftStickY, setLeftStickY] = createSignal(0);
const [hasStream, setHasStream] = createSignal(false);
const [nestriLock, setNestriLock] = createSignal(false);
const [showOffline, setShowOffline] = createSignal(false);
const [canvas, setCanvas] = createSignal<HTMLCanvasElement | undefined>(undefined);
@@ -67,6 +68,25 @@ export function PlayComponent() {
await canvasElement.requestPointerLock();
await canvasElement.requestFullscreen();
//initializeGamepad();
if (document.fullscreenElement !== null) {
if ('keyboard' in navigator && 'lock' in (navigator.keyboard as any)) {
const keys = [
"AltLeft", "AltRight", "Tab", "Escape",
"ContextMenu", "MetaLeft", "MetaRight"
];
try {
await (navigator.keyboard as any).lock(keys);
setNestriLock(true);
console.log("Keyboard lock acquired");
} catch (e) {
console.warn("Keyboard lock failed:", e);
setNestriLock(false);
}
}
}
} catch (error) {
console.error("Error during lock sequence:", error);
}
@@ -79,6 +99,15 @@ export function PlayComponent() {
if (document.pointerLockElement === canvasElement) {
initializeInputDevices();
} else {
if (!showBannerModal) {
const playing = sessionStorage.getItem("showedBanner");
setShowBannerModal(!playing || playing !== "true");
setShowButtonModal(playing === "false");
}
nestriKeyboard?.dispose();
nestriMouse?.dispose();
}
@@ -114,6 +143,9 @@ export function PlayComponent() {
onMount(() => {
const canvasElement = canvas();
if(!canvasElement) return;
setupPointerLockListener();
video = document.createElement("video");
video.style.visibility = "hidden";
@@ -123,9 +155,17 @@ export function PlayComponent() {
setHasStream(true);
setShowOffline(false);
await handleVideoInput();
} else {
} else if (mediaStream === null) {
console.log("MediaStream is null, Room is offline");
setShowOffline(true);
setHasStream(false);
const ctx = canvasElement.getContext("2d");
if (ctx) ctx.clearRect(0, 0, canvasElement.width, canvasElement.height);
} else if (video && video.srcObject !== null) {
setHasStream(true);
setShowOffline(true);
await handleVideoInput();
}
});
});
@@ -136,14 +176,70 @@ export function PlayComponent() {
});
return (
<>
<FullScreen>
{showOffline() ? (
<div class="w-screen h-screen flex justify-center items-center">
<span class="text-2xl font-semibold flex items-center gap-2">Offline</span>
<button onClick={() =>setShowButtonModal(true)}>Show Modal</button>
</div>
) : (
<canvas ref={setCanvas} onClick={lockPlay} class="aspect-video h-full w-full object-contain max-h-screen" />
)}
</>
<Modal show={showButtonModal}
setShow={setShowButtonModal}
closeOnBackdropClick={false}
handleVideoInput={handleVideoInput}
lockPlay={lockPlay} />
</FullScreen>
);
}
interface ModalProps {
show: () => boolean;
setShow: (value: boolean) => void;
closeOnBackdropClick?: boolean;
handleVideoInput?: () => Promise<void>;
lockPlay?: () => Promise<void>;
}
function Modal(props: ModalProps) {
return (
<Show when={props.show()}>
<div
class="fixed inset-0 flex items-center justify-center dark:backdrop:bg-[#0009] backdrop:bg-[#b3b5b799] backdrop:backdrop-grayscale-[.3]"
onClick={() => props.closeOnBackdropClick && props.setShow(false)}
>
<div
class="
w-full max-w-[370px] max-h-[75vh] rounded-xl border dark:border-[#343434] border-[#e2e2e2]
dark:[box-shadow:0_0_0_1px_rgba(255,255,255,0.08),_0_3.3px_2.7px_rgba(0,0,0,.1),0_8.3px_6.9px_rgba(0,0,0,.13),0_17px_14.2px_rgba(0,0,0,.17),0_35px_29.2px_rgba(0,0,0,.22),0px_-4px_4px_0px_rgba(0,0,0,.04)_inset] dark:bg-[#222b]
[box-shadow:0_0_0_1px_rgba(19,21,23,0.08),_0_3.3px_2.7px_rgba(0,0,0,.03),0_8.3px_6.9px_rgba(0,0,0,.04),0_17px_14.2px_rgba(0,0,0,.05),0_35px_29.2px_rgba(0,0,0,.06),0px_-4px_4px_0px_rgba(0,0,0,.07)_inset] bg-[#fffd]
backdrop-blur-lg py-4 px-5 modal"
onClick={(e) => e.stopPropagation()} // Prevent closing when clicking inside modal
>
<div class="size-full flex flex-col">
<div class="flex flex-col gap-3">
<button
class="transition-all duration-200 focus:ring-2 focus:ring-gray-300 focus:dark:ring-gray-700 outline-none w-full hover:bg-gray-300 hover:dark:bg-gray-700 bg-gray-200 dark:bg-gray-800 text-gray-800 dark:text-gray-200 items-center justify-center font-medium font-title rounded-lg flex py-3 px-4"
onClick={async () => {
props.setShow(false);
sessionStorage.setItem("showedBanner", "true");
await props.handleVideoInput?.();
await props.lockPlay?.();
}}
>
Continue Playing
</button>
<button
class="transition-all duration-200 focus:ring-2 focus:ring-gray-300 focus:dark:ring-gray-700 outline-none w-full hover:bg-gray-300 hover:dark:bg-gray-700 bg-gray-200 dark:bg-gray-800 text-gray-800 dark:text-gray-200 items-center justify-center font-medium font-title rounded-lg flex py-3 px-4"
>
Shutdown Nestri
</button>
</div>
</div>
</div>
</div>
</Show>
);
}