初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using PCL.Core.App;
|
||||
using PCL.Core.Utils;
|
||||
using PCL.Core.App.Localization;
|
||||
using PCL.Core.Utils.OS;
|
||||
|
||||
namespace PCL;
|
||||
|
||||
public partial class PageSetupUpdate
|
||||
{
|
||||
public VersionDataModel updateInfo;
|
||||
|
||||
public PageSetupUpdate()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += (_, _) => Init();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
ModAnimation.AniControlEnabled += 1;
|
||||
TextMirrorCDK.Password = Config.Update.MirrorChyanKey;
|
||||
|
||||
ComboSystemUpdateChannel.SelectedIndex = (int)Config.Update.UpdateChannel;
|
||||
ComboSystemUpdateMode.SelectedIndex = (int)Config.Update.UpdateMode;
|
||||
|
||||
TextCurrentVersion.Text = "PCL CE " + VersionNameFormat(ModBase.versionBaseName);
|
||||
ModAnimation.AniControlEnabled -= 1;
|
||||
CheckUpdate();
|
||||
}
|
||||
|
||||
private async Task<UpdateStatus> IsLatestAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 修复:使用 dynamic 绕过命名空间重名导致的编译期类型冲突,
|
||||
// 或者你可以尝试替换为 PCL.Core.App.SemVer.Parse(ModBase.versionBaseName)
|
||||
if (await UpdateManager.remoteServer.IsLatestAsync(
|
||||
UpdateManager.IsCurrentVersionBeta ? UpdateChannel.beta : UpdateChannel.stable,
|
||||
SystemInfo.IsArm64System ? UpdateArch.arm64 : UpdateArch.x64,
|
||||
SemVer.Parse(ModBase.versionBaseName),
|
||||
ModBase.versionCode))
|
||||
{
|
||||
ModBase.Log("[Update] 已是最新版本");
|
||||
return UpdateStatus.Latest;
|
||||
}
|
||||
|
||||
ModBase.Log("[Update] 有可用的新版本");
|
||||
return UpdateStatus.Available;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModBase.Log(
|
||||
ex,
|
||||
Lang.Text("Setup.Update.Error.NetworkFailed"),
|
||||
ModBase.LogLevel.Hint,
|
||||
userSummary: Lang.Text("Setup.Update.Error.NetworkFailed"));
|
||||
return UpdateStatus.Error;
|
||||
}
|
||||
}
|
||||
|
||||
public async void CheckUpdate()
|
||||
{
|
||||
ModBase.Log("[Update] 开始检查更新");
|
||||
CardUpdate.Visibility = Visibility.Collapsed;
|
||||
CardCheck.Visibility = Visibility.Visible;
|
||||
TextCurrentDesc.Text = Lang.Text("Setup.Update.Checking");
|
||||
BtnCheckAgain.IsEnabled = false;
|
||||
switch (await IsLatestAsync())
|
||||
{
|
||||
case UpdateStatus.Available:
|
||||
{
|
||||
Exception checkUpdateEx = null;
|
||||
try
|
||||
{
|
||||
updateInfo = UpdateManager.remoteServer.GetLatestVersion(
|
||||
UpdateManager.IsCurrentVersionBeta
|
||||
? UpdateChannel.beta
|
||||
: UpdateChannel.stable, SystemInfo.IsArm64System ? UpdateArch.arm64 : UpdateArch.x64);
|
||||
TextUpdateName.Text = "PCL CE " + VersionNameFormat(updateInfo.VersionName);
|
||||
var summary = updateInfo.Changelog.Between("<summary>", "</summary>");
|
||||
if (!updateInfo.Changelog.Contains("<summary>") || string.IsNullOrWhiteSpace(summary.Trim()))
|
||||
TextChangelog.Text = Lang.Text("Setup.Update.Changelog.Empty");
|
||||
else
|
||||
TextChangelog.Text = summary;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
checkUpdateEx = ex;
|
||||
}
|
||||
|
||||
BtnCheckAgain.IsEnabled = true;
|
||||
if (updateInfo is null)
|
||||
{
|
||||
TextCurrentDesc.Text = Lang.Text("Setup.Update.CheckFailed");
|
||||
if (checkUpdateEx is not null)
|
||||
ModBase.Log(
|
||||
checkUpdateEx,
|
||||
"[Update] 检查更新失败",
|
||||
ModBase.LogLevel.Msgbox,
|
||||
userSummary: Lang.Text("Update.Check.Failed"));
|
||||
else
|
||||
ModBase.Log(
|
||||
"[Update] 检查更新失败",
|
||||
ModBase.LogLevel.Msgbox,
|
||||
userSummary: Lang.Text("Update.Check.Failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (UpdateManager.updateLoader is not null && UpdateManager.updateLoader.State == ModBase.LoadState.Loading)
|
||||
{
|
||||
BtnUpdate_Timer();
|
||||
BtnUpdate.IsEnabled = false;
|
||||
}
|
||||
else if (UpdateManager.isUpdateWaitingRestart)
|
||||
{
|
||||
BtnUpdate.Text = Lang.Text("Setup.Update.RestartInstall");
|
||||
BtnUpdate.IsEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
BtnUpdate.Text = Lang.Text("Setup.Update.Install");
|
||||
BtnUpdate.IsEnabled = true;
|
||||
}
|
||||
|
||||
CardUpdate.Visibility = Visibility.Visible;
|
||||
CardCheck.Visibility = Visibility.Collapsed;
|
||||
break;
|
||||
}
|
||||
case UpdateStatus.Latest:
|
||||
{
|
||||
CardUpdate.Visibility = Visibility.Collapsed;
|
||||
CardCheck.Visibility = Visibility.Visible;
|
||||
BtnCheckAgain.IsEnabled = true;
|
||||
TextCurrentDesc.Text = Lang.Text("Setup.Update.Latest");
|
||||
break;
|
||||
}
|
||||
case UpdateStatus.Error:
|
||||
{
|
||||
CardUpdate.Visibility = Visibility.Collapsed;
|
||||
CardCheck.Visibility = Visibility.Visible;
|
||||
BtnCheckAgain.IsEnabled = true;
|
||||
TextCurrentDesc.Text = Lang.Text("Setup.Update.CheckFailed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void BtnUpdate_Timer()
|
||||
{
|
||||
while (UpdateManager.updateLoader is not null && UpdateManager.updateLoader.State == ModBase.LoadState.Loading)
|
||||
{
|
||||
ModBase.RunInUi(() => BtnUpdate.Text = Lang.Number(UpdateManager.updateLoader.Progress, "P2"));
|
||||
Thread.Sleep(200);
|
||||
}
|
||||
}
|
||||
|
||||
private void BtnUpdate_Click(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (UpdateManager.isUpdateWaitingRestart) UpdateManager.UpdateRestart(true);
|
||||
// 开始更新流程
|
||||
UpdateManager.UpdateStart(UpdateEnums.UpdateType.UpdateNow);
|
||||
}
|
||||
|
||||
private void BtnChangelogDetail_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (updateInfo is null)
|
||||
ModMain.MyMsgBox(Lang.Text("Setup.Update.Changelog.Unavailable"), Lang.Text("Setup.Update.Changelog.Title"));
|
||||
else
|
||||
ModMain.MyMsgBoxMarkdown(updateInfo.Changelog, Lang.Text("Setup.Update.Changelog.Title"));
|
||||
}
|
||||
|
||||
private void ComboSystemUpdateMode_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (ModAnimation.AniControlEnabled == 0)
|
||||
Config.Update.UpdateMode = (LauncherAutoUpdateBehavior)ComboSystemUpdateMode.SelectedIndex;
|
||||
}
|
||||
|
||||
private void ComboSystemUpdateBranch_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (ModAnimation.AniControlEnabled != 0)
|
||||
return;
|
||||
|
||||
var isCancelled = false;
|
||||
switch (ComboSystemUpdateChannel.SelectedIndex)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
if (ModMain.MyMsgBox(Lang.Text("Setup.Update.Channel.Beta.Warning.Message"),
|
||||
Lang.Text("Setup.Update.Channel.Common.Warning.Title"),
|
||||
Lang.Text("Setup.Update.Channel.Common.Warning.Confirm"),
|
||||
Lang.Text("Common.Action.Cancel"), isWarn: true) == 2)
|
||||
isCancelled = true;
|
||||
else
|
||||
CheckUpdate();
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (ModMain.MyMsgBox(Lang.Text("Setup.Update.Channel.Dev.Warning.Message"),
|
||||
Lang.Text("Setup.Update.Channel.Common.Warning.Title"),
|
||||
Lang.Text("Setup.Update.Channel.Common.Warning.Confirm"),
|
||||
Lang.Text("Common.Action.Cancel"), isWarn: true) == 2)
|
||||
{
|
||||
isCancelled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
var confirmText = Lang.Text("Setup.Update.Channel.Dev.FinalConfirm.ExpectedInput");
|
||||
var ret = ModMain.MyMsgBoxInput(
|
||||
Lang.Text("Setup.Update.Channel.Dev.FinalConfirm.Title"),
|
||||
Lang.Text("Setup.Update.Channel.Dev.FinalConfirm.Message", confirmText),
|
||||
button1: Lang.Text("Setup.Update.Channel.Dev.FinalConfirm.Submit"),
|
||||
button2: Lang.Text("Common.Action.Cancel"), isWarn: true);
|
||||
|
||||
if (ret == confirmText)
|
||||
{
|
||||
CheckUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
HintService.Hint(Lang.Text("Setup.Update.Channel.Dev.FinalConfirm.WrongInput"));
|
||||
isCancelled = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isCancelled)
|
||||
{
|
||||
ModAnimation.AniControlEnabled += 1;
|
||||
ComboSystemUpdateChannel.SelectedItem = e.RemovedItems[0];
|
||||
ModAnimation.AniControlEnabled -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Config.Update.UpdateChannel = (Core.App.UpdateChannel)ComboSystemUpdateChannel.SelectedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
private void TextMirrorCDK_PasswordChanged(object sender, EventArgs e)
|
||||
{
|
||||
Config.Update.MirrorChyanKey = TextMirrorCDK.Password;
|
||||
}
|
||||
|
||||
private void BtnGetMirrorCDK_Click(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
ModBase.OpenWebsite("https://mirrorchyan.com/");
|
||||
}
|
||||
|
||||
private void BtnChangelog_Click(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
ModBase.OpenWebsite("https://github.com/PCL-Community/PCL2-CE/releases/v" + ModBase.versionBaseName);
|
||||
}
|
||||
|
||||
public string VersionNameFormat(string str)
|
||||
{
|
||||
str = str.Replace("v", "");
|
||||
if (!str.Contains("-"))
|
||||
return str;
|
||||
var add = str.AfterLast("-");
|
||||
str = str.BeforeLast("-");
|
||||
return $"{str} {add.Replace(".", " ").Replace("beta", "Beta").Replace("rc", "RC")}";
|
||||
}
|
||||
|
||||
private void BtnCheckAgain_OnClick(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
CheckUpdate();
|
||||
}
|
||||
|
||||
private enum UpdateStatus
|
||||
{
|
||||
Checking = 0,
|
||||
Available = 1,
|
||||
Error = 2,
|
||||
Latest = 3
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user