From b1667320cb4c9cc67f0cb7364c5c4c6a61955d17 Mon Sep 17 00:00:00 2001 From: Nakshatra Sharma Date: Thu, 12 Feb 2026 23:27:40 +0530 Subject: [PATCH 1/2] feat: keep mobile screen awake using Wake Lock API --- src/routes/trackpad.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/routes/trackpad.tsx b/src/routes/trackpad.tsx index cf21e0b..039eca1 100644 --- a/src/routes/trackpad.tsx +++ b/src/routes/trackpad.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/react-router' -import { useState, useRef } from 'react' +import { useState, useRef, useEffect } from 'react' import { useRemoteConnection } from '../hooks/useRemoteConnection'; import { useTrackpadGesture } from '../hooks/useTrackpadGesture'; import { ControlBar } from '../components/Trackpad/ControlBar'; @@ -32,7 +32,21 @@ function TrackpadPage() { const s = localStorage.getItem('rein_invert'); return s ? JSON.parse(s) : false; }); - + useEffect(() => { + let wl: any; + const req = async () => { + try { + if ('wakeLock' in navigator) wl = await (navigator as any).wakeLock.request('screen'); + } catch (err) {} + }; + req(); + const vc = () => document.visibilityState === 'visible' && req(); + document.addEventListener('visibilitychange', vc); + return () => { + document.removeEventListener('visibilitychange', vc); + wl?.release(); + }; + }, []); const { status, send, sendCombo } = useRemoteConnection(); // Pass sensitivity and invertScroll to the gesture hook const { isTracking, handlers } = useTrackpadGesture(send, scrollMode, sensitivity, invertScroll); From 610be5429d8849073e6d3010c0eba0bd05229c2a Mon Sep 17 00:00:00 2001 From: Nakshatra Sharma Date: Thu, 12 Feb 2026 23:35:31 +0530 Subject: [PATCH 2/2] refactor: improve wake lock lifecycle management and prevent leaks --- src/routes/trackpad.tsx | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/routes/trackpad.tsx b/src/routes/trackpad.tsx index 039eca1..5d395b5 100644 --- a/src/routes/trackpad.tsx +++ b/src/routes/trackpad.tsx @@ -19,7 +19,9 @@ function TrackpadPage() { const bufferText = buffer.join(" + "); const hiddenInputRef = useRef(null); const isComposingRef = useRef(false); - + const sentinelRef = useRef(null); + const mountedRef = useRef(false); + // Load Client Settings const [sensitivity] = useState(() => { if (typeof window === 'undefined') return 1.0; @@ -33,18 +35,28 @@ function TrackpadPage() { return s ? JSON.parse(s) : false; }); useEffect(() => { - let wl: any; - const req = async () => { + mountedRef.current = true; + const requestWakeLock = async () => { try { - if ('wakeLock' in navigator) wl = await (navigator as any).wakeLock.request('screen'); - } catch (err) {} + if ('wakeLock' in navigator) { + const result = await (navigator as any).wakeLock.request('screen'); + if (mountedRef.current) { + sentinelRef.current = result; + } else { + await result.release(); + } + } + } catch (err) { + console.warn('Wake lock request failed:', err); + } }; - req(); - const vc = () => document.visibilityState === 'visible' && req(); - document.addEventListener('visibilitychange', vc); + requestWakeLock(); + const handleVisibilityChange = () => document.visibilityState === 'visible' && requestWakeLock(); + document.addEventListener('visibilitychange', handleVisibilityChange); return () => { - document.removeEventListener('visibilitychange', vc); - wl?.release(); + mountedRef.current = false; + document.removeEventListener('visibilitychange', handleVisibilityChange); + sentinelRef.current?.release(); }; }, []); const { status, send, sendCombo } = useRemoteConnection();