diff --git a/LANCommander.Launcher.Avalonia/ViewModels/DownloadQueueViewModel.cs b/LANCommander.Launcher.Avalonia/ViewModels/DownloadQueueViewModel.cs index 1cde4fca..0ee4b4f9 100644 --- a/LANCommander.Launcher.Avalonia/ViewModels/DownloadQueueViewModel.cs +++ b/LANCommander.Launcher.Avalonia/ViewModels/DownloadQueueViewModel.cs @@ -11,6 +11,7 @@ using LANCommander.Launcher.Avalonia.Services; using LANCommander.Launcher.Models; using LANCommander.Launcher.Services; using LANCommander.SDK.Enums; +using LANCommander.SDK.Models; using LANCommander.SDK.Services; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -92,6 +93,7 @@ public partial class DownloadQueueViewModel : ViewModelBase _installService.OnQueueChanged += OnQueueChanged; _installService.OnProgress += OnProgress; + _installService.OnTaskProgressUpdate += OnTaskProgressUpdate; _installService.OnInstallComplete += OnInstallComplete; _installService.OnInstallFail += OnInstallFail; @@ -104,6 +106,37 @@ public partial class DownloadQueueViewModel : ViewModelBase return Task.CompletedTask; } + private Task OnTaskProgressUpdate(InstallTaskProgress taskProgress) + { + Dispatcher.UIThread.Post(() => + { + var item = QueueItems.FirstOrDefault(i => i.Id == taskProgress.QueueItemId); + if (item == null) + return; + + var task = item.Tasks.FirstOrDefault(t => t.Id == taskProgress.TaskId); + if (task == null) + return; + + task.Status = taskProgress.TaskStatus; + task.Progress = taskProgress.Progress; + task.BytesTransferred = taskProgress.BytesTransferred; + task.TotalBytes = taskProgress.TotalBytes; + task.TransferSpeed = taskProgress.TransferSpeed; + task.ErrorMessage = taskProgress.ErrorMessage; + + item.CurrentTask = task; + + // Update current status from task + if (item == CurrentItem) + { + CurrentStatus = taskProgress.TaskTitle; + } + }); + + return Task.CompletedTask; + } + private Task OnProgress(InstallProgress progress) { _taskbarProgressService.SetProgress(progress.Progress); @@ -364,9 +397,18 @@ public partial class InstallQueueItemViewModel : ViewModelBase [ObservableProperty] private bool _isUpdate; - public bool IsActive => Status != InstallStatus.Queued && - Status != InstallStatus.Complete && - Status != InstallStatus.Failed && + [ObservableProperty] + private ObservableCollection _tasks = new(); + + [ObservableProperty] + private InstallTaskItemViewModel? _currentTask; + + [ObservableProperty] + private bool _hasTasks; + + public bool IsActive => Status != InstallStatus.Queued && + Status != InstallStatus.Complete && + Status != InstallStatus.Failed && Status != InstallStatus.Canceled; public bool IsQueued => Status == InstallStatus.Queued; @@ -390,6 +432,15 @@ public partial class InstallQueueItemViewModel : ViewModelBase CoverId = item.CoverId; IconId = item.IconId; IsUpdate = item.IsUpdate; + + if (item.Tasks != null && item.Tasks.Count > 0) + { + foreach (var taskDef in item.Tasks.OrderBy(t => t.Order)) + { + Tasks.Add(new InstallTaskItemViewModel(taskDef)); + } + HasTasks = true; + } } private static string FormatBytes(long bytes) diff --git a/LANCommander.Launcher.Avalonia/ViewModels/InstallTaskItemViewModel.cs b/LANCommander.Launcher.Avalonia/ViewModels/InstallTaskItemViewModel.cs new file mode 100644 index 00000000..6bfd7641 --- /dev/null +++ b/LANCommander.Launcher.Avalonia/ViewModels/InstallTaskItemViewModel.cs @@ -0,0 +1,59 @@ +using System; +using CommunityToolkit.Mvvm.ComponentModel; +using LANCommander.SDK.Enums; +using LANCommander.SDK.Models; + +namespace LANCommander.Launcher.Avalonia.ViewModels; + +public partial class InstallTaskItemViewModel : ViewModelBase +{ + [ObservableProperty] + private Guid _id; + + [ObservableProperty] + private string _title = string.Empty; + + [ObservableProperty] + private InstallTaskType _type; + + [ObservableProperty] + private InstallTaskStatus _status = InstallTaskStatus.Queued; + + [ObservableProperty] + private float _progress; + + [ObservableProperty] + private bool _reportsProgress; + + [ObservableProperty] + private bool _isCritical; + + [ObservableProperty] + private string? _errorMessage; + + [ObservableProperty] + private long _bytesTransferred; + + [ObservableProperty] + private long _totalBytes; + + [ObservableProperty] + private long _transferSpeed; + + public bool IsCompleted => Status == InstallTaskStatus.Completed; + public bool IsRunning => Status == InstallTaskStatus.Running; + public bool IsFailed => Status == InstallTaskStatus.Failed; + public bool IsQueued => Status == InstallTaskStatus.Queued; + public bool IsSkipped => Status == InstallTaskStatus.Skipped; + + public InstallTaskItemViewModel() { } + + public InstallTaskItemViewModel(InstallTaskDefinition taskDef) + { + Id = taskDef.Id; + Title = taskDef.Title; + Type = taskDef.Type; + ReportsProgress = taskDef.ReportsProgress; + IsCritical = taskDef.IsCritical; + } +} diff --git a/LANCommander.Launcher.Avalonia/Views/DownloadQueuePageView.axaml b/LANCommander.Launcher.Avalonia/Views/DownloadQueuePageView.axaml index 68c7a97b..44bc4c04 100644 --- a/LANCommander.Launcher.Avalonia/Views/DownloadQueuePageView.axaml +++ b/LANCommander.Launcher.Avalonia/Views/DownloadQueuePageView.axaml @@ -114,6 +114,51 @@ IsVisible="{Binding TimeRemainingText, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" /> + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LANCommander.Launcher.Avalonia/Views/DownloadQueueView.axaml b/LANCommander.Launcher.Avalonia/Views/DownloadQueueView.axaml index 70a26473..21b4779d 100644 --- a/LANCommander.Launcher.Avalonia/Views/DownloadQueueView.axaml +++ b/LANCommander.Launcher.Avalonia/Views/DownloadQueueView.axaml @@ -71,7 +71,7 @@ - +