WEB-384: Fix idle timer (#2733)

This commit is contained in:
Adam Saghy
2025-10-29 14:05:47 -06:00
committed by GitHub
parent 28c8f7b9c4
commit b63b0e19cc
3 changed files with 77 additions and 21 deletions
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { environment } from '../../../environments/environment';
import { interval, merge, fromEvent, Observable } from 'rxjs';
import { takeUntil, repeat, map } from 'rxjs/operators';
import { fromEvent, merge, Subject, timer, Observable, Subscription } from 'rxjs';
import { switchMap, takeUntil, tap, map } from 'rxjs/operators';
/**
* Idle timeout service used to track idle user
@@ -11,24 +11,59 @@ import { takeUntil, repeat, map } from 'rxjs/operators';
})
export class IdleTimeoutService {
// max timeout for an idle user
readonly timeoutDelay = environment.session.timeout.idleTimeout || 300000; // 5 minutes
private readonly timeoutDelay = environment.session.timeout.idleTimeout || 300000;
private timeout$ = new Subject<void>();
private resetTimer$ = new Subject<void>();
private active = false;
private timerSubscription?: Subscription;
private userActionsSubscription?: Subscription;
// observable timeout
readonly $onSessionTimeout: Observable<void>;
constructor() {
const events = [
'mousemove',
'keydown',
'wheel',
'mousedown',
'scroll'
];
const $signal = merge(...events.map((eventName) => fromEvent(document, eventName)));
this.$onSessionTimeout = interval(this.timeoutDelay).pipe(
takeUntil($signal),
map((): void => undefined),
repeat()
);
this.$onSessionTimeout = this.timeout$.asObservable();
this.resetTimer$.subscribe(() => {
this.timerSubscription?.unsubscribe();
this.timerSubscription = timer(this.timeoutDelay).subscribe(() => {
this.timeout$.next();
this.stop();
});
});
}
start() {
if (!this.active) {
this.active = true;
this.reset();
// Subscribe to user actions only when active
const events = [
'mousemove',
'keydown',
'wheel',
'mousedown',
'scroll'
];
const userActions$ = merge(...events.map((e) => fromEvent(document, e)));
this.userActionsSubscription = userActions$.subscribe(() => {
this.reset();
});
}
}
stop() {
if (this.active) {
this.active = false;
this.timerSubscription?.unsubscribe();
this.userActionsSubscription?.unsubscribe();
}
}
reset() {
if (this.active) {
this.resetTimer$.next();
}
}
}