From 9871665bf5944764c59a578b7e76a8ff25a568a6 Mon Sep 17 00:00:00 2001 From: Patrik Niebur Date: Fri, 22 Sep 2023 12:31:16 +0100 Subject: [PATCH] Add screen lock --- package-lock.json | 13 +++++++++ package.json | 1 + src/ts/Views/ExerciseRunner.tsx | 3 +- src/ts/helpers/hooks.ts | 52 +++++++++++++++++++++++++++++++-- 4 files changed, 66 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0dd2147..81e29c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-dom": "^18.2.0", + "react-screen-wake-lock": "^3.0.2", "react-speech-recognition": "^3.10.0" }, "devDependencies": { @@ -6824,6 +6825,18 @@ } } }, + "node_modules/react-screen-wake-lock": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/react-screen-wake-lock/-/react-screen-wake-lock-3.0.2.tgz", + "integrity": "sha512-f88vcfMG1AWYRSIWQ5Qx5YVboH6TSL0F4ZlFLERZp6aKiZRGVRAAJ9wedJdO5jqTMcCDZ4OXJ8PjcSkDmvGSBg==", + "hasInstallScript": true, + "engines": { + "node": ">=14.16" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-speech-recognition": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/react-speech-recognition/-/react-speech-recognition-3.10.0.tgz", diff --git a/package.json b/package.json index 92d3d1d..8eec3e5 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-dom": "^18.2.0", + "react-screen-wake-lock": "^3.0.2", "react-speech-recognition": "^3.10.0" }, "@parcel/transformer-css": { diff --git a/src/ts/Views/ExerciseRunner.tsx b/src/ts/Views/ExerciseRunner.tsx index 4d2420c..e89ce73 100644 --- a/src/ts/Views/ExerciseRunner.tsx +++ b/src/ts/Views/ExerciseRunner.tsx @@ -13,7 +13,7 @@ import type { DirectoryConfiguration } from "../types"; import { useGlobalContext } from "../GlobalContext"; import { ExerciseItem } from "../components/ExerciseItem"; import { getDirectoryConfig } from "../helpers/directoryFunctions"; -import { useVoiceCommands, useKeyboardControls } from "../helpers/hooks"; +import { useVoiceCommands, useKeyboardControls, useRefreshingWakeLock } from "../helpers/hooks"; import { VoiceControlledTimer } from "../components/Timer/VoiceControlledTimer"; import { ControlsModal } from "../components/ControlsModal"; @@ -23,6 +23,7 @@ const BASE_PATH = process.env.BASE_PATH; export function ExerciseRunner() { useKeyboardControls({ ArrowLeft: prev, ArrowRight: next }); const [config] = useDirectoryConfiguration(); + useRefreshingWakeLock() const [currentExerciseIndex, setCurrentExerciseIndex] = React.useState(0); const [lastCommand, resetLastCommand] = useVoiceCommands([ "next", diff --git a/src/ts/helpers/hooks.ts b/src/ts/helpers/hooks.ts index 6b4ca3d..356c525 100644 --- a/src/ts/helpers/hooks.ts +++ b/src/ts/helpers/hooks.ts @@ -2,6 +2,7 @@ import React from "react"; import SpeechRecognition, { useSpeechRecognition, } from "react-speech-recognition"; +import { useWakeLock } from "react-screen-wake-lock"; export function useVoiceCommands(command: string[]) { const [lastCommand, setLastCommand] = React.useState(""); @@ -51,8 +52,8 @@ export function useKeyboardControls( const listener = (e: KeyboardEvent) => { const callback = listeners[e.code]; if (callback) { - e.preventDefault() - callback() + e.preventDefault(); + callback(); } }; window.addEventListener("keydown", listener); @@ -60,3 +61,50 @@ export function useKeyboardControls( return () => window.removeEventListener("keydown", listener); }, [listeners]); } + +export function useRefreshingWakeLock() { + const locked = React.useRef(false); + const { request, release } = useWakeLock({ + onRelease: () => { + console.log("release"); + locked.current = false; + }, + }); + + const lock = () => { + console.log("lock"); + if (locked.current !== true) { + request().then(() => { + locked.current = true; + }); + } + }; + + /* Lock/unlock on component mount/unmount */ + React.useEffect(() => { + lock(); + + return () => { + if (locked.current) { + release().then(() => { + console.log("release (hook)"); + locked.current = false; + }); + } + }; + }, []); + + /* Re-lock after visibility change */ + React.useEffect(() => { + const listener = () => { + if (document.visibilityState === "visible" && locked.current === false) { + lock(); + } + }; + window.addEventListener("visibilitychange", listener); + + return () => { + window.removeEventListener("visibilitychange", listener); + }; + }, []); +}