Files
AX-Copilot-Codex/src/AxCopilot/Views/LauncherWindow.Widgets.cs
lacvet 5fd69d32f5
Some checks failed
Release Gate / gate (push) Has been cancelled
AX Commander 하단 위젯 설정 분리와 서버 상태 제거
- 일반 설정의 AX Commander 섹션에 성능, 포모도로, 메모, 날씨, 일정, 배터리 위젯 표시 토글을 추가

- 런처 하단의 Ollama, API, MCP 서버 상태 위젯을 완전히 제거하고 남은 위젯만 설정값 기준으로 표시되도록 정리

- 배터리 위젯은 실제 배터리 가용 상태와 사용자 토글을 함께 반영하고 위젯이 모두 꺼지면 하단 바 전체를 숨기도록 조정

- README와 DEVELOPMENT 문서를 2026-04-05 15:16 (KST) 기준으로 갱신하고 dotnet build 검증에서 경고 0 오류 0 확인
2026-04-05 13:48:00 +09:00

219 lines
7.1 KiB
C#

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();
});
}
}