diff --git a/Ink Canvas/Helpers/AutoUpdateHelper.cs b/Ink Canvas/Helpers/AutoUpdateHelper.cs index 33e31bd2..92fdcca8 100644 --- a/Ink Canvas/Helpers/AutoUpdateHelper.cs +++ b/Ink Canvas/Helpers/AutoUpdateHelper.cs @@ -27,6 +27,87 @@ namespace Ink_Canvas.Helpers private static readonly string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate"); private static string statusFilePath; + public static bool IsX64UpdatePackageSelected() + { + try + { + return MainWindow.Settings?.Startup?.UpdatePackageArchitecture == UpdatePackageArchitecture.X64; + } + catch + { + return false; + } + } + + private static string NormalizeVersionForUpdate(string version) + { + if (string.IsNullOrWhiteSpace(version)) return version; + return version.Trim().TrimStart('v', 'V'); + } + + public static string AppendX64SuffixBeforeZipExtension(string url) + { + if (string.IsNullOrEmpty(url) || !IsX64UpdatePackageSelected()) return url; + int query = url.IndexOf('?'); + string pathPart = query >= 0 ? url.Substring(0, query) : url; + string qs = query >= 0 ? url.Substring(query) : ""; + const string ext = ".zip"; + int idx = pathPart.LastIndexOf(ext, StringComparison.OrdinalIgnoreCase); + if (idx < 0) return url; + var basePart = pathPart.Substring(0, idx); + if (basePart.EndsWith("-x64", StringComparison.OrdinalIgnoreCase)) return url; + return basePart + "-x64" + ext + qs; + } + + public static string GetUpdateZipFileName(string version) + { + var v = NormalizeVersionForUpdate(version); + return IsX64UpdatePackageSelected() + ? $"InkCanvasForClass.CE.{v}-x64.zip" + : $"InkCanvasForClass.CE.{v}.zip"; + } + + public static string GetUpdateDownloadStatusFilePath(string version) + { + var v = NormalizeVersionForUpdate(version); + string name = IsX64UpdatePackageSelected() + ? $"DownloadV{v}_x64Status.txt" + : $"DownloadV{v}Status.txt"; + return Path.Combine(updatesFolderPath, name); + } + + public static string GetLocalUpdateZipFilePath(string version) + { + return Path.Combine(updatesFolderPath, GetUpdateZipFileName(version)); + } + + private static string PickBrowserDownloadUrlFromAssets(JToken assets) + { + if (assets == null || !assets.Any()) return null; + bool wantX64 = IsX64UpdatePackageSelected(); + string anyZip = null; + string x64Zip = null; + string nonX64Zip = null; + foreach (JToken a in assets) + { + string name = a["name"]?.ToString(); + string url = a["browser_download_url"]?.ToString(); + if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(url)) continue; + if (!name.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)) continue; + if (anyZip == null) anyZip = url; + if (name.EndsWith("-x64.zip", StringComparison.OrdinalIgnoreCase)) + { + if (x64Zip == null) x64Zip = url; + } + else + { + if (nonX64Zip == null) nonX64Zip = url; + } + } + if (wantX64) + return x64Zip ?? anyZip; + return nonX64Zip ?? anyZip; + } // 线路组结构体(包含版本、下载、日志地址) public class UpdateLineGroup @@ -317,6 +398,7 @@ namespace Ink_Canvas.Helpers if (!string.IsNullOrEmpty(group.DownloadUrlFormat)) { testUrl = group.DownloadUrlFormat.Replace("{0}", "test"); + testUrl = AppendX64SuffixBeforeZipExtension(testUrl); } } catch @@ -608,7 +690,7 @@ namespace Ink_Canvas.Helpers if (version == targetVersion || version == $"v{targetVersion}" || version == $"V{targetVersion}") { string releaseNotes = release["body"]?.ToString(); - string downloadUrl = release["assets"]?.First?["browser_download_url"]?.ToString(); + string downloadUrl = PickBrowserDownloadUrlFromAssets(release["assets"]); // 解析发布时间 DateTime? releaseTime = null; @@ -649,7 +731,7 @@ namespace Ink_Canvas.Helpers var latestRelease = releases[0]; string version = latestRelease["tag_name"]?.ToString(); string releaseNotes = latestRelease["body"]?.ToString(); - string downloadUrl = latestRelease["assets"]?.First?["browser_download_url"]?.ToString(); + string downloadUrl = PickBrowserDownloadUrlFromAssets(latestRelease["assets"]); DateTime? releaseTime = null; if (latestRelease["published_at"] != null && DateTime.TryParse(latestRelease["published_at"].ToString(), out DateTime parsedTime)) @@ -675,7 +757,7 @@ namespace Ink_Canvas.Helpers var json = JObject.Parse(response); string version = json["tag_name"]?.ToString(); string releaseNotes = json["body"]?.ToString(); - string downloadUrl = json["assets"]?.First?["browser_download_url"]?.ToString(); + string downloadUrl = PickBrowserDownloadUrlFromAssets(json["assets"]); DateTime? releaseTime = null; if (json["published_at"] != null && DateTime.TryParse(json["published_at"].ToString(), out DateTime parsedTime)) @@ -865,7 +947,8 @@ namespace Ink_Canvas.Helpers { try { - statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{version}Status.txt"); + version = NormalizeVersionForUpdate(version); + statusFilePath = GetUpdateDownloadStatusFilePath(version); if (File.Exists(statusFilePath) && File.ReadAllText(statusFilePath).Trim().ToLower() == "true") { @@ -881,7 +964,7 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile($"AutoUpdate | 创建更新目录: {updatesFolderPath}"); } - string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip"); + string zipFilePath = GetLocalUpdateZipFilePath(version); LogHelper.WriteLogToFile($"AutoUpdate | 目标文件路径: {zipFilePath}"); SaveDownloadStatus(false); @@ -899,6 +982,7 @@ namespace Ink_Canvas.Helpers foreach (var group in groups) { string url = string.Format(group.DownloadUrlFormat, version); + url = AppendX64SuffixBeforeZipExtension(url); // 智教联盟需要先获取真实下载地址 if (group.GroupName == "智教联盟") { @@ -2170,7 +2254,7 @@ namespace Ink_Canvas.Helpers { string version = item["tag_name"]?.ToString(); string releaseNotes = item["body"]?.ToString(); - string downloadUrl = item["assets"]?.First?["browser_download_url"]?.ToString(); + string downloadUrl = PickBrowserDownloadUrlFromAssets(item["assets"]); if (!string.IsNullOrEmpty(version) && !string.IsNullOrEmpty(downloadUrl)) result.Add((version, downloadUrl, releaseNotes)); } diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index dec5c180..c441956c 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -1863,8 +1863,7 @@ namespace Ink_Canvas if (AvailableLatestVersion != null && Settings.Startup.IsAutoUpdate) { // 检查更新文件是否已下载 - string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate"); - string statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{AvailableLatestVersion}Status.txt"); + string statusFilePath = AutoUpdateHelper.GetUpdateDownloadStatusFilePath(AvailableLatestVersion); if (File.Exists(statusFilePath) && File.ReadAllText(statusFilePath).Trim().ToLower() == "true") { diff --git a/Ink Canvas/MainWindow_cs/MW_Timer.cs b/Ink Canvas/MainWindow_cs/MW_Timer.cs index f6ad197d..651e8208 100644 --- a/Ink Canvas/MainWindow_cs/MW_Timer.cs +++ b/Ink Canvas/MainWindow_cs/MW_Timer.cs @@ -1147,8 +1147,7 @@ namespace Ink_Canvas } // 检查更新文件是否已下载 - string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate"); - string statusFilePath = Path.Combine(updatesFolderPath, $"DownloadV{AvailableLatestVersion}Status.txt"); + string statusFilePath = AutoUpdateHelper.GetUpdateDownloadStatusFilePath(AvailableLatestVersion); if (!File.Exists(statusFilePath) || File.ReadAllText(statusFilePath).Trim().ToLower() != "true") { diff --git a/Ink Canvas/Resources/Settings.cs b/Ink Canvas/Resources/Settings.cs index e72468d9..e4023769 100644 --- a/Ink Canvas/Resources/Settings.cs +++ b/Ink Canvas/Resources/Settings.cs @@ -188,6 +188,15 @@ namespace Ink_Canvas Beta } + /// 自动更新要下载的安装包架构(与当前运行进程的位数无关)。默认 32 位包;64 位包对应发布物 ZIP 文件名在 .zip 前增加 -x64。 + public enum UpdatePackageArchitecture + { + /// 32 位包,例如 InkCanvasForClass.CE.1.7.0.0.zip + X86 = 0, + /// 64 位包,例如 InkCanvasForClass.CE.1.7.0.0-x64.zip + X64 = 1 + } + /// /// 遥测上传等级 /// @@ -219,6 +228,8 @@ namespace Ink_Canvas public string AutoUpdateWithSilenceEndTime { get; set; } = "22:00"; [JsonProperty("updateChannel")] public UpdateChannel UpdateChannel { get; set; } = UpdateChannel.Release; + [JsonProperty("updatePackageArchitecture")] + public UpdatePackageArchitecture UpdatePackageArchitecture { get; set; } = UpdatePackageArchitecture.X86; [JsonProperty("skippedVersion")] public string SkippedVersion { get; set; } = ""; [JsonProperty("autoUpdatePauseUntilDate")] diff --git a/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs b/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs index 9622e2e6..ced5197b 100644 --- a/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs +++ b/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs @@ -1,4 +1,4 @@ -using Ink_Canvas.Helpers; +using Ink_Canvas.Helpers; using iNKORE.UI.WPF.Modern; using iNKORE.UI.WPF.Modern.Controls; using MdXaml; @@ -500,8 +500,7 @@ namespace Ink_Canvas if (string.IsNullOrEmpty(downloadUrl)) { // 自动更新场景下,downloadUrl为null,直接用主下载目录 - string updatesFolderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "AutoUpdate"); - downloadUrl = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip"); + downloadUrl = AutoUpdateHelper.GetLocalUpdateZipFilePath(version); } LogHelper.WriteLogToFile($"AutoUpdate | 开始安装版本: {version}"); AutoUpdateHelper.InstallNewVersionApp(version, true); diff --git a/Ink Canvas/Windows/SettingsViews/SettingsViews/UpdateCenterPanel.xaml b/Ink Canvas/Windows/SettingsViews/SettingsViews/UpdateCenterPanel.xaml index 569f6a63..7d7c0eb1 100644 --- a/Ink Canvas/Windows/SettingsViews/SettingsViews/UpdateCenterPanel.xaml +++ b/Ink Canvas/Windows/SettingsViews/SettingsViews/UpdateCenterPanel.xaml @@ -157,6 +157,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Ink Canvas/Windows/SettingsViews/SettingsViews/UpdateCenterPanel.xaml.cs b/Ink Canvas/Windows/SettingsViews/SettingsViews/UpdateCenterPanel.xaml.cs index 382f5c05..e7cc69b3 100644 --- a/Ink Canvas/Windows/SettingsViews/SettingsViews/UpdateCenterPanel.xaml.cs +++ b/Ink Canvas/Windows/SettingsViews/SettingsViews/UpdateCenterPanel.xaml.cs @@ -48,7 +48,10 @@ namespace Ink_Canvas.Windows.SettingsViews { var version = Assembly.GetExecutingAssembly().GetName().Version; var platform = Environment.Is64BitOperatingSystem ? "windows-x64" : "windows-x86"; - CurrentVersionText.Text = $"当前版本: v{version} | {platform}"; + var pkgArch = MainWindow.Settings.Startup.UpdatePackageArchitecture == UpdatePackageArchitecture.X64 + ? "更新包: 64位" + : "更新包: 32位"; + CurrentVersionText.Text = $"当前版本: v{version} | {platform} | {pkgArch}"; LoadLastCheckTime(); @@ -111,6 +114,11 @@ namespace Ink_Canvas.Windows.SettingsViews { UpdateUpdateChannelButtons(UpdateChannel.Beta); } + + if (MainWindow.Settings.Startup.UpdatePackageArchitecture == UpdatePackageArchitecture.X64) + UpdateUpdateArchitectureButtons(UpdatePackageArchitecture.X64); + else + UpdateUpdateArchitectureButtons(UpdatePackageArchitecture.X86); } catch (Exception ex) { @@ -806,6 +814,79 @@ namespace Ink_Canvas.Windows.SettingsViews LoadHistoryVersions(); LoadUpdateLogWithPriority(UpdateChannel.Beta); break; + + case "UpdateArch_X86": + MainWindowSettingsHelper.UpdateSettingDirectly(() => + { + MainWindow.Settings.Startup.UpdatePackageArchitecture = UpdatePackageArchitecture.X86; + }, "UpdatePackageArchitecture"); + UpdateUpdateArchitectureButtons(UpdatePackageArchitecture.X86); + MainWindow.SaveSettingsToFile(); + RefreshVersionArchLabel(); + break; + + case "UpdateArch_X64": + MainWindowSettingsHelper.UpdateSettingDirectly(() => + { + MainWindow.Settings.Startup.UpdatePackageArchitecture = UpdatePackageArchitecture.X64; + }, "UpdatePackageArchitecture"); + UpdateUpdateArchitectureButtons(UpdatePackageArchitecture.X64); + MainWindow.SaveSettingsToFile(); + RefreshVersionArchLabel(); + break; + } + } + + private void RefreshVersionArchLabel() + { + try + { + if (MainWindow.Settings == null || CurrentVersionText == null) return; + var version = Assembly.GetExecutingAssembly().GetName().Version; + var platform = Environment.Is64BitOperatingSystem ? "windows-x64" : "windows-x86"; + var pkgArch = MainWindow.Settings.Startup.UpdatePackageArchitecture == UpdatePackageArchitecture.X64 + ? "更新包: 64位" + : "更新包: 32位"; + CurrentVersionText.Text = $"当前版本: v{version} | {platform} | {pkgArch}"; + } + catch { /* ignore */ } + } + + private void UpdateUpdateArchitectureButtons(UpdatePackageArchitecture selected) + { + try + { + bool isDarkTheme = ThemeHelper.IsDarkTheme; + var selectedBrush = isDarkTheme ? new SolidColorBrush(Color.FromRgb(25, 25, 25)) : new SolidColorBrush(Color.FromRgb(225, 225, 225)); + var unselectedBrush = new SolidColorBrush(Colors.Transparent); + + if (UpdateArchX86Border != null) + { + bool isSel = selected == UpdatePackageArchitecture.X86; + UpdateArchX86Border.Background = isSel ? selectedBrush : unselectedBrush; + var tb = UpdateArchX86Border.Child as TextBlock; + if (tb != null) + { + tb.FontWeight = isSel ? FontWeights.Bold : FontWeights.Normal; + tb.Foreground = ThemeHelper.GetTextPrimaryBrush(); + } + } + + if (UpdateArchX64Border != null) + { + bool isSel = selected == UpdatePackageArchitecture.X64; + UpdateArchX64Border.Background = isSel ? selectedBrush : unselectedBrush; + var tb = UpdateArchX64Border.Child as TextBlock; + if (tb != null) + { + tb.FontWeight = isSel ? FontWeights.Bold : FontWeights.Normal; + tb.Foreground = ThemeHelper.GetTextPrimaryBrush(); + } + } + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"更新软件架构按钮状态时出错: {ex.Message}"); } }