Prevent screen dimming during playback
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
- Add `Shift+↑/↓` shortcuts for adjusting WPM by 100 and document them in the shortcuts modal
|
||||
- Improve mobile support for long words by shifting the focal point left
|
||||
- Fix major performance issues on long texts by reducing frequent localStorage writes during playback and keeping global keyboard listeners stable
|
||||
- Keep the screen awake while playing when the browser supports the Screen Wake Lock API
|
||||
|
||||
### 2026-02-07: 1.1.0
|
||||
|
||||
|
||||
+32
@@ -31,6 +31,7 @@ import {
|
||||
saveTextPayload,
|
||||
setPositionForTextInPlace,
|
||||
} from "./lib/storage";
|
||||
import { createWakeLockHandle } from "./lib/wakelock";
|
||||
import { styles } from "./styles";
|
||||
import type { BookMetadata, PositionsMap } from "./types";
|
||||
|
||||
@@ -119,16 +120,22 @@ export default function App() {
|
||||
const lastIndexRef = useRef<number>(currentIndex);
|
||||
const currentIndexRef = useRef<number>(currentIndex);
|
||||
const wordsLengthRef = useRef<number>(words.length);
|
||||
const isPlayingRef = useRef<boolean>(isPlaying);
|
||||
const speedScaleRef = useRef(1);
|
||||
const observedWpmRef = useRef<number | null>(null);
|
||||
const observedWpmEmaRef = useRef<number | null>(null);
|
||||
const lastControlTickRef = useRef<number | null>(null);
|
||||
const wasPlayingRef = useRef(false);
|
||||
const wakeLockRef = useRef(createWakeLockHandle());
|
||||
|
||||
useEffect(() => {
|
||||
currentIndexRef.current = currentIndex;
|
||||
}, [currentIndex]);
|
||||
|
||||
useEffect(() => {
|
||||
isPlayingRef.current = isPlaying;
|
||||
}, [isPlaying]);
|
||||
|
||||
useEffect(() => {
|
||||
wordsLengthRef.current = words.length;
|
||||
}, [words.length]);
|
||||
@@ -604,6 +611,31 @@ export default function App() {
|
||||
document.removeEventListener("fullscreenchange", handleFullscreenChange);
|
||||
}, []);
|
||||
|
||||
// Keep the screen awake while playing (best effort; may be unsupported).
|
||||
useEffect(() => {
|
||||
const wl = wakeLockRef.current;
|
||||
if (!isPlaying) {
|
||||
void wl.release();
|
||||
return;
|
||||
}
|
||||
|
||||
void wl.request();
|
||||
|
||||
const onVisibilityChange = () => {
|
||||
if (document.visibilityState === "visible" && isPlayingRef.current) {
|
||||
void wl.request();
|
||||
} else {
|
||||
void wl.release();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("visibilitychange", onVisibilityChange);
|
||||
return () => {
|
||||
document.removeEventListener("visibilitychange", onVisibilityChange);
|
||||
void wl.release();
|
||||
};
|
||||
}, [isPlaying]);
|
||||
|
||||
const handleProgressClick = useCallback(
|
||||
(e: ReactMouseEvent<HTMLDivElement>) => {
|
||||
const rect = e.currentTarget.getBoundingClientRect();
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// Best-effort screen wake lock helper.
|
||||
// Supported in Chromium-based browsers and some others; not supported in iOS Safari.
|
||||
|
||||
export type WakeLockHandle = {
|
||||
request: () => Promise<void>;
|
||||
release: () => Promise<void>;
|
||||
};
|
||||
|
||||
type WakeLockSentinelLike = {
|
||||
released: boolean;
|
||||
release: () => Promise<void>;
|
||||
};
|
||||
|
||||
export function createWakeLockHandle(): WakeLockHandle {
|
||||
let sentinel: WakeLockSentinelLike | null = null;
|
||||
|
||||
const request = async () => {
|
||||
// Re-request is allowed; only keep one sentinel.
|
||||
if (sentinel && !sentinel.released) return;
|
||||
|
||||
const wl = (navigator as unknown as { wakeLock?: { request: (type: "screen") => Promise<WakeLockSentinelLike> } })
|
||||
.wakeLock;
|
||||
if (!wl) return;
|
||||
|
||||
try {
|
||||
sentinel = await wl.request("screen");
|
||||
} catch {
|
||||
// Not allowed (e.g. user gesture required, tab not visible) or unsupported.
|
||||
sentinel = null;
|
||||
}
|
||||
};
|
||||
|
||||
const release = async () => {
|
||||
const s = sentinel;
|
||||
sentinel = null;
|
||||
if (!s || s.released) return;
|
||||
try {
|
||||
await s.release();
|
||||
} catch {
|
||||
// Ignore.
|
||||
}
|
||||
};
|
||||
|
||||
return { request, release };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user