Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ function Component() {
onRequest: () => alert('Screen Wake Lock: requested!'),
onError: () => alert('An error happened 💥'),
onRelease: () => alert('Screen Wake Lock: released!'),
reacquireOnPageVisible: true,
});

return (
Expand All @@ -69,10 +70,7 @@ function Component() {
<br />
Released: <b>{`${released}`}</b>
</p>
<button
type="button"
onClick={() => (released === false ? release() : request())}
>
<button type="button" onClick={() => (released === false ? release() : request())}>
{released === false ? 'Release' : 'Request'}
</button>
</div>
Expand All @@ -84,11 +82,12 @@ export default Component;

## Props

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

### Returns

Expand Down
22 changes: 22 additions & 0 deletions src/use-wake-lock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ export interface WakeLockOptions {
onError?: (error: Error) => void;
onRequest?: () => void;
onRelease?: EventListener;
reacquireOnPageVisible?: boolean;
}

export const useWakeLock = ({
onError,
onRequest,
onRelease,
reacquireOnPageVisible = false,
}: WakeLockOptions | undefined = {}) => {
const [released, setReleased] = React.useState<boolean | undefined>();
const wakeLock = React.useRef<WakeLockSentinel | null>(null);
Expand Down Expand Up @@ -68,6 +70,26 @@ export const useWakeLock = ({
wakeLock.current && (await wakeLock.current.release());
}, [isSupported]);

React.useEffect(() => {
if (reacquireOnPageVisible) {
const handleVisibilityChange = async () => {
if (wakeLock.current && document.visibilityState === 'visible') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Deftera186 @jorisre hey folks, I might be missing something here, but shouldn't this check for if (wakeLock.current === null && document.visibilityState === 'visible') instead?

Navigating away from the page triggers wakeLock.current.onrelease, which then sets wakeLock.current = null.

Returning to the page then should check for wakeLock.current === null, before attempting to reacquire the lock.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch

try {
wakeLock.current = await navigator.wakeLock.request('screen');
} catch (error: any) {
onError?.(error);
}
}
};

document.addEventListener('visibilitychange', handleVisibilityChange);
return () => {
document.removeEventListener('visibilitychange', handleVisibilityChange);
};
}
return undefined;
}, [reacquireOnPageVisible, onError]);

return {
isSupported,
request,
Expand Down
34 changes: 34 additions & 0 deletions test/use-wake-lock.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,37 @@ test('useWakeLock should call `onRelease` when wakeLockSentinel is released', as

expect(handleRelease).toHaveBeenCalledWith(expect.any(Event));
});

test('useWakeLock reacquires wake lock on page visibility change when `reacquireOnPageVisible` is true', async () => {
const handleError = jest.fn();
const { result } = renderHook(() => useWakeLock({ reacquireOnPageVisible: true, onError: handleError }));

await act(async () => {
await result.current.request();
});

expect(window.navigator.wakeLock.request).toHaveBeenCalledTimes(1);
expect(result.current.type).toEqual('screen');
expect(result.current.released).toBe(false);

// Mock document.visibilityState to 'hidden'
Object.defineProperty(document, 'visibilityState', {
value: 'hidden',
configurable: true,
});
document.dispatchEvent(new Event('visibilitychange'));

// Mock document.visibilityState to 'visible'
Object.defineProperty(document, 'visibilityState', {
value: 'visible',
configurable: true,
});
await act(async () => {
document.dispatchEvent(new Event('visibilitychange'));
});

expect(window.navigator.wakeLock.request).toHaveBeenCalledTimes(2);
expect(result.current.type).toEqual('screen');
expect(result.current.released).toBe(false);
expect(handleError).not.toHaveBeenCalled();
});
Loading