using System.Windows.Threading; using CommunityToolkit.Mvvm.Messaging; using Livia.Models.Data; using Livia.Properties; using Livia.Utility; using Livia.Views.Utility; using Microsoft.Extensions.Logging; namespace Livia.Models; public interface IIdleTimer { void ResetTimer(); } public class IdleTimerTickMessage(IIdleTimer idleTimer) { public readonly IIdleTimer IdleTimer = idleTimer; } public class IdleTimer : IIdleTimer { private DateTime _lastActiveTime = DateTime.Now; private readonly TimeSpan _lockAfter = TimeSpan.FromMinutes(Settings.Default.LogoutAfter); private readonly ILogger _logger; private readonly IServerHandler _serverHandler; private readonly IWarningSystem _warningSystem; private static readonly TimeSpan TickInterval = new(0, 0, 5); private static readonly TimeSpan SnackBarWarningTime = new(0, 1, 0); public IdleTimer(ILogger logger, IServerHandler serverHandler, IWarningSystem warningSystem) { _logger = logger; _serverHandler = serverHandler; _warningSystem = warningSystem; if (Settings.Default.LogoutAfter <= 0) return; DispatcherTimer dispatcherTimer = new(); dispatcherTimer.Tick += Tick; dispatcherTimer.Interval = TickInterval; dispatcherTimer.Start(); } private void Tick(object? sender, EventArgs? e) { //sent tick message, any busy module will reset timer when receives this message WeakReferenceMessenger.Default.Send(new IdleTimerTickMessage(this)); //no access, do not lock again if (!_serverHandler.IsLoggedIn) { ResetTimer(); return; } TimeSpan idleTime = DateTime.Now - _lastActiveTime; TimeSpan timeToLock = _lockAfter - idleTime; if (timeToLock <= TimeSpan.Zero) { _logger.LogInformation("Idle time up"); _warningSystem.AddSnackbarMessage("IdleTimeout"); ResetTimer(); WeakReferenceMessenger.Default.Send(new LogoutMessage()); } else if (timeToLock <= SnackBarWarningTime) { _warningSystem.AddSnackbarMessage(TickInterval - TimeSpan.FromSeconds(0.7), "IdleTimeoutWarning", (int)Math.Ceiling(timeToLock.TotalSeconds)); } //waiting } public void ResetTimer() { //_logger.LogInformation("Timer reset"); _lastActiveTime = DateTime.Now; } }