Files
LanMountainDesktop/LanMountainDesktop.Launcher/Views/UpdateWindow.axaml.cs
lincube 4cb52e56c7 Launcher (#4)
* 激进的更新

* 试试

* fix.可爱的我一直在修CI(

* fix.启动器一定要能够启动

* feat.尝试弄了AOT的启动器。

* fix.修CI,好像是因为Linux那边有个问题,反正修就对了。

* fix.ci难修,为什么liunx跑不起来呢?

* Update build.yml

* Update LanMountainDesktop.csproj

* changed.调整了启动逻辑,优化了更新页面。

* changed.优化了更新体验

* feat.依旧试增量更新这一块,看看velopack

* fix.我们试验性地修复了启动器无法正常启动的问题,原因可能是这个画面没有启动,就GUI没显示。然后还把编译问题修了一下。

* fix.继续修ci,ci怎么天天炸

* changed.velopack,试试rust

* fix.修ci,修融合桌面,修启动器

* fix.GitHub Action工作流怎么天天出问题

* feat.引入velopack,不好,是rust(至少内存很安全了。

* chore: migrate release pipeline to signed filemap and wire rainyun s3

* fix: make optional s3 upload step workflow-parse safe

* fix: make delta pack generation robust for empty diffs and linux paths

* chore: rotate launcher update public key for pdc signing

* fix: restore stable launcher update public key

* fix: sync launcher public key with update signing secret

* fix: normalize PEM line endings in signing key validation

* fix: rotate launcher public key to match ci signing secret

* fix: compare signing keys by SPKI instead of PEM text

* refactor update backend to host-managed PDC pipeline

* fix release workflow env key collisions

* relax publish-pdc precheck to require S3 only

* set GH_TOKEN for PDCC installer step

* ci: add local pdc mock fallback for release publish

* ci: fix pdc mock process log redirection

* ci: fallback pdcc signing key to update private key

* ci: ensure pdcc signing passphrase env is always set

* ci: create pdcc publish root before invoking client

* ci: set pdcc version variable from release version

* ci: decouple pdcc installer version from publish config version

* ci: package pdcc subchannels with generated filemap and changelog

* ci: make local pdc mock diff return empty for fast fallback

* ci: fix pdcc variable mapping and pdc signing prechecks

* Update App.axaml.cs

* ci: wire aws cli credentials for rainyun s3

* ci: pin pdcc client version separately from app version

* ci: harden local pdc mock transport handling

* ci: publish pdcc subchannels in one pass

* ci: add pdcc publish heartbeat and timeout

* ci: fix pdcc publish workdir bootstrap

* feat.Penguin Logistics Online Network Distribution System

* ci: fix plonds s3 probe and signing fallback

* ci: validate signing key and quiet missing baselines

* ci: relax aws checksum mode for rainyun s3

* ci: avoid multipart uploads to rainyun s3

* ci: handle empty plonds baselines safely

* ci.plonds

* Rebuild release pipeline around PLONDS and DDSS

* Fix Windows installer script path in release workflow
2026-04-21 20:59:52 +08:00

124 lines
3.8 KiB
C#

using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
namespace LanMountainDesktop.Launcher.Views;
/// <summary>
/// 更新进度窗口 - 用于 apply-update 命令模式下显示更新/插件升级进度
/// </summary>
public partial class UpdateWindow : Window
{
public UpdateWindow()
{
AvaloniaXamlLoader.Load(this);
InitializeEventHandlers();
}
/// <summary>
/// 初始化事件处理程序
/// </summary>
private void InitializeEventHandlers()
{
var minimizeButton = this.FindControl<Button>("MinimizeButton");
if (minimizeButton != null)
{
minimizeButton.Click += (s, e) =>
{
this.WindowState = WindowState.Minimized;
};
}
}
/// <summary>
/// 更新状态和进度
/// </summary>
public void Report(string stage, string message, int progressPercent = -1)
{
Dispatcher.UIThread.Post(() =>
{
var statusText = this.FindControl<TextBlock>("StatusText");
var progressIndicator = this.FindControl<ProgressBar>("ProgressIndicator");
var percentText = this.FindControl<TextBlock>("PercentText");
if (statusText is null || progressIndicator is null || percentText is null)
{
Console.Error.WriteLine($"[UpdateWindow] Controls not found in Report: StatusText={statusText != null}, ProgressIndicator={progressIndicator != null}, PercentText={percentText != null}");
return;
}
statusText.Text = message;
if (progressPercent >= 0)
{
progressIndicator.IsIndeterminate = false;
progressIndicator.Value = progressPercent;
percentText.Text = $"{progressPercent}%";
}
else
{
progressIndicator.IsIndeterminate = true;
percentText.Text = "";
}
});
}
/// <summary>
/// 显示更新完成状态
/// </summary>
public void ReportComplete(bool success, string? errorMessage = null)
{
Dispatcher.UIThread.Post(() =>
{
var statusText = this.FindControl<TextBlock>("StatusText");
var progressIndicator = this.FindControl<ProgressBar>("ProgressIndicator");
var percentText = this.FindControl<TextBlock>("PercentText");
var titleText = this.FindControl<TextBlock>("TitleText");
if (statusText is null || progressIndicator is null || percentText is null || titleText is null)
{
Console.Error.WriteLine($"[UpdateWindow] Controls not found in ReportComplete");
return;
}
progressIndicator.IsIndeterminate = false;
progressIndicator.Value = 100;
percentText.Text = "100%";
if (success)
{
statusText.Text = "更新完成";
}
else
{
titleText.Text = "更新失败";
statusText.Text = errorMessage ?? "更新过程中发生错误";
}
});
}
/// <summary>
/// 设置调试模式
/// </summary>
public void SetDebugMode(bool isDebugMode)
{
Dispatcher.UIThread.Post(() =>
{
var statusText = this.FindControl<TextBlock>("StatusText");
var titleText = this.FindControl<TextBlock>("TitleText");
if (statusText is null || titleText is null)
{
Console.Error.WriteLine($"[UpdateWindow] Controls not found in SetDebugMode");
return;
}
if (isDebugMode)
{
titleText.Text = "[调试模式] 更新页面";
statusText.Text = "预览更新进度界面";
}
});
}
}