Skip to content

Commit 691f1fc

Browse files
authored
feat: add reacquireOnPageVisible functionality (#279)
* Add reacquireOnPageVisible functionality - Implement `reacquireOnPageVisible` option in the hook - Add tests to verify `reacquireOnPageVisible` functionality - Solves issue #273 * Document the `reacquireOnPageVisible` prop Added documentation and updated the usage example
1 parent 793db87 commit 691f1fc

File tree

3 files changed

+64
-9
lines changed

3 files changed

+64
-9
lines changed

README.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ function Component() {
6060
onRequest: () => alert('Screen Wake Lock: requested!'),
6161
onError: () => alert('An error happened 💥'),
6262
onRelease: () => alert('Screen Wake Lock: released!'),
63+
reacquireOnPageVisible: true,
6364
});
6465

6566
return (
@@ -69,10 +70,7 @@ function Component() {
6970
<br />
7071
Released: <b>{`${released}`}</b>
7172
</p>
72-
<button
73-
type="button"
74-
onClick={() => (released === false ? release() : request())}
75-
>
73+
<button type="button" onClick={() => (released === false ? release() : request())}>
7674
{released === false ? 'Release' : 'Request'}
7775
</button>
7876
</div>
@@ -84,11 +82,12 @@ export default Component;
8482

8583
## Props
8684

87-
| Prop | description | default | required |
88-
| :---------: | :-----------------------------------------------------------: | :---------: | :------: |
89-
| `onRequest` | called on successfully `navigator.wakeLock.request` | `undefined` | false |
90-
| `onError` | called when caught an error from `navigator.wakeLock.request` | `undefined` | false |
91-
| `onRelease` | called when wake lock is released | `undefined` | false |
85+
| Prop | description | default | required |
86+
| :----------------------: | :-----------------------------------------------------------: | :---------: | :------: |
87+
| `onRequest` | called on successfully `navigator.wakeLock.request` | `undefined` | false |
88+
| `onError` | called when caught an error from `navigator.wakeLock.request` | `undefined` | false |
89+
| `onRelease` | called when wake lock is released | `undefined` | false |
90+
| `reacquireOnPageVisible` | Reacquires the wake lock when the page becomes visible again | `false` | false |
9291

9392
### Returns
9493

src/use-wake-lock.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ export interface WakeLockOptions {
77
onError?: (error: Error) => void;
88
onRequest?: () => void;
99
onRelease?: EventListener;
10+
reacquireOnPageVisible?: boolean;
1011
}
1112

1213
export const useWakeLock = ({
1314
onError,
1415
onRequest,
1516
onRelease,
17+
reacquireOnPageVisible = false,
1618
}: WakeLockOptions | undefined = {}) => {
1719
const [released, setReleased] = React.useState<boolean | undefined>();
1820
const wakeLock = React.useRef<WakeLockSentinel | null>(null);
@@ -68,6 +70,26 @@ export const useWakeLock = ({
6870
wakeLock.current && (await wakeLock.current.release());
6971
}, [isSupported]);
7072

73+
React.useEffect(() => {
74+
if (reacquireOnPageVisible) {
75+
const handleVisibilityChange = async () => {
76+
if (wakeLock.current && document.visibilityState === 'visible') {
77+
try {
78+
wakeLock.current = await navigator.wakeLock.request('screen');
79+
} catch (error: any) {
80+
onError?.(error);
81+
}
82+
}
83+
};
84+
85+
document.addEventListener('visibilitychange', handleVisibilityChange);
86+
return () => {
87+
document.removeEventListener('visibilitychange', handleVisibilityChange);
88+
};
89+
}
90+
return undefined;
91+
}, [reacquireOnPageVisible, onError]);
92+
7193
return {
7294
isSupported,
7395
request,

test/use-wake-lock.test.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,37 @@ test('useWakeLock should call `onRelease` when wakeLockSentinel is released', as
171171

172172
expect(handleRelease).toHaveBeenCalledWith(expect.any(Event));
173173
});
174+
175+
test('useWakeLock reacquires wake lock on page visibility change when `reacquireOnPageVisible` is true', async () => {
176+
const handleError = jest.fn();
177+
const { result } = renderHook(() => useWakeLock({ reacquireOnPageVisible: true, onError: handleError }));
178+
179+
await act(async () => {
180+
await result.current.request();
181+
});
182+
183+
expect(window.navigator.wakeLock.request).toHaveBeenCalledTimes(1);
184+
expect(result.current.type).toEqual('screen');
185+
expect(result.current.released).toBe(false);
186+
187+
// Mock document.visibilityState to 'hidden'
188+
Object.defineProperty(document, 'visibilityState', {
189+
value: 'hidden',
190+
configurable: true,
191+
});
192+
document.dispatchEvent(new Event('visibilitychange'));
193+
194+
// Mock document.visibilityState to 'visible'
195+
Object.defineProperty(document, 'visibilityState', {
196+
value: 'visible',
197+
configurable: true,
198+
});
199+
await act(async () => {
200+
document.dispatchEvent(new Event('visibilitychange'));
201+
});
202+
203+
expect(window.navigator.wakeLock.request).toHaveBeenCalledTimes(2);
204+
expect(result.current.type).toEqual('screen');
205+
expect(result.current.released).toBe(false);
206+
expect(handleError).not.toHaveBeenCalled();
207+
});

0 commit comments

Comments
 (0)