using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; using Avalonia.Media; using Avalonia.Threading; using LanMountainDesktop.Launcher.Services; using LanMountainDesktop.Shared.Contracts.Launcher; using System.Collections.ObjectModel; using System.ComponentModel; namespace LanMountainDesktop.Launcher.Views; /// /// 加载详情窗口 - 显示详细的加载状态和进度 /// public partial class LoadingDetailsWindow : Window { private readonly ObservableCollection _items = new(); private readonly DispatcherTimer _updateTimer; private DateTimeOffset _startTime; public LoadingDetailsWindow() { AvaloniaXamlLoader.Load(this); var itemsList = this.FindControl("LoadingItemsList"); if (itemsList != null) { itemsList.ItemsSource = _items; } _updateTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(100) }; _updateTimer.Tick += OnUpdateTimerTick; _startTime = DateTimeOffset.UtcNow; } /// /// 窗口加载完成 /// protected override void OnLoaded(RoutedEventArgs e) { base.OnLoaded(e); _updateTimer.Start(); } /// /// 窗口关闭 /// protected override void OnClosing(WindowClosingEventArgs e) { _updateTimer.Stop(); base.OnClosing(e); } /// /// 更新加载状? /// public void UpdateLoadingState(LoadingStateMessage state) { Dispatcher.UIThread.Post(() => { try { // 更新标题和副标题 UpdateHeader(state); // 更新整体进度 UpdateOverallProgress(state); UpdateCurrentItem(state); // 更新列表 UpdateItemsList(state); // 更新错误信息 UpdateErrorPanel(state); // 更新完成计数 UpdateCompletedCount(state); } catch (Exception ex) { Console.Error.WriteLine($"[LoadingDetailsWindow] Error updating state: {ex.Message}"); } }); } /// /// 更新标题 /// private void UpdateHeader(LoadingStateMessage state) { var subtitleText = this.FindControl("SubtitleText"); if (subtitleText != null) { subtitleText.Text = GetStageDescription(state.Stage); } } /// /// 更新整体进度 /// private void UpdateOverallProgress(LoadingStateMessage state) { var progressBar = this.FindControl("OverallProgressBar"); var percentText = this.FindControl("PercentText"); if (progressBar != null) { progressBar.Value = state.OverallProgressPercent; } if (percentText != null) { percentText.Text = $"{state.OverallProgressPercent}%"; } } /// /// 更新当前活动? /// private void UpdateCurrentItem(LoadingStateMessage state) { var currentItem = state.ActiveItems.FirstOrDefault(); if (currentItem == null) return; var nameText = this.FindControl("CurrentItemName"); var descText = this.FindControl("CurrentItemDescription"); var progressBar = this.FindControl("CurrentItemProgress"); var iconText = this.FindControl("CurrentItemIcon"); if (nameText != null) { nameText.Text = currentItem.Name; } if (descText != null) { descText.Text = currentItem.Message ?? GetItemDescription(currentItem); } if (progressBar != null) { progressBar.Value = currentItem.ProgressPercent; } if (iconText != null) { iconText.Text = GetItemIcon(currentItem.Type); } } /// /// 更新列表 /// private void UpdateItemsList(LoadingStateMessage state) { foreach (var item in state.ActiveItems) { var existing = _items.FirstOrDefault(i => i.Id == item.Id); if (existing != null) { existing.UpdateFrom(item); } else { _items.Add(new LoadingItemViewModel(item)); } } // 移除已完成的项(保留最近完成的5个) var completedItems = _items.Where(i => i.State == LoadingState.Completed).ToList(); if (completedItems.Count > 5) { var itemsToRemove = completedItems.OrderBy(i => i.CompletedTime).Take(completedItems.Count - 5); foreach (var item in itemsToRemove) { _items.Remove(item); } } // 按状态排序:进行?-> 等待?-> 已完?-> 失败 var sortedItems = _items.OrderBy(i => GetStatePriority(i.State)).ToList(); _items.Clear(); foreach (var item in sortedItems) { _items.Add(item); } } /// /// 更新错误面板 /// private void UpdateErrorPanel(LoadingStateMessage state) { var errorPanel = this.FindControl("ErrorPanel"); var errorText = this.FindControl("ErrorText"); if (errorPanel != null) { errorPanel.IsVisible = state.HasErrors; } if (errorText != null && state.ErrorMessages?.Any() == true) { errorText.Text = string.Join("\n", state.ErrorMessages.Take(3)); } } /// /// 更新完成计数 /// private void UpdateCompletedCount(LoadingStateMessage state) { var countText = this.FindControl("CompletedCountText"); if (countText != null) { countText.Text = state.CompletedCount.ToString(); } } /// /// 定时更新 /// private void OnUpdateTimerTick(object? sender, EventArgs e) { // 可以在这里添加时间显示等实时更新 } /// /// 获取阶段描述 /// private static string GetStageDescription(StartupStage stage) => stage switch { StartupStage.Initializing => "ڳʼϵͳ...", StartupStage.LoadingSettings => "ڼ...", StartupStage.LoadingPlugins => "ڼز...", StartupStage.InitializingUI => "ڳʼ...", StartupStage.ShellInitialized => "ѳʼ", StartupStage.DesktopVisible => "Ѿɼ", StartupStage.ActivationRedirected => "Ѽʵ", StartupStage.ActivationFailed => "ʵʧ", StartupStage.Ready => "", _ => "ڼ..." }; /// /// 获取项描? /// private static string GetItemDescription(LoadingItem item) { if (!string.IsNullOrEmpty(item.Description)) return item.Description; return item.Type switch { LoadingItemType.Plugin => "正在加载插件...", LoadingItemType.Component => "正在加载组件...", LoadingItemType.Resource => "正在加载资源...", LoadingItemType.Data => "正在加载数据...", LoadingItemType.Network => "正在下载...", _ => "正在处理..." }; } /// /// 获取项图? /// private static string GetItemIcon(LoadingItemType type) => type switch { LoadingItemType.Plugin => "\uE768", LoadingItemType.Component => "\uE7C4", LoadingItemType.Resource => "\uE7C5", LoadingItemType.Data => "\uE7C6", LoadingItemType.Network => "\uE774", LoadingItemType.Settings => "\uE713", LoadingItemType.System => "\uE7C7", _ => "\uE768" }; /// /// 获取状态优先级 /// private static int GetStatePriority(LoadingState state) => state switch { LoadingState.InProgress => 0, LoadingState.Pending => 1, LoadingState.Completed => 2, LoadingState.Failed => 3, LoadingState.Timeout => 4, LoadingState.Cancelled => 5, _ => 6 }; } /// /// 加载项视图模?/// public class LoadingItemViewModel : INotifyPropertyChanged { public string Id { get; } public string Name { get; private set; } public LoadingItemType Type { get; private set; } public LoadingState State { get; private set; } public int ProgressPercent { get; private set; } public DateTimeOffset? CompletedTime { get; private set; } public string StatusIcon => GetStatusIcon(State); public IBrush StatusColor => GetStatusColor(State); public string ProgressText => State == LoadingState.Completed ? "完成" : $"{ProgressPercent}%"; public string TypeLabel => GetTypeLabel(Type); public IBrush TypeBackground => GetTypeBackground(Type); public IBrush TypeForeground => GetTypeForeground(Type); public double Opacity => State == LoadingState.Completed ? 0.6 : 1.0; public event PropertyChangedEventHandler? PropertyChanged; public LoadingItemViewModel(LoadingItem item) { Id = item.Id; UpdateFrom(item); } public void UpdateFrom(LoadingItem item) { Name = item.Name; Type = item.Type; State = item.State; ProgressPercent = item.ProgressPercent; if (State == LoadingState.Completed && !CompletedTime.HasValue) { CompletedTime = DateTimeOffset.UtcNow; } PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(string.Empty)); } private static string GetStatusIcon(LoadingState state) => state switch { LoadingState.Pending => "\uE7C3", LoadingState.InProgress => "\uE768", LoadingState.Completed => "\uE73E", LoadingState.Failed => "\uE783", LoadingState.Timeout => "\uE71A", LoadingState.Cancelled => "\uE711", _ => "\uE7C3" }; private static IBrush GetStatusColor(LoadingState state) => state switch { LoadingState.Pending => new SolidColorBrush(Colors.Gray), LoadingState.InProgress => new SolidColorBrush(Colors.DodgerBlue), LoadingState.Completed => new SolidColorBrush(Colors.Green), LoadingState.Failed => new SolidColorBrush(Colors.Red), LoadingState.Timeout => new SolidColorBrush(Colors.Orange), LoadingState.Cancelled => new SolidColorBrush(Colors.Gray), _ => new SolidColorBrush(Colors.Gray) }; private static string GetTypeLabel(LoadingItemType type) => type switch { LoadingItemType.Plugin => "插件", LoadingItemType.Component => "组件", LoadingItemType.Resource => "资源", LoadingItemType.Data => "数据", LoadingItemType.Network => "网络", LoadingItemType.Settings => "设置", LoadingItemType.System => "系统", _ => "其他" }; private static IBrush GetTypeBackground(LoadingItemType type) => type switch { LoadingItemType.Plugin => new SolidColorBrush(Color.Parse("#E3F2FD")), LoadingItemType.Component => new SolidColorBrush(Color.Parse("#F3E5F5")), LoadingItemType.Resource => new SolidColorBrush(Color.Parse("#E8F5E9")), LoadingItemType.Data => new SolidColorBrush(Color.Parse("#FFF3E0")), LoadingItemType.Network => new SolidColorBrush(Color.Parse("#E0F7FA")), _ => new SolidColorBrush(Color.Parse("#F5F5F5")) }; private static IBrush GetTypeForeground(LoadingItemType type) => type switch { LoadingItemType.Plugin => new SolidColorBrush(Color.Parse("#1976D2")), LoadingItemType.Component => new SolidColorBrush(Color.Parse("#7B1FA2")), LoadingItemType.Resource => new SolidColorBrush(Color.Parse("#388E3C")), LoadingItemType.Data => new SolidColorBrush(Color.Parse("#F57C00")), LoadingItemType.Network => new SolidColorBrush(Color.Parse("#0097A7")), _ => new SolidColorBrush(Color.Parse("#616161")) }; }