Logout MatDialog not working in mobile browsers
Asked Answered
T

2

6

I want to alert user if he is idle for 20 min. So, created a service.

It is working fine with desktop but in mobile phone its not showing up and sometimes if screen left in the background for couple of hours, then logout dialog screen started the countdown once i got on the page again.

I mean it should logout and I should see login page but here it shows logout alert countdown page after couple of hours else it doesn't show up in mobile browser.

Here is my code please let me know which logic I am missing.

Here is Service.ts file. check() will be called for every 5 sec and will logout alert will show in 20 sec...

const MINUTES_UNITL_AUTO_LOGOUT = 0.2; // 1 mins- 20
const CHECK_INTERVAL = 5000; // checks every 5 secs- 5000

@Injectable({
  providedIn: "root",
})
export class AutoLogoutService {
  logOutInterval: any;

  constructor(
    private localStorage: LocalStoreManager,
    private authService: AuthService,
    public dialog: MatDialog
  ) {
    this.localStorage.savePermanentData(
      Date.now().toString().toString(),
      DBkeys.AUTO_LOGOUT
    );
    this.initListener();
  }

  initListener() {
    document.body.addEventListener("click", () => this.reset());
    document.body.addEventListener("mouseover", () => this.reset());
    document.body.addEventListener("mouseout", () => this.reset());
    document.body.addEventListener("keydown", () => this.reset());
    document.body.addEventListener("keyup", () => this.reset());
    document.body.addEventListener("keypress", () => this.reset());
  }

  reset() {
    this.setLastAction(Date.now());
  }

  initInterval() {
    this.logOutInterval = setInterval(() => {
      this.check();
    }, CHECK_INTERVAL);
  }
  clearInterval() {
    clearInterval(this.logOutInterval);
  }

  check() {
    const now = Date.now();
    const timeleft = this.getLastAction() + MINUTES_UNITL_AUTO_LOGOUT * 60 * 1000;
    const diff = timeleft - now;
    const isTimeout = diff < 0;
    console.log(diff);
    if (isTimeout && !this.authService.isLogoutDialogOpenned) {
      this.authService.isLogoutDialogOpenned = true;
      this.dialog
        .open(LogoutDialog, {
          maxWidth: "100vw",
        })
        .afterClosed()
        .subscribe((result) => {
          this.authService.isLogoutDialogOpenned = false;
        });
    }
  }

  public getLastAction() {
    return parseInt(this.localStorage.getData(DBkeys.AUTO_LOGOUT));
  }

  public setLastAction(lastAction: number) {
    this.localStorage.savePermanentData(
      lastAction.toString(),
      DBkeys.AUTO_LOGOUT
    );
  }
}
Trela answered 15/5, 2020 at 11:34 Comment(1)
You could try if the visibility of the page changes, when the page is backgrounded or when the phone goes to sleep without the page actually going into the background, and also when it comes back from those states. If yes, you could use those changes to store a timestamp when the page goes down, check it when it comes up, and decide based on the difference.Avery
T
3

Thanks for the suggestions, but the below solution worked for me

Used ngZone where it runs in the background

initInterval() {
    this.ngZone.runOutsideAngular(() => {
      this.logOutInterval = setInterval(() => {
        this.check();
      }, CHECK_INTERVAL);
    })
  }
  clearInterval() {
    clearInterval(this.logOutInterval);
  }

  check() {
    const now = Date.now();
    const timeleft =
      this.getLastAction() + MINUTES_UNITL_AUTO_LOGOUT * 60 * 1000;
    const diff = timeleft - now;
    const isTimeout = diff < 0;
    const isBackgroundLogoutEnabled = diff < -ONE_MINUTE;

    this.ngZone.run(() => {
      if (isTimeout && !this.authService.isLogoutDialogOpenned) {
        this.authService.isLogoutDialogOpenned = true;
        this.dialog
          .open(LogoutDialog, {
            maxWidth: "100vw",
          })
          .afterClosed()
          .subscribe((result) => {
            this.authService.isLogoutDialogOpenned = false;
          });
      }
      if(isBackgroundLogoutEnabled){
        this.clearInterval();
        this.authService.isLogoutDialogOpenned = false;
        this.authService.logout();
        this.authService.redirectLogoutUser();
        this.dialog.closeAll();
      }
    });
  }
Trela answered 26/5, 2020 at 13:58 Comment(0)
B
3

I believe in mobile, when user minimized browser your logic stops executing as mobile phones kill background application automatically for ram management and when he relaunches browser your script starts again. You should also logout on destroy or on window.beforeunload event.

Blossomblot answered 23/5, 2020 at 7:56 Comment(0)
T
3

Thanks for the suggestions, but the below solution worked for me

Used ngZone where it runs in the background

initInterval() {
    this.ngZone.runOutsideAngular(() => {
      this.logOutInterval = setInterval(() => {
        this.check();
      }, CHECK_INTERVAL);
    })
  }
  clearInterval() {
    clearInterval(this.logOutInterval);
  }

  check() {
    const now = Date.now();
    const timeleft =
      this.getLastAction() + MINUTES_UNITL_AUTO_LOGOUT * 60 * 1000;
    const diff = timeleft - now;
    const isTimeout = diff < 0;
    const isBackgroundLogoutEnabled = diff < -ONE_MINUTE;

    this.ngZone.run(() => {
      if (isTimeout && !this.authService.isLogoutDialogOpenned) {
        this.authService.isLogoutDialogOpenned = true;
        this.dialog
          .open(LogoutDialog, {
            maxWidth: "100vw",
          })
          .afterClosed()
          .subscribe((result) => {
            this.authService.isLogoutDialogOpenned = false;
          });
      }
      if(isBackgroundLogoutEnabled){
        this.clearInterval();
        this.authService.isLogoutDialogOpenned = false;
        this.authService.logout();
        this.authService.redirectLogoutUser();
        this.dialog.closeAll();
      }
    });
  }
Trela answered 26/5, 2020 at 13:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.