using System.Windows; using System.Windows.Media; using System.Windows.Threading; using AxCopilot.Services; namespace AxCopilot.Views; public partial class LauncherWindow { private DispatcherTimer? _widgetTimer; private int _widgetBatteryTick; private int _widgetWeatherTick; internal void StartWidgetUpdates() { PerformanceMonitorService.Instance.StartPolling(); PomodoroService.Instance.StateChanged -= OnPomoStateChanged; PomodoroService.Instance.StateChanged += OnPomoStateChanged; _vm.UpdateWidgets(); UpdateWidgetVisibility(); UpdateBatteryWidget(); _ = RefreshWeatherAsync(); if (_widgetTimer == null) { _widgetTimer = new DispatcherTimer(DispatcherPriority.Background) { Interval = TimeSpan.FromSeconds(1) }; _widgetTimer.Tick += (_, _) => { _vm.UpdateWidgets(); UpdateWidgetVisibility(); if (_vm.Widget_PerfText.Length > 0 && _widgetBatteryTick++ % 30 == 0) UpdateBatteryWidget(); if (_widgetWeatherTick++ % 120 == 0) _ = RefreshWeatherAsync(); }; } _widgetTimer.Start(); UpdatePomoWidgetStyle(); } internal void StopWidgetUpdates() { _widgetTimer?.Stop(); PerformanceMonitorService.Instance.StopPolling(); PomodoroService.Instance.StateChanged -= OnPomoStateChanged; } private void OnPomoStateChanged(object? sender, EventArgs e) { Dispatcher.InvokeAsync(() => { _vm.UpdateWidgets(); UpdatePomoWidgetStyle(); UpdateWidgetVisibility(); }); } private void UpdatePomoWidgetStyle() { if (WgtPomo == null) return; var running = PomodoroService.Instance.IsRunning; WgtPomo.Background = running ? new SolidColorBrush(Color.FromArgb(0x1E, 0xF5, 0x9E, 0x0B)) : new SolidColorBrush(Color.FromArgb(0x0D, 0xF5, 0x9E, 0x0B)); } private void UpdateWidgetVisibility() { var launcher = CurrentApp?.SettingsService?.Settings?.Launcher; if (launcher == null) return; if (WgtPerf != null) WgtPerf.Visibility = launcher.ShowWidgetPerf ? Visibility.Visible : Visibility.Collapsed; if (WgtPomo != null) WgtPomo.Visibility = launcher.ShowWidgetPomo ? Visibility.Visible : Visibility.Collapsed; if (WgtNote != null) WgtNote.Visibility = launcher.ShowWidgetNote ? Visibility.Visible : Visibility.Collapsed; if (WgtWeather != null) WgtWeather.Visibility = launcher.ShowWidgetWeather ? Visibility.Visible : Visibility.Collapsed; if (WgtCal != null) WgtCal.Visibility = launcher.ShowWidgetCalendar ? Visibility.Visible : Visibility.Collapsed; if (WgtBattery != null) WgtBattery.Visibility = launcher.ShowWidgetBattery && _vm.Widget_BatteryVisible ? Visibility.Visible : Visibility.Collapsed; var hasAny = launcher.ShowWidgetPerf || launcher.ShowWidgetPomo || launcher.ShowWidgetNote || launcher.ShowWidgetWeather || launcher.ShowWidgetCalendar || (launcher.ShowWidgetBattery && _vm.Widget_BatteryVisible); if (WidgetBar != null) WidgetBar.Visibility = hasAny ? Visibility.Visible : Visibility.Collapsed; } private void WgtPerf_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { _vm.InputText = "info "; InputBox?.Focus(); } private void WgtPomo_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { _vm.InputText = "pomo "; InputBox?.Focus(); } private void WgtNote_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { _vm.InputText = "note "; InputBox?.Focus(); } private void WgtWeather_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { var internalMode = CurrentApp?.SettingsService?.Settings.InternalModeEnabled ?? true; if (!internalMode) { try { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("https://wttr.in") { UseShellExecute = true }); } catch (Exception ex) { LogService.Warn($"날씨 페이지 열기 실패: {ex.Message}"); } } else { WeatherWidgetService.Invalidate(); _ = RefreshWeatherAsync(); } } private void WgtCal_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { try { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("ms-clock:") { UseShellExecute = true }); } catch { try { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("outlookcal:") { UseShellExecute = true }); } catch (Exception ex) { LogService.Warn($"일정 열기 실패: {ex.Message}"); } } } private void WgtBattery_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { try { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("ms-settings:powersleep") { UseShellExecute = true }); } catch (Exception ex) { LogService.Warn($"전원 설정 열기 실패: {ex.Message}"); } } private void UpdateBatteryWidget() { try { var power = System.Windows.Forms.SystemInformation.PowerStatus; var pct = power.BatteryLifePercent; if (pct > 1.0f || pct < 0f) { _vm.Widget_BatteryVisible = false; UpdateWidgetVisibility(); return; } _vm.Widget_BatteryVisible = true; var pctInt = (int)(pct * 100); var charging = power.PowerLineStatus == System.Windows.Forms.PowerLineStatus.Online; _vm.Widget_BatteryText = charging ? $"{pctInt}% 충전" : $"{pctInt}%"; _vm.Widget_BatteryIcon = charging ? "\uE83E" : pctInt >= 85 ? "\uEBA7" : pctInt >= 70 ? "\uEBA5" : pctInt >= 50 ? "\uEBA3" : pctInt >= 25 ? "\uEBA1" : "\uEBA0"; UpdateWidgetVisibility(); } catch (Exception ex) { LogService.Warn($"배터리 상태 갱신 실패: {ex.Message}"); _vm.Widget_BatteryVisible = false; UpdateWidgetVisibility(); } } private async Task RefreshWeatherAsync() { var internalMode = CurrentApp?.SettingsService?.Settings.InternalModeEnabled ?? true; await WeatherWidgetService.RefreshAsync(internalMode); await Dispatcher.InvokeAsync(() => { _vm.Widget_WeatherText = WeatherWidgetService.CachedText; UpdateWidgetVisibility(); }); } }