diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Theme/SettingsStyle.xaml b/src/Snap.Hutao/Snap.Hutao/Control/Theme/SettingsStyle.xaml
index f0182d63..ab5cb42f 100644
--- a/src/Snap.Hutao/Snap.Hutao/Control/Theme/SettingsStyle.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/Control/Theme/SettingsStyle.xaml
@@ -4,6 +4,9 @@
0
0
0
+
+ 120
+
diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
index 66afb624..4dbcbd3e 100644
--- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
+++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
@@ -539,6 +539,9 @@
验证失败
+
+ 验证码已发送至邮箱
+
验证请求过快,请 1 分钟后再试
@@ -1163,6 +1166,18 @@
配置无感验证接口
+
+ 登录胡桃通行证
+
+
+ 注册胡桃通行证
+
+
+ 重置胡桃通行证密码
+
+
+ 注销胡桃通行证账号
+
导出 App
@@ -1925,6 +1940,9 @@
重置密码
+
+ 注销账号的数据将永远丢失,无法恢复
+
请输入邮箱
@@ -2207,8 +2225,50 @@
主页
+
+ 三思而后行
+
+
+ 危险操作
+
+
+ 胡桃云服务到期时间
+
- 胡桃账号
+ 胡桃通行证账号
+
+
+ 您可以无限制使用任何基于胡桃云服务的功能
+
+
+ 已认证的合作开发者
+
+
+ 登录
+
+
+ 退出登录
+
+
+ 您可以无限制的使用任何测试功能
+
+
+ 胡桃开发/运维
+
+
+ 我们有时会向某些用户赠送胡桃云兑换码
+
+
+ 使用兑换码
+
+
+ 注册
+
+
+ 修改密码
+
+
+ 注销账号
在完整阅读原神和胡桃工具箱用户协议后,我选择启用「启动游戏-高级功能」
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs
index a5549861..e035b262 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs
@@ -21,6 +21,7 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions
@@ -55,6 +56,8 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions
public string? GachaLogExpireAt { get => gachaLogExpireAt; set => SetProperty(ref gachaLogExpireAt, value); }
+ public string? GachaLogExpireAtSlim { get => gachaLogExpireAtSlim; set => SetProperty(ref gachaLogExpireAtSlim, value); }
+
///
public HutaoUserOptions Value { get => this; }
@@ -71,6 +74,14 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions
/// 登录失败
///
@@ -94,9 +105,19 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions DateTimeOffset.Now;
}
+ private void ClearUserInfo()
+ {
+ IsLicensedDeveloper = false;
+ IsMaintainer = false;
+ GachaLogExpireAt = null;
+ GachaLogExpireAtSlim = null;
+ IsCloudServiceAllowed = false;
+ }
+
public async ValueTask GetTokenAsync()
{
await initializedTaskCompletionSource.Task.ConfigureAwait(false);
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Navigation/DocumentationProvider.cs b/src/Snap.Hutao/Snap.Hutao/Service/Navigation/DocumentationProvider.cs
index b21f1f62..c8fe5d6a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Navigation/DocumentationProvider.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Navigation/DocumentationProvider.cs
@@ -19,7 +19,6 @@ internal sealed partial class DocumentationProvider : IDocumentationProvider
[typeof(CultivationPage)] = "https://hut.ao/features/develop-plan.html",
[typeof(DailyNotePage)] = "https://hut.ao/features/real-time-notes.html",
[typeof(GachaLogPage)] = "https://hut.ao/features/wish-export.html",
- [typeof(HutaoPassportPage)] = "https://hut.ao/zh/features/hutao-settings.html#%E8%83%A1%E6%A1%83%E5%B8%90%E5%8F%B7",
[typeof(LaunchGamePage)] = "https://hut.ao/features/game-launcher.html",
[typeof(LoginHoyoverseUserPage)] = "https://hut.ao/features/mhy-account-switch.html",
[typeof(LoginMihoyoUserPage)] = "https://hut.ao/features/mhy-account-switch.html",
diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
index e84ef19c..90d98569 100644
--- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
+++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
@@ -150,6 +150,10 @@
+
+
+
+
@@ -163,7 +167,6 @@
-
@@ -302,6 +305,30 @@
+
+
+
+ MSBuild:Compile
+
+
+
+
+
+ MSBuild:Compile
+
+
+
+
+
+ MSBuild:Compile
+
+
+
+
+
+ MSBuild:Compile
+
+
@@ -488,12 +515,6 @@
MSBuild:Compile
-
-
-
- MSBuild:Compile
-
-
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportLoginDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportLoginDialog.xaml
new file mode 100644
index 00000000..3fef6d2f
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportLoginDialog.xaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportLoginDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportLoginDialog.xaml.cs
new file mode 100644
index 00000000..0b24bb6d
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportLoginDialog.xaml.cs
@@ -0,0 +1,28 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.UI.Xaml.Controls;
+
+namespace Snap.Hutao.View.Dialog;
+
+[DependencyProperty("UserName", typeof(string))]
+[DependencyProperty("Password", typeof(string))]
+internal sealed partial class HutaoPassportLoginDialog : ContentDialog
+{
+ private readonly ITaskContext taskContext;
+
+ public HutaoPassportLoginDialog(IServiceProvider serviceProvider)
+ {
+ InitializeComponent();
+
+ taskContext = serviceProvider.GetRequiredService();
+ }
+
+ public async ValueTask> GetInputAsync()
+ {
+ await taskContext.SwitchToMainThreadAsync();
+ ContentDialogResult result = await ShowAsync();
+
+ return new(result is ContentDialogResult.Primary, (UserName, Password));
+ }
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportRegisterDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportRegisterDialog.xaml
new file mode 100644
index 00000000..a826c6da
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportRegisterDialog.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportRegisterDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportRegisterDialog.xaml.cs
new file mode 100644
index 00000000..e9801fcb
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportRegisterDialog.xaml.cs
@@ -0,0 +1,54 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using CommunityToolkit.Common;
+using Microsoft.UI.Xaml.Controls;
+using Snap.Hutao.Service.Notification;
+using Snap.Hutao.Web.Hutao;
+
+namespace Snap.Hutao.View.Dialog;
+
+[DependencyProperty("UserName", typeof(string))]
+[DependencyProperty("Password", typeof(string))]
+[DependencyProperty("VerifyCode", typeof(string))]
+internal sealed partial class HutaoPassportRegisterDialog : ContentDialog
+{
+ private readonly HomaPassportClient homaPassportClient;
+ private readonly IInfoBarService infoBarService;
+ private readonly ITaskContext taskContext;
+
+ public HutaoPassportRegisterDialog(IServiceProvider serviceProvider)
+ {
+ InitializeComponent();
+
+ taskContext = serviceProvider.GetRequiredService();
+ homaPassportClient = serviceProvider.GetRequiredService();
+ infoBarService = serviceProvider.GetRequiredService();
+ }
+
+ public async ValueTask> GetInputAsync()
+ {
+ await taskContext.SwitchToMainThreadAsync();
+ ContentDialogResult result = await ShowAsync();
+
+ return new(result is ContentDialogResult.Primary, (UserName, Password, VerifyCode));
+ }
+
+ [Command("VerifyCommand")]
+ private async Task VerifyAsync()
+ {
+ if (string.IsNullOrEmpty(UserName))
+ {
+ return;
+ }
+
+ if (!UserName.IsEmail())
+ {
+ infoBarService.Warning(SH.ViewModelHutaoPassportEmailNotValidHint);
+ return;
+ }
+
+ HutaoResponse response = await homaPassportClient.VerifyAsync(UserName, false).ConfigureAwait(false);
+ infoBarService.Information(response.GetLocalizationMessage());
+ }
+}
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml
new file mode 100644
index 00000000..70345628
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml.cs
new file mode 100644
index 00000000..c88a0a93
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml.cs
@@ -0,0 +1,54 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using CommunityToolkit.Common;
+using Microsoft.UI.Xaml.Controls;
+using Snap.Hutao.Service.Notification;
+using Snap.Hutao.Web.Hutao;
+
+namespace Snap.Hutao.View.Dialog;
+
+[DependencyProperty("UserName", typeof(string))]
+[DependencyProperty("Password", typeof(string))]
+[DependencyProperty("VerifyCode", typeof(string))]
+internal sealed partial class HutaoPassportResetPasswordDialog : ContentDialog
+{
+ private readonly HomaPassportClient homaPassportClient;
+ private readonly IInfoBarService infoBarService;
+ private readonly ITaskContext taskContext;
+
+ public HutaoPassportResetPasswordDialog(IServiceProvider serviceProvider)
+ {
+ InitializeComponent();
+
+ taskContext = serviceProvider.GetRequiredService();
+ homaPassportClient = serviceProvider.GetRequiredService();
+ infoBarService = serviceProvider.GetRequiredService();
+ }
+
+ public async ValueTask> GetInputAsync()
+ {
+ await taskContext.SwitchToMainThreadAsync();
+ ContentDialogResult result = await ShowAsync();
+
+ return new(result is ContentDialogResult.Primary, (UserName, Password, VerifyCode));
+ }
+
+ [Command("VerifyCommand")]
+ private async Task VerifyAsync()
+ {
+ if (string.IsNullOrEmpty(UserName))
+ {
+ return;
+ }
+
+ if (!UserName.IsEmail())
+ {
+ infoBarService.Warning(SH.ViewModelHutaoPassportEmailNotValidHint);
+ return;
+ }
+
+ HutaoResponse response = await homaPassportClient.VerifyAsync(UserName, false).ConfigureAwait(false);
+ infoBarService.Information(response.GetLocalizationMessage());
+ }
+}
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportUnregisterDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportUnregisterDialog.xaml
new file mode 100644
index 00000000..8b57b94c
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportUnregisterDialog.xaml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportUnregisterDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportUnregisterDialog.xaml.cs
new file mode 100644
index 00000000..bfde38a5
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportUnregisterDialog.xaml.cs
@@ -0,0 +1,28 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.UI.Xaml.Controls;
+
+namespace Snap.Hutao.View.Dialog;
+
+[DependencyProperty("UserName", typeof(string))]
+[DependencyProperty("Password", typeof(string))]
+internal sealed partial class HutaoPassportUnregisterDialog : ContentDialog
+{
+ private readonly ITaskContext taskContext;
+
+ public HutaoPassportUnregisterDialog(IServiceProvider serviceProvider)
+ {
+ InitializeComponent();
+
+ taskContext = serviceProvider.GetRequiredService();
+ }
+
+ public async ValueTask> GetInputAsync()
+ {
+ await taskContext.SwitchToMainThreadAsync();
+ ContentDialogResult result = await ShowAsync();
+
+ return new(result is ContentDialogResult.Primary, (UserName, Password));
+ }
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml
index 4de5f6c8..76fe9c82 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml
@@ -315,25 +315,11 @@
-
-
-
-
-
+ Text="{Binding TimeSpanFormatted}"/>
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/HutaoPassportPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/HutaoPassportPage.xaml
deleted file mode 100644
index 6b5f4802..00000000
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/HutaoPassportPage.xaml
+++ /dev/null
@@ -1,115 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/HutaoPassportPage.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Page/HutaoPassportPage.xaml.cs
deleted file mode 100644
index acb61da6..00000000
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/HutaoPassportPage.xaml.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) DGP Studio. All rights reserved.
-// Licensed under the MIT license.
-
-using Snap.Hutao.Control;
-using Snap.Hutao.ViewModel;
-
-namespace Snap.Hutao.View.Page;
-
-///
-/// 胡桃通行证页面
-///
-internal sealed partial class HutaoPassportPage : ScopedPage
-{
- ///
- /// 构造一个新的胡桃通行证页面
- ///
- public HutaoPassportPage()
- {
- InitializeWith();
- InitializeComponent();
- }
-}
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml
index 1472301e..6c867801 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/SettingPage.xaml
@@ -8,9 +8,9 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:shc="using:Snap.Hutao.Control"
xmlns:shcm="using:Snap.Hutao.Control.Markup"
- xmlns:shv="using:Snap.Hutao.ViewModel"
xmlns:shvc="using:Snap.Hutao.View.Control"
- d:DataContext="{d:DesignInstance shv:SettingViewModel}"
+ xmlns:shvs="using:Snap.Hutao.ViewModel.Setting"
+ d:DataContext="{d:DesignInstance shvs:SettingViewModel}"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
@@ -71,11 +71,10 @@
-
@@ -95,13 +94,62 @@
-
-
+ IsExpanded="True">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-/// 胡桃通行证视图模型
-///
-[ConstructorGenerated]
-[Injection(InjectAs.Scoped)]
-internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel
-{
- private readonly HomaPassportClient homaPassportClient;
- private readonly INavigationService navigationService;
- private readonly HutaoUserOptions hutaoUserOptions;
- private readonly IInfoBarService infoBarService;
- private readonly ITaskContext taskContext;
-
- private string? userName;
- private string? password;
- private string? verifyCode;
-
- ///
- /// 用户名
- ///
- public string? UserName { get => userName; set => SetProperty(ref userName, value); }
-
- ///
- /// 密码
- ///
- public string? Password { get => password; set => SetProperty(ref password, value); }
-
- ///
- /// 验证码
- ///
- public string? VerifyCode { get => verifyCode; set => SetProperty(ref verifyCode, value); }
-
- [Command("RegisterVerifyCommand")]
- private Task RegisterVerifyAsync()
- {
- return VerifyAsync(false).AsTask();
- }
-
- [Command("RegisterCommand")]
- private async Task RegisterAsync()
- {
- if (UserName is null || Password is null || VerifyCode is null)
- {
- return;
- }
-
- Response response = await homaPassportClient.RegisterAsync(UserName, Password, VerifyCode).ConfigureAwait(false);
-
- if (response.IsOk())
- {
- SaveUserNameAndPassword();
- infoBarService.Information(response.Message);
-
- await taskContext.SwitchToMainThreadAsync();
- hutaoUserOptions.LoginSucceed(UserName, response.Data);
-
- await navigationService
- .NavigateAsync(INavigationAwaiter.Default, true)
- .ConfigureAwait(false);
- }
- }
-
- [Command("ResetPasswordVerifyCommand")]
- private Task ResetPasswordVerifyAsync()
- {
- return VerifyAsync(true).AsTask();
- }
-
- [Command("ResetPasswordCommand")]
- private async Task ResetPasswordAsync()
- {
- if (UserName is null || Password is null || VerifyCode is null)
- {
- return;
- }
-
- Response response = await homaPassportClient.ResetPasswordAsync(UserName, Password, VerifyCode).ConfigureAwait(false);
-
- if (response.IsOk())
- {
- SaveUserNameAndPassword();
- infoBarService.Information(response.Message);
-
- await taskContext.SwitchToMainThreadAsync();
- hutaoUserOptions.LoginSucceed(UserName, response.Data);
-
- await navigationService
- .NavigateAsync(INavigationAwaiter.Default, true)
- .ConfigureAwait(false);
- }
- }
-
- [Command("LoginCommand")]
- private async Task LoginAsync()
- {
- if (UserName is null || Password is null)
- {
- return;
- }
-
- Response response = await homaPassportClient.LoginAsync(UserName, Password).ConfigureAwait(false);
-
- if (response.IsOk())
- {
- SaveUserNameAndPassword();
- infoBarService.Information(response.Message);
-
- await taskContext.SwitchToMainThreadAsync();
- hutaoUserOptions.LoginSucceed(UserName, response.Data);
-
- await navigationService
- .NavigateAsync(INavigationAwaiter.Default, true)
- .ConfigureAwait(false);
- }
- }
-
- private async ValueTask VerifyAsync(bool isResetPassword)
- {
- if (string.IsNullOrEmpty(UserName))
- {
- return;
- }
-
- if (!UserName.IsEmail())
- {
- infoBarService.Warning(SH.ViewModelHutaoPassportEmailNotValidHint);
- }
-
- Response response = await homaPassportClient.VerifyAsync(UserName, isResetPassword).ConfigureAwait(false);
- infoBarService.Information(response.Message);
- }
-
- private void SaveUserNameAndPassword()
- {
- if (!string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(Password))
- {
- LocalSetting.Set(SettingKeys.PassportUserName, UserName);
- LocalSetting.Set(SettingKeys.PassportPassword, Password);
- }
- }
-}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/HutaoPassportViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/HutaoPassportViewModel.cs
new file mode 100644
index 00000000..cfc00fbf
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/HutaoPassportViewModel.cs
@@ -0,0 +1,156 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using Snap.Hutao.Core.Setting;
+using Snap.Hutao.Factory.Abstraction;
+using Snap.Hutao.Service.Hutao;
+using Snap.Hutao.Service.Notification;
+using Snap.Hutao.View.Dialog;
+using Snap.Hutao.Web.Hutao;
+using Snap.Hutao.Web.Response;
+using Windows.System;
+
+namespace Snap.Hutao.ViewModel.Setting;
+
+///
+/// 胡桃通行证视图模型
+///
+[ConstructorGenerated]
+[Injection(InjectAs.Scoped)]
+internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel
+{
+ private readonly IContentDialogFactory contentDialogFactory;
+ private readonly HomaPassportClient homaPassportClient;
+ private readonly HutaoUserOptions hutaoUserOptions;
+ private readonly IInfoBarService infoBarService;
+ private readonly ITaskContext taskContext;
+
+ [Command("OpenRedeemWebsiteCommand")]
+ private static async Task OpenRedeemWebsiteAsync()
+ {
+ await Launcher.LaunchUriAsync("https://homa.snapgenshin.com/redeem.html".ToUri());
+ }
+
+ private static void SaveUserNameAndPassword(string username, string password)
+ {
+ LocalSetting.Set(SettingKeys.PassportUserName, username);
+ LocalSetting.Set(SettingKeys.PassportPassword, password);
+ }
+
+ [Command("RegisterCommand")]
+ private async Task RegisterAsync()
+ {
+ HutaoPassportRegisterDialog dialog = await contentDialogFactory.CreateInstanceAsync().ConfigureAwait(false);
+ ValueResult result = await dialog.GetInputAsync().ConfigureAwait(false);
+
+ if (result.IsOk)
+ {
+ (string username, string password, string verifyCode) = result.Value;
+
+ if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(verifyCode))
+ {
+ return;
+ }
+
+ Response response = await homaPassportClient.RegisterAsync(username, password, verifyCode).ConfigureAwait(false);
+
+ if (response.IsOk())
+ {
+ SaveUserNameAndPassword(username, password);
+ infoBarService.Information(response.Message);
+
+ await taskContext.SwitchToMainThreadAsync();
+ hutaoUserOptions.LoginSucceed(username, response.Data);
+ }
+ }
+ }
+
+ [Command("UnregisterCommand")]
+ private async Task UnregisterAsync()
+ {
+ HutaoPassportUnregisterDialog dialog = await contentDialogFactory.CreateInstanceAsync().ConfigureAwait(false);
+ ValueResult result = await dialog.GetInputAsync().ConfigureAwait(false);
+
+ if (result.IsOk)
+ {
+ (string username, string password) = result.Value;
+
+ if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
+ {
+ return;
+ }
+
+ Response response = await homaPassportClient.UnregisterAsync(username, password).ConfigureAwait(false);
+
+ if (response.IsOk())
+ {
+ infoBarService.Information(response.Message);
+
+ await taskContext.SwitchToMainThreadAsync();
+ hutaoUserOptions.LogoutOrUnregister();
+ }
+ }
+ }
+
+ [Command("LoginCommand")]
+ private async Task LoginAsync()
+ {
+ HutaoPassportLoginDialog dialog = await contentDialogFactory.CreateInstanceAsync().ConfigureAwait(false);
+ ValueResult result = await dialog.GetInputAsync().ConfigureAwait(false);
+
+ if (result.IsOk)
+ {
+ (string username, string password) = result.Value;
+
+ if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
+ {
+ return;
+ }
+
+ Response response = await homaPassportClient.LoginAsync(username, password).ConfigureAwait(false);
+
+ if (response.IsOk())
+ {
+ SaveUserNameAndPassword(username, password);
+ infoBarService.Information(response.Message);
+
+ await taskContext.SwitchToMainThreadAsync();
+ hutaoUserOptions.LoginSucceed(username, response.Data);
+ }
+ }
+ }
+
+ [Command("LogoutCommand")]
+ private void LogoutAsync()
+ {
+ hutaoUserOptions.LogoutOrUnregister();
+ }
+
+ [Command("ResetPasswordCommand")]
+ private async Task ResetPasswordAsync()
+ {
+ HutaoPassportResetPasswordDialog dialog = await contentDialogFactory.CreateInstanceAsync().ConfigureAwait(false);
+ ValueResult result = await dialog.GetInputAsync().ConfigureAwait(false);
+
+ if (result.IsOk)
+ {
+ (string username, string password, string verifyCode) = result.Value;
+
+ if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(verifyCode))
+ {
+ return;
+ }
+
+ Response response = await homaPassportClient.ResetPasswordAsync(username, password, verifyCode).ConfigureAwait(false);
+
+ if (response.IsOk())
+ {
+ SaveUserNameAndPassword(username, password);
+ infoBarService.Information(response.Message);
+
+ await taskContext.SwitchToMainThreadAsync();
+ hutaoUserOptions.LoginSucceed(username, response.Data);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingViewModel.cs
similarity index 97%
rename from src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs
rename to src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingViewModel.cs
index f026d392..523b6e96 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/SettingViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingViewModel.cs
@@ -28,7 +28,7 @@ using System.Runtime.InteropServices;
using Windows.Storage.Pickers;
using Windows.System;
-namespace Snap.Hutao.ViewModel;
+namespace Snap.Hutao.ViewModel.Setting;
///
/// 设置视图模型
@@ -45,6 +45,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
private readonly INavigationService navigationService;
private readonly IClipboardInterop clipboardInterop;
private readonly IShellLinkInterop shellLinkInterop;
+ private readonly HutaoPassportViewModel hutaoPassportViewModel;
private readonly HutaoUserOptions hutaoUserOptions;
private readonly IInfoBarService infoBarService;
private readonly RuntimeOptions runtimeOptions;
@@ -73,6 +74,8 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
public HomeCardOptions HomeCardOptions { get => homeCardOptions; }
+ public HutaoPassportViewModel Passport { get => hutaoPassportViewModel; }
+
///
/// 选中的背景类型
///
@@ -227,12 +230,6 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
}
}
- [Command("NavigateToHutaoPassportCommand")]
- private void NavigateToHutaoPassport()
- {
- navigationService.Navigate(INavigationAwaiter.Default);
- }
-
[Command("OpenCacheFolderCommand")]
private Task OpenCacheFolderAsync()
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaPassportClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaPassportClient.cs
index 16a3fe5d..8c813881 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaPassportClient.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaPassportClient.cs
@@ -47,7 +47,7 @@ internal sealed partial class HomaPassportClient
/// 是否重置账号密码
/// 取消令牌
/// 响应
- public async ValueTask VerifyAsync(string email, bool isResetPassword, CancellationToken token = default)
+ public async ValueTask VerifyAsync(string email, bool isResetPassword, CancellationToken token = default)
{
Dictionary data = new()
{
@@ -59,11 +59,11 @@ internal sealed partial class HomaPassportClient
.SetRequestUri(HutaoEndpoints.PassportVerify)
.PostJson(data);
- Response.Response? resp = await builder
- .TryCatchSendAsync(httpClient, logger, token)
+ HutaoResponse? resp = await builder
+ .TryCatchSendAsync(httpClient, logger, token)
.ConfigureAwait(false);
- return Response.Response.DefaultIfNull(resp);
+ return HutaoResponse.DefaultIfNull(resp);
}
///
@@ -74,7 +74,7 @@ internal sealed partial class HomaPassportClient
/// 验证码
/// 取消令牌
/// 响应,包含登录令牌
- public async ValueTask> RegisterAsync(string email, string password, string verifyCode, CancellationToken token = default)
+ public async ValueTask> RegisterAsync(string email, string password, string verifyCode, CancellationToken token = default)
{
Dictionary data = new()
{
@@ -87,11 +87,30 @@ internal sealed partial class HomaPassportClient
.SetRequestUri(HutaoEndpoints.PassportRegister)
.PostJson(data);
- Response? resp = await builder
- .TryCatchSendAsync>(httpClient, logger, token)
+ HutaoResponse? resp = await builder
+ .TryCatchSendAsync>(httpClient, logger, token)
.ConfigureAwait(false);
- return Response.Response.DefaultIfNull(resp);
+ return HutaoResponse.DefaultIfNull(resp);
+ }
+
+ public async ValueTask UnregisterAsync(string email, string password, CancellationToken token = default)
+ {
+ Dictionary data = new()
+ {
+ ["UserName"] = Encrypt(email),
+ ["Password"] = Encrypt(password),
+ };
+
+ HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
+ .SetRequestUri(HutaoEndpoints.PassportCancel)
+ .PostJson(data);
+
+ HutaoResponse? resp = await builder
+ .TryCatchSendAsync(httpClient, logger, token)
+ .ConfigureAwait(false);
+
+ return HutaoResponse.DefaultIfNull(resp);
}
///
@@ -102,7 +121,7 @@ internal sealed partial class HomaPassportClient
/// 验证码
/// 取消令牌
/// 响应,包含登录令牌
- public async ValueTask> ResetPasswordAsync(string email, string password, string verifyCode, CancellationToken token = default)
+ public async ValueTask> ResetPasswordAsync(string email, string password, string verifyCode, CancellationToken token = default)
{
Dictionary data = new()
{
@@ -115,11 +134,11 @@ internal sealed partial class HomaPassportClient
.SetRequestUri(HutaoEndpoints.PassportResetPassword)
.PostJson(data);
- Response? resp = await builder
- .TryCatchSendAsync>(httpClient, logger, token)
+ HutaoResponse? resp = await builder
+ .TryCatchSendAsync>(httpClient, logger, token)
.ConfigureAwait(false);
- return Response.Response.DefaultIfNull(resp);
+ return HutaoResponse.DefaultIfNull(resp);
}
///
@@ -129,7 +148,7 @@ internal sealed partial class HomaPassportClient
/// 密码
/// 取消令牌
/// 响应,包含登录令牌
- public async ValueTask> LoginAsync(string email, string password, CancellationToken token = default)
+ public async ValueTask> LoginAsync(string email, string password, CancellationToken token = default)
{
Dictionary data = new()
{
@@ -141,11 +160,11 @@ internal sealed partial class HomaPassportClient
.SetRequestUri(HutaoEndpoints.PassportLogin)
.PostJson(data);
- Response? resp = await builder
- .TryCatchSendAsync>(httpClient, logger, token)
+ HutaoResponse? resp = await builder
+ .TryCatchSendAsync>(httpClient, logger, token)
.ConfigureAwait(false);
- return Response.Response.DefaultIfNull(resp);
+ return HutaoResponse.DefaultIfNull(resp);
}
///
@@ -153,7 +172,7 @@ internal sealed partial class HomaPassportClient
///
/// 取消令牌
/// 用户信息
- public async ValueTask> GetUserInfoAsync(CancellationToken token = default)
+ public async ValueTask> GetUserInfoAsync(CancellationToken token = default)
{
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(HutaoEndpoints.PassportUserInfo)
@@ -161,11 +180,11 @@ internal sealed partial class HomaPassportClient
await builder.TrySetTokenAsync(hutaoUserOptions).ConfigureAwait(false);
- Response? resp = await builder
- .TryCatchSendAsync>(httpClient, logger, token)
+ HutaoResponse? resp = await builder
+ .TryCatchSendAsync>(httpClient, logger, token)
.ConfigureAwait(false);
- return Response.Response.DefaultIfNull(resp);
+ return HutaoResponse.DefaultIfNull(resp);
}
private static string Encrypt(string text)
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/HutaoEndpoints.cs b/src/Snap.Hutao/Snap.Hutao/Web/HutaoEndpoints.cs
index 86e473a5..ae990650 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/HutaoEndpoints.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/HutaoEndpoints.cs
@@ -102,6 +102,11 @@ internal static class HutaoEndpoints
///
public const string PassportRegister = $"{HomaSnapGenshinApi}/Passport/Register";
+ ///
+ /// 注销账号
+ ///
+ public const string PassportCancel = $"{HomaSnapGenshinApi}/Passport/Cancel";
+
///
/// 重设密码
///