using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; namespace LumaTunnel.Client.ViewModels; public partial class DashboardViewModel : ObservableObject { [ObservableProperty] public partial bool IsEnabled { get; private set; } [ObservableProperty] public partial bool IsBusy { get; private set; } [ObservableProperty] public partial string StatusText { get; private set; } = "代理已关闭"; [ObservableProperty] public partial string ActionText { get; private set; } = "启用代理"; [ObservableProperty] public partial string CurrentNodeText { get; private set; } = "未连接"; [ObservableProperty] public partial string TrafficText { get; private set; } = "↑ 0 B/s ↓ 0 B/s"; [ObservableProperty] public partial string? ErrorText { get; private set; } [RelayCommand] private async Task ToggleAsync() { if (IsBusy) return; IsBusy = true; ErrorText = null; try { if (AppServices.IsEnabled) await AppServices.DisableAsync(); else await AppServices.EnableAsync(); } catch (Exception exception) { ErrorText = exception.Message; } finally { IsBusy = false; Refresh(0, 0); } } public void Refresh(long uploadPerSecond, long downloadPerSecond) { IsEnabled = AppServices.IsEnabled; StatusText = IsEnabled ? "代理运行中" : "代理已关闭"; ActionText = IsEnabled ? "关闭代理" : "启用代理"; CurrentNodeText = AppServices.Nodes.ActiveNode is { } node ? $"{node.Name} · {node.LastLatencyMilliseconds:0} ms" : AppServices.Profile.Mode == Shared.Models.ProxyMode.Direct ? "直连模式" : "未连接"; TrafficText = $"↑ {FormatRate(uploadPerSecond)} ↓ {FormatRate(downloadPerSecond)}"; } private static string FormatRate(long bytes) => bytes switch { >= 1024 * 1024 => $"{bytes / 1024d / 1024d:0.0} MB/s", >= 1024 => $"{bytes / 1024d:0.0} KB/s", _ => $"{bytes} B/s" }; }