There are multiple alternatives to be considered here. Here are the ones that we ran into:
- IdleObserver
- navigator.idle.query() and variations (chrome.idle, browser.idle)
Here are some guidance on Events vs Observers we got from the TAG review.
This formulation is inspired by @kenchris's feedback, the overall guidance on Observers vs EventTargets, and the Sensor API, specifically, the Accelerometer
class.
async function main() {
// feature detection.
if (!window.IdleDetector) {
console.log("IdleDetector is not available :(");
return;
}
console.log("IdleDetector is available! Go idle!");
try {
let idleDetector = new IdleDetector({ threshold: 60 });
idleDetector.addEventListener('change', ({user, screen}) => {
console.log(`idle change: ${user}, ${screen}`);
});
await idleDetector.start();
} catch (e) {
// deal with initialization errors.
// permission denied, running outside of top-level frame, etc
}
};
And for a one-shot reading of the state:
const {user, screen} = await IdleDetector.read({ threshold: 2 * 60 });
This formulation is inspired by the MutationObserver, the IntersectionObserver and the PerformanceObserver APIs.
const observer = new IdleObserver({user, screen} => {
// do stuff
});
// Define "idle" as two minutes of inactivity.
observer.observe({threshold: 2*60});
Open questions:
- Should we allow observer.disconnect()?
- Should we allow multiple new IdleObserver() to run concurrently?
This formulation is closer to chrome's chrome.idle.query()
API and browser.idle,queryState()
:
const monitor = navigator.idle.query({threshold: 2 * 60});
// Listen to state changes
monitor.addEventListener('change', ({user, screen}) => {
// do stuff
});
Or, if you only care about the current state:
navigator.idle.query({threshold: 2 * 60})
.addEventListener({once: true}, ({user, screen}) => {
// do stuff
});
Open questions:
- do we have a preference between
navigator.idle.query()
ornavigator.idle.observe()
? - should we
navigator.idle.query()
return aPromise
such that the current state is returned easily?
Here are some variations of the Observer pattern that we could try too:
navigator.idle.observe({threshold: 2*60}, (e) => console.log(e))
let observer = navigator.idle.query({threshold: 2*60}, e => console.log(e))
observe.observe()
// More consistent with MutationObserver, less consistent with
// the other static navigator.* APIs.
let observer = new IdleObserver(e => console.log(e));
observer.observe({threshold: 2*60});