XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

LumaTunnel

【WinUI】LumaTunnel 是一个面向个人多设备的 Windows 代理系统。客户端在本机提供 HTTP/HTTPS CONNECT 与 SOCKS5 TCP 代理,并通过一个受信任 TLS 证书保护的 WSS 会话,将多个 TCP 流复用到自建 Windows Server 节点。

公开
关注 0 Fork 0 Star 0
UTF-8
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"
    };
}