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

XFEToolBox

【WPF】XFE工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace XFEToolBox.Client.Models;

public enum ActivityKind
{
    General,
    SoftwareDownload,
    ToolPackage,
    Build,
    Publish,
    Update
}

public enum ActivityState
{
    Pending,
    Running,
    Succeeded,
    Failed,
    Cancelled
}

public sealed class ActivityItem : ObservableObject
{
    private readonly CancellationTokenSource? cancellationSource;
    private ActivityState state = ActivityState.Pending;
    private double? progress;
    private string message = string.Empty;
    private bool canCancel;

    internal ActivityItem(string id, ActivityKind kind, string title, bool canCancel)
    {
        Id = id;
        Kind = kind;
        Title = title;
        StartedAt = DateTimeOffset.Now;
        this.canCancel = canCancel;
        cancellationSource = canCancel ? new CancellationTokenSource() : null;
        CancelCommand = new RelayCommand(RequestCancel, () => CanCancel);
    }

    public string Id { get; }

    public ActivityKind Kind { get; }

    public string Title { get; }

    public DateTimeOffset StartedAt { get; }

    public DateTimeOffset? CompletedAt { get; internal set; }

    public ActivityState State
    {
        get => state;
        internal set
        {
            if (!SetProperty(ref state, value)) return;
            OnPropertyChanged(nameof(StateText));
            OnPropertyChanged(nameof(CanCancel));
            CancelCommand.NotifyCanExecuteChanged();
        }
    }

    public double? Progress
    {
        get => progress;
        internal set
        {
            if (!SetProperty(ref progress, value is null ? null : Math.Clamp(value.Value, 0, 100))) return;
            OnPropertyChanged(nameof(ProgressText));
        }
    }

    public string Message
    {
        get => message;
        internal set => SetProperty(ref message, value);
    }

    public bool CanCancel
    {
        get => canCancel && State is ActivityState.Pending or ActivityState.Running;
        internal set
        {
            if (!SetProperty(ref canCancel, value)) return;
            CancelCommand.NotifyCanExecuteChanged();
        }
    }

    public string StateText => State switch
    {
        ActivityState.Pending => "等待中",
        ActivityState.Running => "进行中",
        ActivityState.Succeeded => "已完成",
        ActivityState.Failed => "失败",
        ActivityState.Cancelled => "已取消",
        _ => State.ToString()
    };

    public string ProgressText => Progress is { } value ? $"{value:0}%" : StateText;

    public RelayCommand CancelCommand { get; }

    internal CancellationToken Token => cancellationSource?.Token ?? CancellationToken.None;

    private void RequestCancel()
    {
        if (!CanCancel) return;
        Message = "正在取消…";
        cancellationSource?.Cancel();
        CanCancel = false;
    }
}