NgbModal dialog is not opening consistnetly when app is openend in more than 1 browser tabs

24 Views Asked by At

I have an Angular application that has an user inactivity timer implemented. The idea is that if the user is not interacting with the app for certain period of time, the app will open a bootstrap modal dialog with a prompt that the user will be logged out unless they respond to the modal dialog. The problem I am experiencing is that when the app is opened in more than 2 browser tabs, the dialog is not always visible. It seems that it has been partially created, but has missing contents and styles to be properly displayed to the user. I am using NgbModal Service and the open method to create the modal and set its content and while debugging the codebase in the browser Dev Tools I don't see any errors or issues and all is set as it should but the end result is not OK. From the De Tools I can locate the problematic modal and even reset the timer as its button is there but I wonder why it is not visible and created in this kind of uncomplete state.

Here is a brief sample of the component I am using to implement the modal logic: I am subscribing to an observable from the app's Authentication service that is emitting whenever an inactivity timer expires(this considers all tabs by utilizing BroadcastChannel) and upon such event my component opens a dialog usning the NgbModal service(v.10.0.0) and update its content every second with a timer letting the user know when it will expire. Also on each update it checks for whether there has been a change from another tab to the this.authService.userInactivityTimerRunning. All this is working fine but the creation of the dialog seem to be problematic. Any ideas what I am doing wrong will be appreciated.

export class UserInactivityComponent implements OnInit, OnDestroy {

  private readonly destroy$ = new Subject();
  private modalRef: NgbModalRef;
  
  constructor(
    private router: Router,
    private authService: AuthService,
    private modalService: NgbModal
  ) 

  ngOnInit(): void {
    this.authService.userInactivity()
      .pipe(takeUntil(this.destroy$))
      .subscribe(() => {
        this.openConfirmationModal();
      });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  openConfirmationModal(): void {
    let timeLeft = environment.userInactivityAlertTimeout / 1000;
    this.modalRef = this.modalService.open(ConfirmationModalComponent);
    this.modalRef.componentInstance.showCancelButton = false;
    this.modalRef.componentInstance.title = 'Are you still here?';
    this.modalRef.componentInstance.body = `${timeLeft} ${timeLeft > 1 ? 'seconds' : 'second'} until you are signed out.`;
    this.modalRef.componentInstance.buttonText = `Yes`;

    const interval = setInterval(() => {
      if (timeLeft > 0) {
        if(!this.authService.userInactivityTimerRunning){
          timeLeft--;
          this.modalRef.componentInstance.body = `${timeLeft} ${timeLeft > 1 ? 'seconds' : 'second'} until you are signed out.`;
        }else{
          this.modalRef.close("Modal closed");
        }
      } else {
        clearInterval(interval);
        this.router.navigate(['/sign-out']);
      }
    }, 1000);

    this.modalRef.result
      .then(() => {
        clearInterval(interval);
        this.authService.resetUserInactivityTimer();
      })
      .catch(() => { });
  }
}

0

There are 0 best solutions below