Skip to content

Instantly share code, notes, and snippets.

@michael-lynch
Created July 31, 2024 19:59
Show Gist options
  • Select an option

  • Save michael-lynch/cda64c85d2f02479f7c5b68029191378 to your computer and use it in GitHub Desktop.

Select an option

Save michael-lynch/cda64c85d2f02479f7c5b68029191378 to your computer and use it in GitHub Desktop.
// react
import { useCallback, useEffect, useRef } from 'react';
// props
export interface UseIdleProps {
events?: string[];
onIdle: () => void;
onPrompt?: () => void;
promptTimeout?: number;
timeout: number;
}
export const useIdle = ({
events = [
'click',
'DOMMouseScroll',
'keydown',
'load',
'MSPointerDown',
'MSPointerMove',
'mousedown',
'mousemove',
'mousewheel',
'scroll',
'touchmove',
'touchstart',
'visibilitychange',
'wheel',
],
onIdle,
onPrompt,
promptTimeout,
timeout = 10000,
}: UseIdleProps) => {
// vars
const timer = useRef<ReturnType<typeof setTimeout> | undefined>();
const timerPrompt = useRef<ReturnType<typeof setTimeout> | undefined>();
const getTimeInUnit = useCallback(() => {
// define timeout in seconds
let time = timeout / 1000;
let unit = 'seconds';
if (timeout > 60000) {
// define timeout in minutes
time = timeout / 60000;
unit = 'minutes';
}
return {
time,
unit,
};
}, [timeout]);
// set timeouts
useEffect(() => {
const { time, unit } = getTimeInUnit();
const handleClearTimeout = () => {
if (timer.current) {
clearTimeout(timer.current);
}
if (timerPrompt.current) {
clearTimeout(timerPrompt.current);
}
};
const handleSetTimeout = () => {
// start idle timeout
timer.current = setTimeout(() => {
console.log(`User was idle for ${time} ${unit}.`);
// reset timer
handleClearTimeout();
// remove event listeners
for (let i = 0; i < events.length; i++) {
window.removeEventListener(events[i], handleClearTimeout);
}
// callback
if (onIdle) {
onIdle();
}
}, timeout);
// start prompt timeout
if (promptTimeout) {
timerPrompt.current = setTimeout(() => {
if (onPrompt) {
onPrompt();
}
}, promptTimeout);
}
};
for (let i = 0; i < events.length; i++) {
window.addEventListener(events[i], () => {
// reset timeout
handleClearTimeout();
handleSetTimeout();
});
}
}, [events, getTimeInUnit, onIdle, onPrompt, promptTimeout, timeout]);
useEffect(() => {
const { time, unit } = getTimeInUnit();
console.warn(`Idle event set for ${time} ${unit}.`);
}, [getTimeInUnit]);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment