using CursorLang.Core.Models; using CursorLang.Core.Services; using CursorLang.Core.Threading; namespace CursorLang.Agent.Services; /// /// Manages the lifetime of the popup: the window is only responsible for showing it, /// while the decision of when to show and when to take it down is made here. /// /// /// The same service it always was, with DispatcherTimer swapped for /// : both tick on the thread that owns the window, so /// nothing else about the logic had to move. /// public sealed class LayoutPopupService : ILayoutPopupService, IDisposable { private readonly ILayoutPopupWindow _window; private readonly AppSettings _settings; private readonly MessageTimer _hideTimer = new(); public LayoutPopupService(ILayoutPopupWindow window, AppSettings settings) { _window = window; _settings = settings; _hideTimer.Tick += OnHideTimerTick; } public void Show(KeyboardLayout layout) { ShowUntilHidden(layout); // The duration is read on every show: it is changed in the settings on the fly. // Restarting the timer also prolongs the show on quick switches _hideTimer.Interval = _settings.Duration; _hideTimer.Start(); } public void ShowUntilHidden(KeyboardLayout layout) { _hideTimer.Stop(); _window.ShowPopup(layout.ShortName); } public void Hide() { _hideTimer.Stop(); _window.Hide(); } public void Dispose() { _hideTimer.Tick -= OnHideTimerTick; _hideTimer.Dispose(); _window.Close(); } private void OnHideTimerTick(object? sender, EventArgs e) { _hideTimer.Stop(); _window.Hide(); } }