maison_alexandra/www/js/class/SessionTicker.js

65 lines
1.8 KiB
JavaScript

export default class SessionTicker {
constructor({ duration, onTick, onExpire, tickInterval = 1 }) {
this.duration = duration;
this.onTick = onTick;
this.onExpire = onExpire;
this.tickInterval = tickInterval;
this.expiresAt = null;
this._interval = null;
this._onVisibility = this._onVisibility.bind(this);
this._onPageShow = this._onPageShow.bind(this);
}
start() {
this.expiresAt = Date.now() + this.duration * 1000;
this._attachListeners();
this._tick();
this._interval = setInterval(() => this._tick(), this.tickInterval * 1000);
return this;
}
stop() {
clearInterval(this._interval);
this._interval = null;
this._detachListeners();
return this;
}
reset(newDuration) {
if (newDuration != null) this.duration = newDuration;
this.stop();
return this.start();
}
getRemaining() {
if (!this.expiresAt) return 0;
return Math.max(0, Math.ceil((this.expiresAt - Date.now()) / 1000));
}
_tick() {
const remaining = this.getRemaining();
this.onTick?.(remaining);
if (remaining <= 0) {
this.stop();
this.onExpire?.();
}
}
_onVisibility() {
if (document.visibilityState === 'visible') this._tick();
}
_onPageShow(e) {
if (e.persisted) this._tick();
}
_attachListeners() {
document.addEventListener('visibilitychange', this._onVisibility);
window.addEventListener('pageshow', this._onPageShow);
}
_detachListeners() {
document.removeEventListener('visibilitychange', this._onVisibility);
window.removeEventListener('pageshow', this._onPageShow);
}
}