mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-10 00:44:10 +08:00
Mirror酱集成 (#1666)
* 更多更新渠道的UI改造 * CDK存储逻辑 * feat: enhance CDK input dialog with left button and update check logic for Alpha channel * 支持修改cdk * 支持删除cdk
This commit is contained in:
@@ -1,2 +1,5 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=enkanomiya/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=chyan/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=enkanomiya/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mirrorchan/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=steambird/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -18,14 +18,10 @@
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #555;
|
||||
}
|
||||
.body {
|
||||
background-color: #202020;
|
||||
color: #e6edf3;
|
||||
}
|
||||
.markdown-body {
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
background-color: #202020;
|
||||
background-color: #202020 !important;
|
||||
height: 100%
|
||||
}
|
||||
* {
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
<PackageReference Include="DeviceId.Windows" Version="6.9.0" />
|
||||
<PackageReference Include="DeviceId.Windows.Wmi" Version="6.9.0" />
|
||||
<PackageReference Include="Emoji.Wpf" Version="0.3.4" />
|
||||
<PackageReference Include="Meziantou.Framework.Win32.CredentialManager" Version="1.7.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.4" />
|
||||
|
||||
52
BetterGenshinImpact/Helpers/Win32/CredentialManagerHelper.cs
Normal file
52
BetterGenshinImpact/Helpers/Win32/CredentialManagerHelper.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using Meziantou.Framework.Win32;
|
||||
|
||||
namespace BetterGenshinImpact.Helpers.Win32;
|
||||
|
||||
public static class CredentialManagerHelper
|
||||
{
|
||||
public static void SaveCredential(string applicationName, string userName, string secret, string comment,
|
||||
CredentialPersistence persistence)
|
||||
{
|
||||
CredentialManager.WriteCredential(
|
||||
applicationName: applicationName,
|
||||
userName: userName,
|
||||
secret: secret,
|
||||
comment: comment,
|
||||
persistence: persistence);
|
||||
}
|
||||
|
||||
public static Credential? ReadCredential(string applicationName)
|
||||
{
|
||||
var credential = CredentialManager.ReadCredential(applicationName);
|
||||
if (credential == null)
|
||||
{
|
||||
Console.WriteLine("No credential found.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Console.WriteLine($"UserName: {credential.UserName}");
|
||||
Console.WriteLine($"Secret: {credential.Password}");
|
||||
Console.WriteLine($"Comment: {credential.Comment}");
|
||||
|
||||
return credential;
|
||||
}
|
||||
|
||||
public static void UpdateCredential(string applicationName, string newUserName, string newSecret, string newComment)
|
||||
{
|
||||
SaveCredential(applicationName, newUserName, newSecret, newComment, CredentialPersistence.LocalMachine);
|
||||
}
|
||||
|
||||
public static void DeleteCredential(string applicationName)
|
||||
{
|
||||
try
|
||||
{
|
||||
CredentialManager.DeleteCredential(applicationName);
|
||||
Console.WriteLine("Credential deleted successfully.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error deleting credential: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
93
BetterGenshinImpact/Helpers/Win32/MirrorChyanHelper.cs
Normal file
93
BetterGenshinImpact/Helpers/Win32/MirrorChyanHelper.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using Windows.System;
|
||||
using BetterGenshinImpact.View.Windows;
|
||||
using Meziantou.Framework.Win32;
|
||||
using Wpf.Ui.Violeta.Controls;
|
||||
|
||||
namespace BetterGenshinImpact.Helpers.Win32;
|
||||
|
||||
public static class MirrorChyanHelper
|
||||
{
|
||||
public static readonly string MirrorChyanCdkAppName = "KachinaInstaller_MirrorChyanCDK_BetterGI";
|
||||
|
||||
|
||||
public static string? GetCdk()
|
||||
{
|
||||
var credential = CredentialManagerHelper.ReadCredential(MirrorChyanCdkAppName);
|
||||
return credential?.Password;
|
||||
}
|
||||
|
||||
public static string? GetAndPromptCdk()
|
||||
{
|
||||
var credential = CredentialManagerHelper.ReadCredential(MirrorChyanCdkAppName);
|
||||
if (credential == null || credential.Password == null)
|
||||
{
|
||||
var cdk = PromptDialog.Prompt("Mirror酱是独立的第三方软件下载平台,提供付费的软件下载加速服务。\n如果你有 Mirror酱的 CDK,可以在这里输入。",
|
||||
"请输入Mirror酱CDK",
|
||||
string.Empty,
|
||||
new PromptDialogConfig
|
||||
{
|
||||
ShowLeftButton = true,
|
||||
LeftButtonText = "获取CDK",
|
||||
LeftButtonClick = (sender, args) =>
|
||||
{
|
||||
Launcher.LaunchUriAsync(new Uri("https://mirrorchyan.com/zh/get-start"));
|
||||
}
|
||||
}
|
||||
);
|
||||
if (string.IsNullOrEmpty(cdk))
|
||||
{
|
||||
Toast.Warning("输入CDK为空,无法继续操作");
|
||||
return null;
|
||||
}
|
||||
|
||||
CredentialManagerHelper.SaveCredential(
|
||||
MirrorChyanCdkAppName,
|
||||
string.Empty,
|
||||
cdk,
|
||||
string.Empty,
|
||||
CredentialPersistence.LocalMachine);
|
||||
return cdk;
|
||||
}
|
||||
else
|
||||
{
|
||||
return credential.Password;
|
||||
}
|
||||
}
|
||||
|
||||
public static void EditCdk()
|
||||
{
|
||||
var credential = CredentialManagerHelper.ReadCredential(MirrorChyanCdkAppName);
|
||||
var cdk = PromptDialog.Prompt("Mirror酱是独立的第三方软件下载平台,提供付费的软件下载加速服务。\n如果你有 Mirror酱的 CDK,可以在这里输入。",
|
||||
"修改Mirror酱CDK",
|
||||
credential?.Password!,
|
||||
new PromptDialogConfig
|
||||
{
|
||||
ShowLeftButton = true,
|
||||
LeftButtonText = "获取CDK",
|
||||
LeftButtonClick = (sender, args) =>
|
||||
{
|
||||
Launcher.LaunchUriAsync(new Uri("https://mirrorchyan.com/zh/get-start"));
|
||||
}
|
||||
}
|
||||
);
|
||||
if (string.IsNullOrEmpty(cdk))
|
||||
{
|
||||
DeleteCdk();
|
||||
}
|
||||
else
|
||||
{
|
||||
CredentialManagerHelper.SaveCredential(
|
||||
MirrorChyanCdkAppName,
|
||||
string.Empty,
|
||||
cdk,
|
||||
string.Empty,
|
||||
CredentialPersistence.LocalMachine);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DeleteCdk()
|
||||
{
|
||||
CredentialManagerHelper.DeleteCredential(MirrorChyanCdkAppName);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
public sealed class UpdateOption
|
||||
{
|
||||
public UpdateTrigger Trigger { get; set; } = default;
|
||||
|
||||
public UpdateChannel Channel { get; set; } = UpdateChannel.Stable;
|
||||
}
|
||||
|
||||
public enum UpdateTrigger
|
||||
@@ -10,3 +12,10 @@ public enum UpdateTrigger
|
||||
Auto,
|
||||
Manual,
|
||||
}
|
||||
|
||||
|
||||
public enum UpdateChannel
|
||||
{
|
||||
Stable,
|
||||
Alpha,
|
||||
}
|
||||
117
BetterGenshinImpact/Service/Model/MirrorChyan/LatestResponse.cs
Normal file
117
BetterGenshinImpact/Service/Model/MirrorChyan/LatestResponse.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace BetterGenshinImpact.Service.Model.MirrorChyan;
|
||||
|
||||
#nullable enable
|
||||
#pragma warning disable CS8618
|
||||
#pragma warning disable CS8601
|
||||
#pragma warning disable CS8603
|
||||
public partial class LatestResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// 响应代码,https://github.com/MirrorChyan/docs/blob/main/ErrorCode.md
|
||||
/// </summary>
|
||||
[JsonPropertyName("code")]
|
||||
public long Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 响应数据
|
||||
/// </summary>
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonPropertyName("data")]
|
||||
public Data Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 响应信息
|
||||
/// </summary>
|
||||
[JsonPropertyName("msg")]
|
||||
public string Msg { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 响应数据
|
||||
/// </summary>
|
||||
public partial class Data
|
||||
{
|
||||
/// <summary>
|
||||
/// 更新包架构
|
||||
/// </summary>
|
||||
[JsonPropertyName("arch")]
|
||||
public string Arch { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// CDK过期时间戳
|
||||
/// </summary>
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonPropertyName("cdk_expired_time")]
|
||||
public double? CdkExpiredTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新频道,stable | beta | alpha
|
||||
/// </summary>
|
||||
[JsonPropertyName("channel")]
|
||||
public string Channel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义数据
|
||||
/// </summary>
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonPropertyName("custom_data")]
|
||||
public string CustomData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件大小
|
||||
/// </summary>
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonPropertyName("filesize")]
|
||||
public long? Filesize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新包系统
|
||||
/// </summary>
|
||||
[JsonPropertyName("os")]
|
||||
public string Os { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 发版日志
|
||||
/// </summary>
|
||||
[JsonPropertyName("release_note")]
|
||||
public string ReleaseNote { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// sha256
|
||||
/// </summary>
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonPropertyName("sha256")]
|
||||
public string Sha256 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新包类型,incremental | full
|
||||
/// </summary>
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonPropertyName("update_type")]
|
||||
public string UpdateType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 下载地址
|
||||
/// </summary>
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[JsonPropertyName("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源版本名称
|
||||
/// </summary>
|
||||
[JsonPropertyName("version_name")]
|
||||
public string VersionName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 资源版本号仅内部使用
|
||||
/// </summary>
|
||||
[JsonPropertyName("version_number")]
|
||||
public long VersionNumber { get; set; }
|
||||
}
|
||||
|
||||
#pragma warning restore CS8618
|
||||
#pragma warning restore CS8601
|
||||
#pragma warning restore CS8603
|
||||
@@ -10,6 +10,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
@@ -18,6 +19,8 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using BetterGenshinImpact.Service.Model.MirrorChyan;
|
||||
using Wpf.Ui.Violeta.Controls;
|
||||
|
||||
namespace BetterGenshinImpact.Service;
|
||||
|
||||
@@ -37,7 +40,7 @@ public class UpdateService : IUpdateService
|
||||
_configService = configService;
|
||||
Config = _configService.Get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Please call me in main thread
|
||||
@@ -50,13 +53,13 @@ public class UpdateService : IUpdateService
|
||||
#if DEBUG && false
|
||||
return;
|
||||
#endif
|
||||
string newVersion = await GetLatestVersionAsync();
|
||||
string newVersion = await GetLatestVersionAsync(option);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(newVersion))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// ---- 如果是调试模式且手动的检查更新的情况下,强制打开更新窗口 -----
|
||||
// 方便调试窗口
|
||||
if (RuntimeHelper.IsDebuggerAttached && option.Trigger == UpdateTrigger.Manual)
|
||||
@@ -72,7 +75,7 @@ public class UpdateService : IUpdateService
|
||||
{
|
||||
await MessageBox.InformationAsync("当前已是最新版本!");
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -87,7 +90,8 @@ public class UpdateService : IUpdateService
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine("获取最新版本信息失败:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message);
|
||||
Debug.WriteLine("获取最新版本信息失败:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" +
|
||||
Environment.NewLine + e.Message);
|
||||
_logger.LogWarning("获取 BetterGI 最新版本信息失败");
|
||||
}
|
||||
}
|
||||
@@ -110,7 +114,14 @@ public class UpdateService : IUpdateService
|
||||
break;
|
||||
|
||||
case CheckUpdateWindow.CheckUpdateWindowButton.OtherUpdate:
|
||||
Process.Start(new ProcessStartInfo(DownloadPageUrl) { UseShellExecute = true });
|
||||
if (option.Channel == UpdateChannel.Stable)
|
||||
{
|
||||
Process.Start(new ProcessStartInfo(DownloadPageUrl) { UseShellExecute = true });
|
||||
}
|
||||
else
|
||||
{
|
||||
Process.Start(new ProcessStartInfo("https://github.com/babalae/better-genshin-impact/actions/workflows/publish.yml") { UseShellExecute = true });
|
||||
}
|
||||
break;
|
||||
|
||||
case CheckUpdateWindow.CheckUpdateWindowButton.Update:
|
||||
@@ -122,12 +133,12 @@ public class UpdateService : IUpdateService
|
||||
await MessageBox.ErrorAsync("更新程序不存在,请选择其他更新方式!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 启动
|
||||
Process.Start(updaterExePath, "-I");
|
||||
|
||||
|
||||
// 退出程序
|
||||
Application.Current.Shutdown();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -144,11 +155,118 @@ public class UpdateService : IUpdateService
|
||||
}
|
||||
};
|
||||
|
||||
win.NavigateToHtml(await GetReleaseMarkdownHtmlAsync());
|
||||
if (option.Channel == UpdateChannel.Stable)
|
||||
{
|
||||
win.NavigateToHtml(await GetReleaseMarkdownHtmlAsync());
|
||||
}
|
||||
|
||||
win.ShowDialog();
|
||||
}
|
||||
|
||||
private async Task<string> GetLatestVersionAsync()
|
||||
private async Task<string> GetLatestVersionAsync(UpdateOption option)
|
||||
{
|
||||
if (option.Channel == UpdateChannel.Stable)
|
||||
{
|
||||
return await UpdateFromOss();
|
||||
}
|
||||
else
|
||||
{
|
||||
return await UpdateFromMirrorChyan();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文档
|
||||
/// https://apifox.com/apidoc/shared/ffdc8453-597d-4ba6-bd3c-5e375c10c789
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task<string> UpdateFromMirrorChyan()
|
||||
{
|
||||
try
|
||||
{
|
||||
const string url = "https://mirrorchyan.com/api/resources/BGI/latest";
|
||||
var queryParams = new Dictionary<string, string>
|
||||
{
|
||||
{ "user_agent", "BetterGI" },
|
||||
{ "os", "win" },
|
||||
{ "arch", "x64" },
|
||||
{ "channel", "alpha" }
|
||||
};
|
||||
|
||||
using var httpClient = new HttpClient();
|
||||
|
||||
var finalUrl = $"{url}?{string.Join("&", queryParams.Select(x => $"{x.Key}={x.Value}"))}";
|
||||
var response = await httpClient.GetAsync(finalUrl);
|
||||
LatestResponse? result = null;
|
||||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
response.EnsureSuccessStatusCode();
|
||||
result = await response.Content.ReadFromJsonAsync<LatestResponse>();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 即使是403、400也尝试读取响应体
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
result = JsonConvert.DeserializeObject<LatestResponse>(content);
|
||||
}
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
if (result.Code == 0)
|
||||
{
|
||||
return result.Data.VersionName;
|
||||
}
|
||||
else if (result.Code < 0)
|
||||
{
|
||||
Toast.Error(
|
||||
$"Mirror酱源更新检查失败,意料之外的严重错误,请及时联系 Mirror 酱的技术支持处理\n,错误代码:{result.Code},错误信息:{result.Msg}");
|
||||
return string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
ToastError(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogDebug(e, "Mirror源更新检查失败");
|
||||
Toast.Warning($"Mirror源更新检查失败,{e.Message}");
|
||||
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private static void ToastError(LatestResponse response)
|
||||
{
|
||||
if (response.Code == 7001)
|
||||
{
|
||||
Toast.Warning("Mirror酱 CDK 已过期,请重新获取CDK");
|
||||
}
|
||||
else if (response.Code == 7002)
|
||||
{
|
||||
Toast.Warning("Mirror酱 CDK 错误!");
|
||||
}
|
||||
else if (response.Code == 7003)
|
||||
{
|
||||
Toast.Warning("Mirror酱 CDK 今日下载次数已达上限");
|
||||
}
|
||||
else if (response.Code == 7004)
|
||||
{
|
||||
Toast.Warning("Mirror酱 CDK 类型和待下载的资源不匹配");
|
||||
}
|
||||
else if (response.Code == 7005)
|
||||
{
|
||||
Toast.Warning("Mirror酱 CDK 已被封禁");
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.Warning($"Mirror酱源更新检查失败,错误信息:{response.Msg}");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> UpdateFromOss()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -181,7 +299,9 @@ public class UpdateService : IUpdateService
|
||||
{
|
||||
using HttpClient httpClient = new();
|
||||
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
|
||||
string jsonString = await httpClient.GetStringAsync("https://api.github.com/repos/babalae/better-genshin-impact/releases/latest");
|
||||
string jsonString =
|
||||
await httpClient.GetStringAsync(
|
||||
"https://api.github.com/repos/babalae/better-genshin-impact/releases/latest");
|
||||
var jsonDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString);
|
||||
|
||||
if (jsonDict != null)
|
||||
@@ -191,7 +311,8 @@ public class UpdateService : IUpdateService
|
||||
string md = $"# {name}{new string('\n', 2)}{body}";
|
||||
|
||||
md = WebUtility.HtmlEncode(md);
|
||||
string md2html = ResourceHelper.GetString($"pack://application:,,,/Assets/Strings/md2html.html", Encoding.UTF8);
|
||||
string md2html = ResourceHelper.GetString($"pack://application:,,,/Assets/Strings/md2html.html",
|
||||
Encoding.UTF8);
|
||||
var html = md2html.Replace("{{content}}", md);
|
||||
|
||||
return html;
|
||||
@@ -240,4 +361,4 @@ public class UpdateService : IUpdateService
|
||||
</html>
|
||||
""";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1176,7 +1176,7 @@
|
||||
Grid.RowSpan="2"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,20,0"
|
||||
Command="{Binding OpenKeyBindingsWindowCommand}"
|
||||
Command="{Binding CheckUpdateCommand}"
|
||||
Content="检查更新" />
|
||||
</Grid>
|
||||
</ui:CardExpander.Header>
|
||||
@@ -1192,20 +1192,50 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
<emoji:TextBlock Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Text="使用 Mirror 酱 更新至测试版⚡"
|
||||
Text="检查是否存在最新测试版"
|
||||
TextWrapping="Wrap" />
|
||||
<ui:TextBlock Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}"
|
||||
Text="测试版非常不稳定,请谨慎选择更新!"
|
||||
Text="【测试版】非常不稳定,请谨慎选择更新!"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="2"
|
||||
Grid.Column="1"
|
||||
Orientation="Horizontal">
|
||||
<ui:Button
|
||||
Margin="0,0,36,0"
|
||||
Command="{Binding CheckUpdateAlphaCommand}"
|
||||
Content="检查更新" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<!--<Grid Margin="16">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<emoji:TextBlock Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Text="直接从 Github 获取最新测试版"
|
||||
TextWrapping="Wrap" />
|
||||
<ui:TextBlock Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}"
|
||||
Text="【测试版】非常不稳定,请谨慎选择更新!"
|
||||
TextWrapping="Wrap" />
|
||||
<ui:Button Grid.Row="0"
|
||||
Grid.RowSpan="2"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,36,0"
|
||||
Command="{Binding OpenKeyBindingsWindowCommand}"
|
||||
Content="测试版检查更新" />
|
||||
</Grid>
|
||||
Command="{Binding GotoGithubActionCommand}"
|
||||
Content="访问 Github" />
|
||||
</Grid>-->
|
||||
</StackPanel>
|
||||
</ui:CardExpander>
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
x:Name="app"
|
||||
Title="发现新版本"
|
||||
Width="680"
|
||||
Height="800"
|
||||
MinHeight="10"
|
||||
SizeToContent="Height"
|
||||
Background="#202020"
|
||||
ExtendsContentIntoTitleBar="True"
|
||||
FontFamily="{DynamicResource TextThemeFontFamily}"
|
||||
@@ -19,11 +20,13 @@
|
||||
WindowStartupLocation="CenterOwner"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<ui:Grid Margin="0,48,0,0" RowDefinitions="Auto,*,Auto,Auto">
|
||||
<ui:Grid Name="MyGrid" Margin="0,48,0,0" RowDefinitions="Auto,*,Auto,Auto">
|
||||
<webview:WebpagePanel x:Name="WebpagePanel"
|
||||
Grid.Row="1"
|
||||
Height="400"
|
||||
Margin="12,0,12,0" />
|
||||
<ui:Grid Grid.Row="0"
|
||||
<ui:Grid Name="UpdateStatusMessageGrid"
|
||||
Grid.Row="0"
|
||||
Margin="16,0,16,0"
|
||||
ColumnDefinitions="Auto,*"
|
||||
Visibility="{Binding ShowUpdateStatus, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
@@ -33,8 +36,8 @@
|
||||
</ui:StackPanel>
|
||||
</ui:Grid>
|
||||
<!-- 新增:多渠道更新方式卡片 -->
|
||||
<StackPanel Grid.Row="2" Margin="12,0,12,0">
|
||||
<ui:CardControl Margin="0,0,0,8">
|
||||
<StackPanel Name="ServerPanel" Grid.Row="2" Margin="12,0,12,0">
|
||||
<ui:CardControl Name="DefaultCard" Margin="0,0,0,8">
|
||||
<ui:CardControl.Icon>
|
||||
<ui:FontIcon Glyph="" Style="{StaticResource FaFontIconStyle}" />
|
||||
</ui:CardControl.Icon>
|
||||
@@ -47,12 +50,12 @@
|
||||
<ui:TextBlock Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
FontTypography="Body"
|
||||
Text="Steambird"
|
||||
Text="默认更新服务器"
|
||||
TextWrapping="Wrap" />
|
||||
<ui:TextBlock Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}"
|
||||
Text="普通用户可通过 Steambird 渠道直接更新(默认更新渠道)"
|
||||
Text="普通用户可点此直接更新"
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</ui:CardControl.Header>
|
||||
@@ -61,7 +64,7 @@
|
||||
Appearance="Success"
|
||||
Icon="{ui:SymbolIcon ArrowDownload24}"
|
||||
Content="立即更新"
|
||||
Command="{Binding UpdateCommand}" />
|
||||
Command="{Binding UpdateFromSteambirdCommand}" />
|
||||
</StackPanel>
|
||||
</ui:CardControl>
|
||||
<ui:CardControl Margin="0,0,0,8">
|
||||
@@ -86,15 +89,21 @@
|
||||
</Grid>
|
||||
</ui:CardControl.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ui:Button
|
||||
Appearance="Primary"
|
||||
<ui:Button
|
||||
Name="EditCdkButton"
|
||||
Margin="0,0,8,0"
|
||||
Icon="{ui:SymbolIcon TicketDiagonal24}"
|
||||
Content="输入CDK更新"
|
||||
Command="{Binding OneKeyExecuteCommand}" />
|
||||
Content="修改CDK"
|
||||
Command="{Binding EditCdkCommand}" />
|
||||
<ui:Button
|
||||
Appearance="Success"
|
||||
Icon="{ui:SymbolIcon ArrowDownload24}"
|
||||
Content="立即更新"
|
||||
Command="{Binding UpdateFromMirrorChyanCommand}" />
|
||||
</StackPanel>
|
||||
</ui:CardControl>
|
||||
|
||||
<ui:CardControl Margin="0,0,0,8">
|
||||
<!--<ui:CardControl Margin="0,0,0,8">
|
||||
<ui:CardControl.Icon>
|
||||
<ui:FontIcon Glyph="" Style="{StaticResource FaFontIconStyle}" />
|
||||
</ui:CardControl.Icon>
|
||||
@@ -122,7 +131,7 @@
|
||||
Content="唤起胡桃"
|
||||
Command="{Binding OneKeyExecuteCommand}" />
|
||||
</StackPanel>
|
||||
</ui:CardControl>
|
||||
</ui:CardControl>-->
|
||||
</StackPanel>
|
||||
<!-- 原有按钮区域 -->
|
||||
<ui:Grid Grid.Row="3"
|
||||
|
||||
@@ -2,10 +2,17 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Windows.System;
|
||||
using BetterGenshinImpact.Core.Config;
|
||||
using BetterGenshinImpact.Helpers.Win32;
|
||||
using BetterGenshinImpact.Model;
|
||||
using Meziantou.Framework.Win32;
|
||||
using Wpf.Ui.Controls;
|
||||
using Wpf.Ui.Violeta.Controls;
|
||||
|
||||
namespace BetterGenshinImpact.View.Windows;
|
||||
|
||||
@@ -14,22 +21,59 @@ public partial class CheckUpdateWindow : FluentWindow
|
||||
{
|
||||
public Func<object, CheckUpdateWindowButton, Task>? UserInteraction = null!;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool showUpdateStatus = false;
|
||||
[ObservableProperty] private bool showUpdateStatus = false;
|
||||
|
||||
[ObservableProperty]
|
||||
private string updateStatusMessage = string.Empty;
|
||||
[ObservableProperty] private string updateStatusMessage = string.Empty;
|
||||
|
||||
private UpdateOption _option;
|
||||
|
||||
public CheckUpdateWindow(UpdateOption option)
|
||||
{
|
||||
_option = option ?? throw new ArgumentNullException(nameof(option));
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
|
||||
|
||||
// 存在CDK则显示修改按钮
|
||||
if (string.IsNullOrEmpty(MirrorChyanHelper.GetCdk()))
|
||||
{
|
||||
EditCdkButton.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
if (option.Trigger == UpdateTrigger.Manual)
|
||||
{
|
||||
IgnoreButton.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
if (option.Channel == UpdateChannel.Alpha)
|
||||
{
|
||||
WebpagePanel.Height = 0;
|
||||
WebpagePanel.Visibility = Visibility.Collapsed;
|
||||
UpdateStatusMessageGrid.Height = 0;
|
||||
ShowUpdateStatus = false;
|
||||
|
||||
// 删除前两行
|
||||
MyGrid.RowDefinitions.RemoveAt(0);
|
||||
MyGrid.RowDefinitions.RemoveAt(0);
|
||||
|
||||
// 注意:删除行定义后,需要调整剩余元素的 Grid.Row 属性
|
||||
foreach (FrameworkElement child in MyGrid.Children)
|
||||
{
|
||||
int currentRow = System.Windows.Controls.Grid.GetRow(child);
|
||||
if (currentRow > 1) // 如果元素在第三行或之后
|
||||
{
|
||||
Grid.SetRow(child, currentRow - 2); // 行号减2
|
||||
}
|
||||
}
|
||||
|
||||
if (ServerPanel.Children.Count > 0)
|
||||
{
|
||||
ServerPanel.Children.RemoveAt(0);
|
||||
}
|
||||
SizeToContent = SizeToContent.Height; // 设置高度为自动
|
||||
UpdateLayout();
|
||||
}
|
||||
|
||||
|
||||
Closing += OnClosing;
|
||||
}
|
||||
|
||||
@@ -73,6 +117,55 @@ public partial class CheckUpdateWindow : FluentWindow
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[RelayCommand]
|
||||
private async Task UpdateFromSteambirdAsync()
|
||||
{
|
||||
await RunUpdaterAsync("-I");
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task UpdateFromMirrorChyanAsync()
|
||||
{
|
||||
var cdk = MirrorChyanHelper.GetAndPromptCdk();
|
||||
if (string.IsNullOrEmpty(cdk))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_option.Channel == UpdateChannel.Stable)
|
||||
{
|
||||
await RunUpdaterAsync("--source mirrorc");
|
||||
}
|
||||
else
|
||||
{
|
||||
await RunUpdaterAsync("--source mirrorc-alpha");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// --source mirrorc
|
||||
/// --source mirrorc-alpha
|
||||
/// --source github
|
||||
/// --dfs-extras {"hutao-token": "...."}
|
||||
/// </summary>
|
||||
private async Task RunUpdaterAsync(string parameters)
|
||||
{
|
||||
// 唤起更新程序
|
||||
string updaterExePath = Global.Absolute("BetterGI.update.exe");
|
||||
if (!File.Exists(updaterExePath))
|
||||
{
|
||||
await MessageBox.ErrorAsync("更新程序不存在,请选择其他更新方式!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 启动
|
||||
Process.Start(updaterExePath, parameters);
|
||||
|
||||
// 退出程序
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task IgnoreAsync()
|
||||
{
|
||||
@@ -90,6 +183,12 @@ public partial class CheckUpdateWindow : FluentWindow
|
||||
await UserInteraction.Invoke(this, CheckUpdateWindowButton.Cancel);
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void EditCdk()
|
||||
{
|
||||
MirrorChyanHelper.EditCdk();
|
||||
}
|
||||
|
||||
public enum CheckUpdateWindowButton
|
||||
{
|
||||
|
||||
@@ -28,21 +28,36 @@
|
||||
<ui:TextBlock Name="TxtQuestion" Margin="5" />
|
||||
<!-- <ui:TextBox Name="TxtResponse" Margin="5" /> -->
|
||||
<ContentControl Name="DynamicContent" Margin="5" />
|
||||
<StackPanel Margin="5"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<ui:Button Name="BtnOk"
|
||||
<Grid Margin="5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 左下角按钮 -->
|
||||
<ui:Button Name="BtnLeftBottom"
|
||||
Margin="5"
|
||||
Appearance="Primary"
|
||||
Click="BtnOkClick"
|
||||
Content="确定"
|
||||
IsDefault="True" />
|
||||
<ui:Button Name="BtnCancel"
|
||||
Margin="5"
|
||||
Click="BtnCancelClick"
|
||||
Content="取消"
|
||||
IsCancel="True" />
|
||||
</StackPanel>
|
||||
HorizontalAlignment="Left"
|
||||
Appearance="Success"
|
||||
Content="左下角按钮"
|
||||
Grid.Column="0" />
|
||||
|
||||
<!-- 原有的右侧按钮 -->
|
||||
<StackPanel Grid.Column="1"
|
||||
Orientation="Horizontal">
|
||||
<ui:Button Name="BtnOk"
|
||||
Margin="5"
|
||||
Appearance="Primary"
|
||||
Click="BtnOkClick"
|
||||
Content="确定"
|
||||
IsDefault="True" />
|
||||
<ui:Button Name="BtnCancel"
|
||||
Margin="5"
|
||||
Click="BtnCancelClick"
|
||||
Content="取消"
|
||||
IsCancel="True" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<ui:TitleBar Name="MyTitleBar" Grid.Row="0">
|
||||
|
||||
@@ -3,13 +3,37 @@ using System.Windows.Controls;
|
||||
|
||||
namespace BetterGenshinImpact.View.Windows;
|
||||
|
||||
/// <summary>
|
||||
/// 对话框配置类,用于控制对话框中的元素显示
|
||||
/// </summary>
|
||||
public class PromptDialogConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否显示左下角按钮
|
||||
/// </summary>
|
||||
public bool ShowLeftButton { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 左下角按钮的文本
|
||||
/// </summary>
|
||||
public string LeftButtonText { get; set; } = "左下角按钮";
|
||||
|
||||
/// <summary>
|
||||
/// 左下角按钮的点击事件
|
||||
/// </summary>
|
||||
public RoutedEventHandler? LeftButtonClick { get; set; }
|
||||
}
|
||||
|
||||
public partial class PromptDialog
|
||||
{
|
||||
public PromptDialog(string question, string title, UIElement uiElement, string defaultValue)
|
||||
private readonly PromptDialogConfig _config;
|
||||
|
||||
public PromptDialog(string question, string title, UIElement uiElement, string defaultValue, PromptDialogConfig? config = null)
|
||||
{
|
||||
InitializeComponent();
|
||||
MyTitleBar.Title = title;
|
||||
TxtQuestion.Text = question;
|
||||
_config = config ?? new PromptDialogConfig();
|
||||
|
||||
DynamicContent.Content = uiElement;
|
||||
if (DynamicContent.Content is TextBox textBox)
|
||||
@@ -21,31 +45,50 @@ public partial class PromptDialog
|
||||
comboBox.Text = defaultValue;
|
||||
}
|
||||
|
||||
// 配置左下角按钮
|
||||
ConfigureLeftButton();
|
||||
|
||||
this.Loaded += PromptDialogLoaded;
|
||||
}
|
||||
|
||||
private void ConfigureLeftButton()
|
||||
{
|
||||
if (_config.ShowLeftButton)
|
||||
{
|
||||
BtnLeftBottom.Content = _config.LeftButtonText;
|
||||
if (_config.LeftButtonClick != null)
|
||||
{
|
||||
BtnLeftBottom.Click += _config.LeftButtonClick;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BtnLeftBottom.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private void PromptDialogLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DynamicContent.Focus();
|
||||
}
|
||||
|
||||
public static string Prompt(string question, string title, string defaultValue = "")
|
||||
public static string Prompt(string question, string title, string defaultValue = "", PromptDialogConfig? config = null)
|
||||
{
|
||||
var inst = new PromptDialog(question, title, new TextBox(), defaultValue);
|
||||
var inst = new PromptDialog(question, title, new TextBox(), defaultValue, config);
|
||||
inst.ShowDialog();
|
||||
return inst.DialogResult == true ? inst.ResponseText : defaultValue;
|
||||
}
|
||||
|
||||
public static string Prompt(string question, string title, UIElement uiElement, string defaultValue = "")
|
||||
public static string Prompt(string question, string title, UIElement uiElement, string defaultValue = "", PromptDialogConfig? config = null)
|
||||
{
|
||||
var inst = new PromptDialog(question, title, uiElement, defaultValue);
|
||||
var inst = new PromptDialog(question, title, uiElement, defaultValue, config);
|
||||
inst.ShowDialog();
|
||||
return inst.DialogResult == true ? inst.ResponseText : defaultValue;
|
||||
}
|
||||
|
||||
public static string Prompt(string question, string title, UIElement uiElement, Size size)
|
||||
public static string Prompt(string question, string title, UIElement uiElement, Size size, PromptDialogConfig? config = null)
|
||||
{
|
||||
var inst = new PromptDialog(question, title, uiElement, "")
|
||||
var inst = new PromptDialog(question, title, uiElement, "", config)
|
||||
{
|
||||
Width = size.Width,
|
||||
Height = size.Height
|
||||
|
||||
@@ -9,6 +9,7 @@ using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Windows.System;
|
||||
using BetterGenshinImpact.Core.Config;
|
||||
using BetterGenshinImpact.Core.Recognition.OCR;
|
||||
using BetterGenshinImpact.Core.Script;
|
||||
@@ -16,6 +17,8 @@ using BetterGenshinImpact.GameTask;
|
||||
using BetterGenshinImpact.GameTask.AutoTrackPath;
|
||||
using BetterGenshinImpact.GameTask.Common.Element.Assets;
|
||||
using BetterGenshinImpact.Helpers;
|
||||
using BetterGenshinImpact.Helpers.Win32;
|
||||
using BetterGenshinImpact.Model;
|
||||
using BetterGenshinImpact.Service.Interface;
|
||||
using BetterGenshinImpact.Service.Notification;
|
||||
using BetterGenshinImpact.View.Converters;
|
||||
@@ -25,9 +28,11 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using Meziantou.Framework.Win32;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Win32;
|
||||
using Wpf.Ui;
|
||||
using Wpf.Ui.Violeta.Controls;
|
||||
|
||||
namespace BetterGenshinImpact.ViewModel.Pages;
|
||||
|
||||
@@ -42,8 +47,8 @@ public partial class CommonSettingsPageViewModel : ViewModel
|
||||
|
||||
|
||||
private string _selectedCountry = string.Empty;
|
||||
[ObservableProperty]
|
||||
private List<string> _adventurersGuildCountry = ["无","枫丹", "稻妻", "璃月", "蒙德"];
|
||||
[ObservableProperty] private List<string> _adventurersGuildCountry = ["无", "枫丹", "稻妻", "璃月", "蒙德"];
|
||||
|
||||
public CommonSettingsPageViewModel(IConfigService configService, INavigationService navigationService,
|
||||
NotificationService notificationService)
|
||||
{
|
||||
@@ -57,17 +62,18 @@ public partial class CommonSettingsPageViewModel : ViewModel
|
||||
public ObservableCollection<string> CountryList { get; } = new();
|
||||
public ObservableCollection<string> Areas { get; } = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private FrozenDictionary<string, string> _languageDict = new string[] { "zh-Hans", "zh-Hant", "en", "fr" }
|
||||
.ToFrozenDictionary(
|
||||
c => c,
|
||||
c =>
|
||||
{
|
||||
CultureInfo.CurrentUICulture = new CultureInfo(c);
|
||||
var stringLocalizer = App.GetService<IStringLocalizer<CultureInfoNameToKVPConverter>>() ?? throw new NullReferenceException();
|
||||
return stringLocalizer["简体中文"].ToString();
|
||||
}
|
||||
);
|
||||
[ObservableProperty] private FrozenDictionary<string, string> _languageDict =
|
||||
new string[] { "zh-Hans", "zh-Hant", "en", "fr" }
|
||||
.ToFrozenDictionary(
|
||||
c => c,
|
||||
c =>
|
||||
{
|
||||
CultureInfo.CurrentUICulture = new CultureInfo(c);
|
||||
var stringLocalizer = App.GetService<IStringLocalizer<CultureInfoNameToKVPConverter>>() ??
|
||||
throw new NullReferenceException();
|
||||
return stringLocalizer["简体中文"].ToString();
|
||||
}
|
||||
);
|
||||
|
||||
public string SelectedCountry
|
||||
{
|
||||
@@ -238,7 +244,7 @@ public partial class CommonSettingsPageViewModel : ViewModel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[RelayCommand]
|
||||
private void OpenAboutWindow()
|
||||
{
|
||||
@@ -246,7 +252,7 @@ public partial class CommonSettingsPageViewModel : ViewModel
|
||||
aboutWindow.Owner = Application.Current.MainWindow;
|
||||
aboutWindow.ShowDialog();
|
||||
}
|
||||
|
||||
|
||||
[RelayCommand]
|
||||
private void OpenKeyBindingsWindow()
|
||||
{
|
||||
@@ -260,4 +266,31 @@ public partial class CommonSettingsPageViewModel : ViewModel
|
||||
{
|
||||
await OcrFactory.ChangeCulture(type.Key);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task CheckUpdateAsync()
|
||||
{
|
||||
await App.GetService<IUpdateService>()!.CheckUpdateAsync(new UpdateOption
|
||||
{
|
||||
Trigger = UpdateTrigger.Manual,
|
||||
Channel = UpdateChannel.Stable
|
||||
});
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task CheckUpdateAlphaAsync()
|
||||
{
|
||||
await App.GetService<IUpdateService>()!.CheckUpdateAsync(new UpdateOption
|
||||
{
|
||||
Trigger = UpdateTrigger.Manual,
|
||||
Channel = UpdateChannel.Alpha,
|
||||
});
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task GotoGithubActionAsync()
|
||||
{
|
||||
await Launcher.LaunchUriAsync(
|
||||
new Uri("https://github.com/babalae/better-genshin-impact/actions/workflows/publish.yml"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user