- ReminderPopupWindow의 자동 닫힘 경로를 점검하고 UI 타이머와 실제 종료 타이머를 분리함 - 남은 시간 계산을 절대 시각 기준으로 바꾸고 Task.Delay 기반 종료 fail-safe를 추가해 팝업이 남는 경우를 줄임 - 창 종료 시 CancellationToken과 타이머를 함께 정리해 후속 종료 처리도 안전하게 맞춤 - README와 DEVELOPMENT 문서에 변경 목적과 검증 결과를 로컬 시각 기준으로 기록함 - 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ (경고 0, 오류 0)
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Threading;
|
||||
@@ -26,7 +28,9 @@ public partial class ReminderPopupWindow : Window
|
||||
// ─── 타이머 ───────────────────────────────────────────────────────────────
|
||||
private readonly DispatcherTimer _timer;
|
||||
private readonly EventHandler _tickHandler;
|
||||
private int _remaining;
|
||||
private readonly CancellationTokenSource _autoCloseCts = new();
|
||||
private readonly DateTime _closeAtUtc;
|
||||
private readonly int _displaySeconds;
|
||||
|
||||
public ReminderPopupWindow(
|
||||
string quoteText,
|
||||
@@ -56,9 +60,10 @@ public partial class ReminderPopupWindow : Window
|
||||
: "오늘 방금 시작했습니다";
|
||||
|
||||
// ── 카운트다운 ──
|
||||
_remaining = Math.Max(3, cfg.DisplaySeconds);
|
||||
CountdownBar.Maximum = _remaining;
|
||||
CountdownBar.Value = _remaining;
|
||||
_displaySeconds = Math.Max(3, cfg.DisplaySeconds);
|
||||
_closeAtUtc = DateTime.UtcNow.AddSeconds(_displaySeconds);
|
||||
CountdownBar.Maximum = _displaySeconds;
|
||||
CountdownBar.Value = _displaySeconds;
|
||||
|
||||
// ── 위치: 레이아웃 완료 후 설정 ──
|
||||
Loaded += (_, _) =>
|
||||
@@ -71,13 +76,15 @@ public partial class ReminderPopupWindow : Window
|
||||
// ── 타이머 ──
|
||||
_tickHandler = (_, _) =>
|
||||
{
|
||||
_remaining--;
|
||||
CountdownBar.Value = _remaining;
|
||||
if (_remaining <= 0) Close();
|
||||
var remainingSeconds = Math.Max(0, (_closeAtUtc - DateTime.UtcNow).TotalSeconds);
|
||||
CountdownBar.Value = remainingSeconds;
|
||||
if (remainingSeconds <= 0)
|
||||
Close();
|
||||
};
|
||||
_timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
|
||||
_timer.Tick += _tickHandler;
|
||||
_timer.Start();
|
||||
_ = StartAutoCloseAsync(_autoCloseCts.Token);
|
||||
|
||||
// ── Esc 키 닫기 ──
|
||||
KeyDown += (_, e) =>
|
||||
@@ -132,10 +139,34 @@ public partial class ReminderPopupWindow : Window
|
||||
|
||||
private void CloseBtn_Click(object sender, RoutedEventArgs e) => Close();
|
||||
|
||||
private async Task StartAutoCloseAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(_displaySeconds), cancellationToken);
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
await Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
if (IsVisible)
|
||||
Close();
|
||||
}, DispatcherPriority.Background, cancellationToken);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
_autoCloseCts.Cancel();
|
||||
_timer.Stop();
|
||||
_timer.Tick -= _tickHandler;
|
||||
_autoCloseCts.Dispose();
|
||||
base.OnClosed(e);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user