237 lines
5.2 KiB
C#
237 lines
5.2 KiB
C#
using System;
|
|
using System.Timers;
|
|
using System.Windows.Threading;
|
|
using AxCopilot.Models;
|
|
using AxCopilot.Views;
|
|
using Microsoft.Win32;
|
|
|
|
namespace AxCopilot.Services;
|
|
|
|
public sealed class WorktimeReminderService : IDisposable
|
|
{
|
|
private readonly SettingsService _settings;
|
|
|
|
private readonly Dispatcher _dispatcher;
|
|
|
|
private readonly object _lock = new object();
|
|
|
|
private DateTime _sessionStart;
|
|
|
|
private TimeSpan _todayTotal;
|
|
|
|
private DateTime _lastDate;
|
|
|
|
private DateTime _lastShownAt;
|
|
|
|
private Timer? _periodicTimer;
|
|
|
|
private volatile bool _disposed;
|
|
|
|
public WorktimeReminderService(SettingsService settings, Dispatcher dispatcher)
|
|
{
|
|
_settings = settings;
|
|
_dispatcher = dispatcher;
|
|
_sessionStart = DateTime.Now;
|
|
_lastDate = DateTime.Today;
|
|
_lastShownAt = DateTime.MinValue;
|
|
try
|
|
{
|
|
int todayActiveSeconds = UsageStatisticsService.GetTodayActiveSeconds();
|
|
if (todayActiveSeconds > 0)
|
|
{
|
|
_todayTotal = TimeSpan.FromSeconds(todayActiveSeconds);
|
|
LogService.Info($"이전 세션 누적 시간 복원: {_todayTotal}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogService.Warn("이전 세션 시간 복원 실패: " + ex.Message);
|
|
}
|
|
SystemEvents.SessionSwitch += OnSessionSwitch;
|
|
LogService.Info("WorktimeReminderService 초기화 완료.");
|
|
ReminderSettings reminder = _settings.Settings.Reminder;
|
|
if (!reminder.Enabled)
|
|
{
|
|
return;
|
|
}
|
|
_dispatcher.BeginInvoke((Delegate)(Action)delegate
|
|
{
|
|
if (!_disposed)
|
|
{
|
|
ShowPopup();
|
|
}
|
|
}, (DispatcherPriority)2, Array.Empty<object>());
|
|
StartPeriodicTimer();
|
|
}
|
|
|
|
private void OnSessionSwitch(object sender, SessionSwitchEventArgs e)
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
LogService.Info($"SessionSwitch 이벤트: {e.Reason}");
|
|
lock (_lock)
|
|
{
|
|
switch (e.Reason)
|
|
{
|
|
case SessionSwitchReason.SessionLock:
|
|
AccumulateSession();
|
|
StopPeriodicTimer();
|
|
LogService.Info($"세션 잠금. 누적 시간: {_todayTotal}");
|
|
break;
|
|
case SessionSwitchReason.SessionLogon:
|
|
case SessionSwitchReason.SessionUnlock:
|
|
{
|
|
ResetForNewDayIfNeeded();
|
|
_sessionStart = DateTime.Now;
|
|
ReminderSettings reminder = _settings.Settings.Reminder;
|
|
if (!reminder.Enabled)
|
|
{
|
|
LogService.Info("알림 비활성화 상태. 팝업 생략.");
|
|
break;
|
|
}
|
|
int num = Math.Max(1, reminder.IntervalMinutes);
|
|
double totalMinutes = (DateTime.Now - _lastShownAt).TotalMinutes;
|
|
LogService.Info($"알림 간격 확인: 경과={totalMinutes:F1}분, 설정={num}분");
|
|
if (totalMinutes >= (double)num)
|
|
{
|
|
ShowPopup();
|
|
}
|
|
StartPeriodicTimer();
|
|
break;
|
|
}
|
|
case SessionSwitchReason.SessionLogoff:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void AccumulateSession()
|
|
{
|
|
ResetForNewDayIfNeeded();
|
|
_todayTotal += DateTime.Now - _sessionStart;
|
|
_sessionStart = DateTime.Now;
|
|
}
|
|
|
|
private void ResetForNewDayIfNeeded()
|
|
{
|
|
if (DateTime.Today == _lastDate)
|
|
{
|
|
return;
|
|
}
|
|
DateTime today = DateTime.Today;
|
|
_sessionStart = today;
|
|
_lastDate = DateTime.Today;
|
|
_lastShownAt = DateTime.MinValue;
|
|
try
|
|
{
|
|
int todayActiveSeconds = UsageStatisticsService.GetTodayActiveSeconds();
|
|
_todayTotal = ((todayActiveSeconds > 0) ? TimeSpan.FromSeconds(todayActiveSeconds) : TimeSpan.Zero);
|
|
}
|
|
catch
|
|
{
|
|
_todayTotal = TimeSpan.Zero;
|
|
}
|
|
}
|
|
|
|
public TimeSpan GetTodayUsage()
|
|
{
|
|
lock (_lock)
|
|
{
|
|
ResetForNewDayIfNeeded();
|
|
return _todayTotal + (DateTime.Now - _sessionStart);
|
|
}
|
|
}
|
|
|
|
private void StartPeriodicTimer()
|
|
{
|
|
StopPeriodicTimer();
|
|
int num = Math.Max(1, _settings.Settings.Reminder.IntervalMinutes);
|
|
_periodicTimer = new Timer(num * 60000);
|
|
_periodicTimer.Elapsed += OnPeriodicTimerElapsed;
|
|
_periodicTimer.AutoReset = true;
|
|
_periodicTimer.Start();
|
|
LogService.Info($"격려 알림 주기 타이머 시작: {num}분 간격");
|
|
}
|
|
|
|
private void StopPeriodicTimer()
|
|
{
|
|
if (_periodicTimer != null)
|
|
{
|
|
_periodicTimer.Elapsed -= OnPeriodicTimerElapsed;
|
|
_periodicTimer.Stop();
|
|
_periodicTimer.Dispose();
|
|
_periodicTimer = null;
|
|
}
|
|
}
|
|
|
|
private void OnPeriodicTimerElapsed(object? sender, ElapsedEventArgs e)
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
ReminderSettings reminder = _settings.Settings.Reminder;
|
|
if (!reminder.Enabled)
|
|
{
|
|
StopPeriodicTimer();
|
|
return;
|
|
}
|
|
lock (_lock)
|
|
{
|
|
ResetForNewDayIfNeeded();
|
|
ShowPopup();
|
|
}
|
|
}
|
|
|
|
public void RestartTimer()
|
|
{
|
|
ReminderSettings reminder = _settings.Settings.Reminder;
|
|
if (reminder.Enabled)
|
|
{
|
|
StartPeriodicTimer();
|
|
}
|
|
else
|
|
{
|
|
StopPeriodicTimer();
|
|
}
|
|
}
|
|
|
|
private void ShowPopup()
|
|
{
|
|
_lastShownAt = DateTime.Now;
|
|
TimeSpan usage = GetTodayUsage();
|
|
var (text, author) = QuoteService.GetRandom(_settings?.Settings.Reminder.EnabledCategories);
|
|
_dispatcher.BeginInvoke((Delegate)(Action)delegate
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
if (_settings != null)
|
|
{
|
|
ReminderPopupWindow reminderPopupWindow = new ReminderPopupWindow(text, author, usage, _settings);
|
|
reminderPopupWindow.Show();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogService.Warn("알림 팝업 표시 실패: " + ex.Message);
|
|
}
|
|
}, (DispatcherPriority)9, Array.Empty<object>());
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (!_disposed)
|
|
{
|
|
_disposed = true;
|
|
StopPeriodicTimer();
|
|
SystemEvents.SessionSwitch -= OnSessionSwitch;
|
|
}
|
|
}
|
|
}
|