fuzzyworld

north-star / mobile / files / src / features / ui / wake_lock_controller.ts

Branch mobile · default branch · all branches

wake_lock_controller.ts

3.9 KB · history · blame

1import { createWakeLockManager } from '../../platform/wakelock';
2import { createToast } from '../../core/toast';
3import { PUBLIC_SETTINGS } from '../../public_settings';
4
5type WakeLockControllerOptions = {
6 wakeLockToggle: HTMLElement | null;
7 isSessionStarted: () => boolean;
8 isFullscreen: () => boolean;
9};
10
11const WAKE_LOCK_ENABLED_STORAGE_KEY = 'friend-compass-wake-lock-enabled';
12
13export const initWakeLockController = ({
14 wakeLockToggle,
15 isSessionStarted,
16 isFullscreen
17}: WakeLockControllerOptions) => {
18 const {
19 setWakeLockEnabled,
20 hasWakeLockSupport
21 } = createWakeLockManager();
22
23 const savedWakeLockPreference = localStorage.getItem(WAKE_LOCK_ENABLED_STORAGE_KEY);
24 let wakeLockEnabledByToggle = savedWakeLockPreference !== '0';
25 const wakeLockToast = createToast({ className: 'wake-lock-toast' });
26
27 const getEffectiveWakeLockEnabled = () => isSessionStarted() && (isFullscreen() || wakeLockEnabledByToggle);
28
29 const updateWakeLockToggleUi = () => {
30 if (!(wakeLockToggle instanceof HTMLButtonElement)) return;
31
32 const supported = hasWakeLockSupport();
33 const forcedByFullscreen = isFullscreen();
34 const enabled = forcedByFullscreen || wakeLockEnabledByToggle;
35
36 wakeLockToggle.disabled = !supported;
37 wakeLockToggle.textContent = enabled
38 ? PUBLIC_SETTINGS.ui.emojis.wakeLock.on
39 : PUBLIC_SETTINGS.ui.emojis.wakeLock.off;
40 wakeLockToggle.classList.toggle('is-on', enabled);
41 wakeLockToggle.setAttribute('aria-pressed', String(enabled));
42
43 if (!supported) {
44 wakeLockToggle.title = 'Wake lock is not supported on this browser/device.';
45 wakeLockToggle.setAttribute('aria-label', 'Wake lock unsupported');
46 return;
47 }
48
49 if (forcedByFullscreen) {
50 wakeLockToggle.title = 'Stay awake is enabled automatically in fullscreen mode.';
51 wakeLockToggle.setAttribute('aria-label', 'Stay awake enabled in fullscreen');
52 return;
53 }
54
55 wakeLockToggle.title = enabled ? 'Stay awake is on. Tap to allow sleeping.' : 'Stay awake is off. Tap to keep screen awake.';
56 wakeLockToggle.setAttribute('aria-label', enabled ? 'Turn stay awake off' : 'Turn stay awake on');
57 };
58
59 const syncWakeLockPreference = ({
60 announce = false,
61 source = 'toggle'
62 }: {
63 announce?: boolean;
64 source?: 'toggle' | 'fullscreen';
65 } = {}) => {
66 const shouldStayAwake = getEffectiveWakeLockEnabled();
67 void setWakeLockEnabled(shouldStayAwake);
68 updateWakeLockToggleUi();
69
70 if (!announce) return;
71 if (!hasWakeLockSupport()) {
72 wakeLockToast.show('Stay awake is not supported on this browser.');
73 return;
74 }
75
76 if (source === 'toggle') {
77 if (shouldStayAwake) {
78 wakeLockToast.show(isSessionStarted() ? 'Stay awake is on.' : 'Stay awake enabled for when you start the session.');
79 return;
80 }
81 wakeLockToast.show('Stay awake is off.');
82 return;
83 }
84
85 if (isFullscreen()) {
86 wakeLockToast.show(isSessionStarted() ? 'Fullscreen keeps your screen awake.' : 'Fullscreen will keep your screen awake once the session starts.');
87 return;
88 }
89
90 wakeLockToast.show(shouldStayAwake ? 'Exited fullscreen. Stay awake is on.' : 'Exited fullscreen. Stay awake is off.');
91 };
92
93 if (wakeLockToggle instanceof HTMLButtonElement) {
94 wakeLockToggle.addEventListener('click', () => {
95 wakeLockEnabledByToggle = !wakeLockEnabledByToggle;
96 localStorage.setItem(WAKE_LOCK_ENABLED_STORAGE_KEY, wakeLockEnabledByToggle ? '1' : '0');
97 syncWakeLockPreference({ announce: true, source: 'toggle' });
98 });
99 }
100
101 updateWakeLockToggleUi();
102
103 return {
104 syncWakeLockPreference,
105 updateWakeLockToggleUi
106 };
107};