mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
implement #911
This commit is contained in:
@@ -4,6 +4,9 @@
|
||||
<x:Double x:Key="SettingsCardMinHeight">0</x:Double>
|
||||
<x:Double x:Key="SettingsCardWrapThreshold">0</x:Double>
|
||||
<x:Double x:Key="SettingsCardWrapNoIconThreshold">0</x:Double>
|
||||
|
||||
<x:Double x:Key="SettingsCardContentControlMinWidth">120</x:Double>
|
||||
|
||||
<Style
|
||||
x:Key="SettingsSectionHeaderTextBlockStyle"
|
||||
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
|
||||
@@ -16,16 +19,17 @@
|
||||
x:Key="SettingsContentComboBoxStyle"
|
||||
BasedOn="{StaticResource DefaultComboBoxStyle}"
|
||||
TargetType="ComboBox">
|
||||
<Setter Property="MinWidth" Value="120"/>
|
||||
<Setter Property="MinWidth" Value="{ThemeResource SettingsCardContentControlMinWidth}"/>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="SettingButtonStyle"
|
||||
BasedOn="{StaticResource DefaultButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardBorderBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}"/>
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
|
||||
<Setter Property="Padding" Value="16,6,16,6"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
<Setter Property="MinWidth" Value="{ThemeResource SettingsCardContentControlMinWidth}"/>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -539,6 +539,9 @@
|
||||
<data name="ServerPassportVerifyFailed" xml:space="preserve">
|
||||
<value>验证失败</value>
|
||||
</data>
|
||||
<data name="ServerPassportVerifyRequestSuccess" xml:space="preserve">
|
||||
<value>验证码已发送至邮箱</value>
|
||||
</data>
|
||||
<data name="ServerPassportVerifyTooFrequent" xml:space="preserve">
|
||||
<value>验证请求过快,请 1 分钟后再试</value>
|
||||
</data>
|
||||
@@ -1163,6 +1166,18 @@
|
||||
<data name="ViewDialogGeetestCustomUrlTitle" xml:space="preserve">
|
||||
<value>配置无感验证接口</value>
|
||||
</data>
|
||||
<data name="ViewDialogHutaoPassportLoginTitle" xml:space="preserve">
|
||||
<value>登录胡桃通行证</value>
|
||||
</data>
|
||||
<data name="ViewDialogHutaoPassportRegisterTitle" xml:space="preserve">
|
||||
<value>注册胡桃通行证</value>
|
||||
</data>
|
||||
<data name="ViewDialogHutaoPassportResetPasswordTitle" xml:space="preserve">
|
||||
<value>重置胡桃通行证密码</value>
|
||||
</data>
|
||||
<data name="ViewDialogHutaoPassportUnregisterTitle" xml:space="preserve">
|
||||
<value>注销胡桃通行证账号</value>
|
||||
</data>
|
||||
<data name="ViewDialogImportExportApp" xml:space="preserve">
|
||||
<value>导出 App</value>
|
||||
</data>
|
||||
@@ -1925,6 +1940,9 @@
|
||||
<data name="ViewPageHutaoPassportResetPasswordHeader" xml:space="preserve">
|
||||
<value>重置密码</value>
|
||||
</data>
|
||||
<data name="ViewPageHutaoPassportResetPasswordHint" xml:space="preserve">
|
||||
<value>注销账号的数据将永远丢失,无法恢复</value>
|
||||
</data>
|
||||
<data name="ViewPageHutaoPassportUserNameHint" xml:space="preserve">
|
||||
<value>请输入邮箱</value>
|
||||
</data>
|
||||
@@ -2207,8 +2225,50 @@
|
||||
<data name="ViewpageSettingHomeHeader" xml:space="preserve">
|
||||
<value>主页</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportDangerZoneDescription" xml:space="preserve">
|
||||
<value>三思而后行</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportDangerZoneHeader" xml:space="preserve">
|
||||
<value>危险操作</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportGachaLogExpiredAtHeader" xml:space="preserve">
|
||||
<value>胡桃云服务到期时间</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportHeader" xml:space="preserve">
|
||||
<value>胡桃账号</value>
|
||||
<value>胡桃通行证账号</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportLicensedDeveloperDescription" xml:space="preserve">
|
||||
<value>您可以无限制使用任何基于胡桃云服务的功能</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportLicensedDeveloperHeader" xml:space="preserve">
|
||||
<value>已认证的合作开发者</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportLoginAction" xml:space="preserve">
|
||||
<value>登录</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportLogoutAction" xml:space="preserve">
|
||||
<value>退出登录</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportMaintainerDescription" xml:space="preserve">
|
||||
<value>您可以无限制的使用任何测试功能</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportMaintainerHeader" xml:space="preserve">
|
||||
<value>胡桃开发/运维</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportRedeemCodeDescription" xml:space="preserve">
|
||||
<value>我们有时会向某些用户赠送胡桃云兑换码</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportRedeemCodeHeader" xml:space="preserve">
|
||||
<value>使用兑换码</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportRegisterAction" xml:space="preserve">
|
||||
<value>注册</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportResetPasswordAction" xml:space="preserve">
|
||||
<value>修改密码</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingHutaoPassportUnregisterAction" xml:space="preserve">
|
||||
<value>注销账号</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingIsAdvancedLaunchOptionsEnabledDescription" xml:space="preserve">
|
||||
<value>在完整阅读原神和胡桃工具箱用户协议后,我选择启用「启动游戏-高级功能」</value>
|
||||
|
||||
@@ -21,6 +21,7 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions<HutaoUserOpt
|
||||
private bool isHutaoCloudServiceAllowed;
|
||||
private bool isLicensedDeveloper;
|
||||
private string? gachaLogExpireAt;
|
||||
private string? gachaLogExpireAtSlim;
|
||||
private bool isMaintainer;
|
||||
|
||||
/// <summary>
|
||||
@@ -55,6 +56,8 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions<HutaoUserOpt
|
||||
/// </summary>
|
||||
public string? GachaLogExpireAt { get => gachaLogExpireAt; set => SetProperty(ref gachaLogExpireAt, value); }
|
||||
|
||||
public string? GachaLogExpireAtSlim { get => gachaLogExpireAtSlim; set => SetProperty(ref gachaLogExpireAtSlim, value); }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public HutaoUserOptions Value { get => this; }
|
||||
|
||||
@@ -71,6 +74,14 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions<HutaoUserOpt
|
||||
initializedTaskCompletionSource.TrySetResult();
|
||||
}
|
||||
|
||||
public void LogoutOrUnregister()
|
||||
{
|
||||
UserName = null;
|
||||
token = null;
|
||||
IsLoggedIn = false;
|
||||
ClearUserInfo();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 登录失败
|
||||
/// </summary>
|
||||
@@ -94,9 +105,19 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions<HutaoUserOpt
|
||||
IsLicensedDeveloper = userInfo.IsLicensedDeveloper;
|
||||
IsMaintainer = userInfo.IsMaintainer;
|
||||
GachaLogExpireAt = Regex.Unescape(SH.ServiceHutaoUserGachaLogExpiredAt).Format(userInfo.GachaLogExpireAt);
|
||||
GachaLogExpireAtSlim = $"{userInfo.GachaLogExpireAt:yyyy.MM.dd HH:mm:ss}";
|
||||
IsCloudServiceAllowed = IsLicensedDeveloper || userInfo.GachaLogExpireAt > DateTimeOffset.Now;
|
||||
}
|
||||
|
||||
private void ClearUserInfo()
|
||||
{
|
||||
IsLicensedDeveloper = false;
|
||||
IsMaintainer = false;
|
||||
GachaLogExpireAt = null;
|
||||
GachaLogExpireAtSlim = null;
|
||||
IsCloudServiceAllowed = false;
|
||||
}
|
||||
|
||||
public async ValueTask<string?> GetTokenAsync()
|
||||
{
|
||||
await initializedTaskCompletionSource.Task.ConfigureAwait(false);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -150,6 +150,10 @@
|
||||
<None Remove="View\Dialog\GachaLogRefreshProgressDialog.xaml" />
|
||||
<None Remove="View\Dialog\GachaLogUrlDialog.xaml" />
|
||||
<None Remove="View\Dialog\GeetestCustomUrlDialog.xaml" />
|
||||
<None Remove="View\Dialog\HutaoPassportLoginDialog.xaml" />
|
||||
<None Remove="View\Dialog\HutaoPassportRegisterDialog.xaml" />
|
||||
<None Remove="View\Dialog\HutaoPassportResetPasswordDialog.xaml" />
|
||||
<None Remove="View\Dialog\HutaoPassportUnregisterDialog.xaml" />
|
||||
<None Remove="View\Dialog\LaunchGameAccountNameDialog.xaml" />
|
||||
<None Remove="View\Dialog\LaunchGamePackageConvertDialog.xaml" />
|
||||
<None Remove="View\Dialog\UserDialog.xaml" />
|
||||
@@ -163,7 +167,6 @@
|
||||
<None Remove="View\Page\CultivationPage.xaml" />
|
||||
<None Remove="View\Page\DailyNotePage.xaml" />
|
||||
<None Remove="View\Page\GachaLogPage.xaml" />
|
||||
<None Remove="View\Page\HutaoPassportPage.xaml" />
|
||||
<None Remove="View\Page\LaunchGamePage.xaml" />
|
||||
<None Remove="View\Page\LoginMihoyoUserPage.xaml" />
|
||||
<None Remove="View\Page\SettingPage.xaml" />
|
||||
@@ -302,6 +305,30 @@
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="Resource\Localization\SH.resx" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="View\Dialog\HutaoPassportUnregisterDialog.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="View\Dialog\HutaoPassportResetPasswordDialog.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="View\Dialog\HutaoPassportRegisterDialog.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="View\Dialog\HutaoPassportLoginDialog.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="View\Dialog\DailyNoteWebhookDialog.xaml">
|
||||
@@ -488,12 +515,6 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="View\Page\HutaoPassportPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Pages -->
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<ContentDialog
|
||||
x:Class="Snap.Hutao.View.Dialog.HutaoPassportLoginDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
Title="{shcm:ResourceString Name=ViewDialogHutaoPassportLoginTitle}"
|
||||
CloseButtonText="{shcm:ResourceString Name=ContentDialogCancelCloseButtonText}"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonText="{shcm:ResourceString Name=ContentDialogConfirmPrimaryButtonText}"
|
||||
Style="{StaticResource DefaultContentDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel Margin="0,8,0,0">
|
||||
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportUserNameHint}" Text="{x:Bind UserName, Mode=TwoWay}"/>
|
||||
<PasswordBox
|
||||
Margin="0,16,0,0"
|
||||
Password="{x:Bind Password, Mode=TwoWay}"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordHint}"/>
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
@@ -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<ITaskContext>();
|
||||
}
|
||||
|
||||
public async ValueTask<ValueResult<bool, (string UserName, string Passport)>> GetInputAsync()
|
||||
{
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
ContentDialogResult result = await ShowAsync();
|
||||
|
||||
return new(result is ContentDialogResult.Primary, (UserName, Password));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<ContentDialog
|
||||
x:Class="Snap.Hutao.View.Dialog.HutaoPassportRegisterDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
Title="{shcm:ResourceString Name=ViewDialogHutaoPassportRegisterTitle}"
|
||||
CloseButtonText="{shcm:ResourceString Name=ContentDialogCancelCloseButtonText}"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonText="{shcm:ResourceString Name=ContentDialogConfirmPrimaryButtonText}"
|
||||
Style="{StaticResource DefaultContentDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel Margin="0,8,0,0">
|
||||
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportUserNameHint}" Text="{x:Bind UserName, Mode=TwoWay}"/>
|
||||
<Grid Margin="0,16,0,0" ColumnSpacing="16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportVerifyCodeHint}" Text="{x:Bind VerifyCode, Mode=TwoWay}"/>
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Stretch"
|
||||
Command="{x:Bind VerifyCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageHutaoPassportVerifyCodeAction}"/>
|
||||
</Grid>
|
||||
<PasswordBox
|
||||
Margin="0,16,0,0"
|
||||
IsEnabled="{x:Bind VerifyCode, Converter={StaticResource StringBoolConverter}}"
|
||||
Password="{x:Bind Password, Mode=TwoWay}"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordHint}"/>
|
||||
<TextBlock
|
||||
Margin="0,4,0,0"
|
||||
Opacity="0.7"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordRequirementHint}"/>
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
@@ -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<ITaskContext>();
|
||||
homaPassportClient = serviceProvider.GetRequiredService<HomaPassportClient>();
|
||||
infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
}
|
||||
|
||||
public async ValueTask<ValueResult<bool, (string UserName, string Password, string VerifyCode)>> 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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<ContentDialog
|
||||
x:Class="Snap.Hutao.View.Dialog.HutaoPassportResetPasswordDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
Title="{shcm:ResourceString Name=ViewDialogHutaoPassportResetPasswordTitle}"
|
||||
CloseButtonText="{shcm:ResourceString Name=ContentDialogCancelCloseButtonText}"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonText="{shcm:ResourceString Name=ContentDialogConfirmPrimaryButtonText}"
|
||||
Style="{StaticResource DefaultContentDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel>
|
||||
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportUserNameHint}" Text="{x:Bind UserName, Mode=TwoWay}"/>
|
||||
<Grid Margin="0,16,0,0" ColumnSpacing="16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportVerifyCodeHint}" Text="{x:Bind VerifyCode, Mode=TwoWay}"/>
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Stretch"
|
||||
Command="{x:Bind VerifyCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageHutaoPassportVerifyCodeAction}"/>
|
||||
</Grid>
|
||||
<PasswordBox
|
||||
Margin="0,16,0,0"
|
||||
IsEnabled="{x:Bind VerifyCode, Converter={StaticResource StringBoolConverter}}"
|
||||
Password="{x:Bind Password, Mode=TwoWay}"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordHint}"/>
|
||||
<TextBlock
|
||||
Margin="0,4,0,0"
|
||||
Opacity="0.7"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordRequirementHint}"/>
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
@@ -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<ITaskContext>();
|
||||
homaPassportClient = serviceProvider.GetRequiredService<HomaPassportClient>();
|
||||
infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
}
|
||||
|
||||
public async ValueTask<ValueResult<bool, (string UserName, string Passport, string VerifyCode)>> 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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<ContentDialog
|
||||
x:Class="Snap.Hutao.View.Dialog.HutaoPassportUnregisterDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
Title="{shcm:ResourceString Name=ViewDialogHutaoPassportUnregisterTitle}"
|
||||
CloseButtonText="{shcm:ResourceString Name=ContentDialogCancelCloseButtonText}"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonText="{shcm:ResourceString Name=ContentDialogConfirmPrimaryButtonText}"
|
||||
Style="{StaticResource DefaultContentDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel Margin="0,8,0,0">
|
||||
<InfoBar
|
||||
Title="{shcm:ResourceString Name=ViewPageHutaoPassportResetPasswordHint}"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
Severity="Error"/>
|
||||
<TextBox
|
||||
Margin="0,16,0,0"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportUserNameHint}"
|
||||
Text="{x:Bind UserName, Mode=TwoWay}"/>
|
||||
<PasswordBox
|
||||
Margin="0,16,0,0"
|
||||
Password="{x:Bind Password, Mode=TwoWay}"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordHint}"/>
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
@@ -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<ITaskContext>();
|
||||
}
|
||||
|
||||
public async ValueTask<ValueResult<bool, (string UserName, string Passport)>> GetInputAsync()
|
||||
{
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
ContentDialogResult result = await ShowAsync();
|
||||
|
||||
return new(result is ContentDialogResult.Primary, (UserName, Password));
|
||||
}
|
||||
}
|
||||
@@ -315,25 +315,11 @@
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<StackPanel
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Margin="0,6,0,8"
|
||||
Opacity="0.6"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Left"
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text="{Binding FromFormatted}"/>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text=" - "/>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Left"
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text="{Binding ToFormatted}"/>
|
||||
</StackPanel>
|
||||
Text="{Binding TimeSpanFormatted}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
<shc:ScopedPage
|
||||
x:Class="Snap.Hutao.View.Page.HutaoPassportPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
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"
|
||||
d:DataContext="{d:DesignInstance shv:HutaoPassportViewModel}"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<TextBlock
|
||||
Style="{StaticResource SubtitleTextBlockStyle}"
|
||||
Text="{shcm:ResourceString Name=ViewPageSettingHutaoPassportHeader}"
|
||||
TextAlignment="Center"/>
|
||||
<Border
|
||||
Margin="0,16,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
Style="{StaticResource BorderCardStyle}">
|
||||
<Pivot
|
||||
Width="360"
|
||||
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}">
|
||||
<PivotItem Header="{shcm:ResourceString Name=ViewPageHutaoPassportLoginHeader}">
|
||||
<StackPanel Margin="16">
|
||||
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportUserNameHint}" Text="{Binding UserName, Mode=TwoWay}"/>
|
||||
<PasswordBox
|
||||
Margin="0,16,0,0"
|
||||
Password="{Binding Password, Mode=TwoWay}"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordHint}"/>
|
||||
<Button
|
||||
Margin="0,16,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding LoginCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageHutaoPassportLoginHeader}"
|
||||
Style="{ThemeResource AccentButtonStyle}"/>
|
||||
</StackPanel>
|
||||
</PivotItem>
|
||||
<PivotItem Header="{shcm:ResourceString Name=ViewPageHutaoPassportRegisterHeader}">
|
||||
<StackPanel Margin="16">
|
||||
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportUserNameHint}" Text="{Binding UserName, Mode=TwoWay}"/>
|
||||
<Grid Margin="0,16,0,0" ColumnSpacing="16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportVerifyCodeHint}" Text="{Binding VerifyCode, Mode=TwoWay}"/>
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Stretch"
|
||||
Command="{Binding RegisterVerifyCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageHutaoPassportVerifyCodeAction}"/>
|
||||
</Grid>
|
||||
<PasswordBox
|
||||
Margin="0,16,0,0"
|
||||
IsEnabled="{Binding VerifyCode, Converter={StaticResource StringBoolConverter}}"
|
||||
Password="{Binding Password, Mode=TwoWay}"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordHint}"/>
|
||||
<TextBlock
|
||||
Margin="0,4,0,0"
|
||||
Opacity="0.7"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordRequirementHint}"/>
|
||||
<Button
|
||||
Margin="0,16,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding RegisterCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageHutaoPassportRegisterHeader}"
|
||||
IsEnabled="{Binding VerifyCode, Converter={StaticResource StringBoolConverter}}"
|
||||
Style="{ThemeResource AccentButtonStyle}"/>
|
||||
</StackPanel>
|
||||
</PivotItem>
|
||||
<PivotItem Header="{shcm:ResourceString Name=ViewPageHutaoPassportResetPasswordHeader}">
|
||||
<StackPanel Margin="16">
|
||||
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportUserNameHint}" Text="{Binding UserName, Mode=TwoWay}"/>
|
||||
<Grid Margin="0,16,0,0" ColumnSpacing="16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportVerifyCodeHint}" Text="{Binding VerifyCode, Mode=TwoWay}"/>
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Stretch"
|
||||
Command="{Binding ResetPasswordVerifyCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageHutaoPassportVerifyCodeAction}"/>
|
||||
</Grid>
|
||||
<PasswordBox
|
||||
Margin="0,16,0,0"
|
||||
IsEnabled="{Binding VerifyCode, Converter={StaticResource StringBoolConverter}}"
|
||||
Password="{Binding Password, Mode=TwoWay}"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordHint}"/>
|
||||
<TextBlock
|
||||
Margin="0,4,0,0"
|
||||
Opacity="0.7"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{shcm:ResourceString Name=ViewPageHutaoPassportPasswordRequirementHint}"/>
|
||||
<Button
|
||||
Margin="0,16,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding ResetPasswordCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageHutaoPassportResetPasswordHeader}"
|
||||
IsEnabled="{Binding VerifyCode, Converter={StaticResource StringBoolConverter}}"
|
||||
Style="{ThemeResource AccentButtonStyle}"/>
|
||||
</StackPanel>
|
||||
</PivotItem>
|
||||
</Pivot>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</shc:ScopedPage>
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 胡桃通行证页面
|
||||
/// </summary>
|
||||
internal sealed partial class HutaoPassportPage : ScopedPage
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的胡桃通行证页面
|
||||
/// </summary>
|
||||
public HutaoPassportPage()
|
||||
{
|
||||
InitializeWith<HutaoPassportViewModel>();
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -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">
|
||||
<ScrollViewer>
|
||||
@@ -71,11 +71,10 @@
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Margin="0,4"
|
||||
Text="Copyright © 2022 - 2023 DGP Studio. All Rights Reserved."
|
||||
Text="Copyright © 2022 - 2024 DGP Studio. All Rights Reserved."
|
||||
TextWrapping="Wrap"/>
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingAboutHeader}"/>
|
||||
@@ -95,13 +94,62 @@
|
||||
<cwc:SettingsCard Description="{Binding HutaoOptions.WebView2Version}" Header="{shcm:ResourceString Name=ViewPageSettingWebview2Header}"/>
|
||||
</cwc:SettingsExpander.Items>
|
||||
</cwc:SettingsExpander>
|
||||
<cwc:SettingsCard
|
||||
Command="{Binding NavigateToHutaoPassportCommand}"
|
||||
<cwc:SettingsExpander
|
||||
Description="{Binding UserOptions.UserName}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
IsClickEnabled="True"/>
|
||||
|
||||
IsExpanded="True">
|
||||
<StackPanel Orientation="Horizontal" Spacing="16">
|
||||
<Button
|
||||
Command="{Binding Passport.LoginCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageSettingHutaoPassportLoginAction}"
|
||||
Style="{ThemeResource SettingButtonStyle}"
|
||||
Visibility="{Binding UserOptions.IsLoggedIn, Converter={StaticResource BoolToVisibilityRevertConverter}}"/>
|
||||
<Button
|
||||
Command="{Binding Passport.RegisterCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageSettingHutaoPassportRegisterAction}"
|
||||
Style="{ThemeResource SettingButtonStyle}"
|
||||
Visibility="{Binding UserOptions.IsLoggedIn, Converter={StaticResource BoolToVisibilityRevertConverter}}"/>
|
||||
<Button
|
||||
Command="{Binding Passport.LogoutCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageSettingHutaoPassportLogoutAction}"
|
||||
Style="{ThemeResource SettingButtonStyle}"
|
||||
Visibility="{Binding UserOptions.IsLoggedIn, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
</StackPanel>
|
||||
<cwc:SettingsExpander.Items>
|
||||
<cwc:SettingsCard
|
||||
Background="{ThemeResource SystemFillColorSuccessBackgroundBrush}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingHutaoPassportLicensedDeveloperDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportLicensedDeveloperHeader}"
|
||||
Visibility="{Binding UserOptions.IsLicensedDeveloper, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
<cwc:SettingsCard
|
||||
Background="{ThemeResource SystemFillColorSuccessBackgroundBrush}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingHutaoPassportMaintainerDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportMaintainerHeader}"
|
||||
Visibility="{Binding UserOptions.IsMaintainer, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
<cwc:SettingsCard Description="{Binding UserOptions.GachaLogExpireAtSlim}" Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportGachaLogExpiredAtHeader}"/>
|
||||
<cwc:SettingsCard
|
||||
Command="{Binding Passport.OpenRedeemWebsiteCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingHutaoPassportRedeemCodeDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportRedeemCodeHeader}"
|
||||
IsClickEnabled="True"/>
|
||||
<cwc:SettingsCard
|
||||
Background="{ThemeResource SystemFillColorCriticalBackgroundBrush}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingHutaoPassportDangerZoneDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportDangerZoneHeader}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="16">
|
||||
<Button
|
||||
Command="{Binding Passport.ResetPasswordCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageSettingHutaoPassportResetPasswordAction}"
|
||||
Style="{ThemeResource SettingButtonStyle}"/>
|
||||
<Button
|
||||
Command="{Binding Passport.UnregisterCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewPageSettingHutaoPassportUnregisterAction}"
|
||||
Style="{ThemeResource SettingButtonStyle}"/>
|
||||
</StackPanel>
|
||||
</cwc:SettingsCard>
|
||||
</cwc:SettingsExpander.Items>
|
||||
</cwc:SettingsExpander>
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingGeetestVerificationHeader}"/>
|
||||
<cwc:SettingsCard
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Control;
|
||||
using Snap.Hutao.ViewModel;
|
||||
using Snap.Hutao.ViewModel.Setting;
|
||||
|
||||
namespace Snap.Hutao.View.Page;
|
||||
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Common;
|
||||
using Snap.Hutao.Core.Setting;
|
||||
using Snap.Hutao.Service.Hutao;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Snap.Hutao.Service.Notification;
|
||||
using Snap.Hutao.Web.Hutao;
|
||||
using Snap.Hutao.Web.Response;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
/// <summary>
|
||||
/// 胡桃通行证视图模型
|
||||
/// </summary>
|
||||
[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;
|
||||
|
||||
/// <summary>
|
||||
/// 用户名
|
||||
/// </summary>
|
||||
public string? UserName { get => userName; set => SetProperty(ref userName, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
public string? Password { get => password; set => SetProperty(ref password, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 验证码
|
||||
/// </summary>
|
||||
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<string> 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<View.Page.SettingPage>(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<string> 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<View.Page.SettingPage>(INavigationAwaiter.Default, true)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[Command("LoginCommand")]
|
||||
private async Task LoginAsync()
|
||||
{
|
||||
if (UserName is null || Password is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Response<string> 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<View.Page.SettingPage>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 胡桃通行证视图模型
|
||||
/// </summary>
|
||||
[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<HutaoPassportRegisterDialog>().ConfigureAwait(false);
|
||||
ValueResult<bool, (string UserName, string Password, string VerifyCode)> 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<string> 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<HutaoPassportUnregisterDialog>().ConfigureAwait(false);
|
||||
ValueResult<bool, (string UserName, string Password)> 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<HutaoPassportLoginDialog>().ConfigureAwait(false);
|
||||
ValueResult<bool, (string UserName, string Password)> result = await dialog.GetInputAsync().ConfigureAwait(false);
|
||||
|
||||
if (result.IsOk)
|
||||
{
|
||||
(string username, string password) = result.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Response<string> 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<HutaoPassportResetPasswordDialog>().ConfigureAwait(false);
|
||||
ValueResult<bool, (string UserName, string Password, string VerifyCode)> 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<string> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ using System.Runtime.InteropServices;
|
||||
using Windows.Storage.Pickers;
|
||||
using Windows.System;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
namespace Snap.Hutao.ViewModel.Setting;
|
||||
|
||||
/// <summary>
|
||||
/// 设置视图模型
|
||||
@@ -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; }
|
||||
|
||||
/// <summary>
|
||||
/// 选中的背景类型
|
||||
/// </summary>
|
||||
@@ -227,12 +230,6 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
[Command("NavigateToHutaoPassportCommand")]
|
||||
private void NavigateToHutaoPassport()
|
||||
{
|
||||
navigationService.Navigate<View.Page.HutaoPassportPage>(INavigationAwaiter.Default);
|
||||
}
|
||||
|
||||
[Command("OpenCacheFolderCommand")]
|
||||
private Task OpenCacheFolderAsync()
|
||||
{
|
||||
@@ -47,7 +47,7 @@ internal sealed partial class HomaPassportClient
|
||||
/// <param name="isResetPassword">是否重置账号密码</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>响应</returns>
|
||||
public async ValueTask<Response.Response> VerifyAsync(string email, bool isResetPassword, CancellationToken token = default)
|
||||
public async ValueTask<HutaoResponse> VerifyAsync(string email, bool isResetPassword, CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, object> data = new()
|
||||
{
|
||||
@@ -59,11 +59,11 @@ internal sealed partial class HomaPassportClient
|
||||
.SetRequestUri(HutaoEndpoints.PassportVerify)
|
||||
.PostJson(data);
|
||||
|
||||
Response.Response? resp = await builder
|
||||
.TryCatchSendAsync<Response.Response>(httpClient, logger, token)
|
||||
HutaoResponse? resp = await builder
|
||||
.TryCatchSendAsync<HutaoResponse>(httpClient, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
return HutaoResponse.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -74,7 +74,7 @@ internal sealed partial class HomaPassportClient
|
||||
/// <param name="verifyCode">验证码</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>响应,包含登录令牌</returns>
|
||||
public async ValueTask<Response<string>> RegisterAsync(string email, string password, string verifyCode, CancellationToken token = default)
|
||||
public async ValueTask<HutaoResponse<string>> RegisterAsync(string email, string password, string verifyCode, CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, string> data = new()
|
||||
{
|
||||
@@ -87,11 +87,30 @@ internal sealed partial class HomaPassportClient
|
||||
.SetRequestUri(HutaoEndpoints.PassportRegister)
|
||||
.PostJson(data);
|
||||
|
||||
Response<string>? resp = await builder
|
||||
.TryCatchSendAsync<Response<string>>(httpClient, logger, token)
|
||||
HutaoResponse<string>? resp = await builder
|
||||
.TryCatchSendAsync<HutaoResponse<string>>(httpClient, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
return HutaoResponse.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
public async ValueTask<HutaoResponse> UnregisterAsync(string email, string password, CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, string> data = new()
|
||||
{
|
||||
["UserName"] = Encrypt(email),
|
||||
["Password"] = Encrypt(password),
|
||||
};
|
||||
|
||||
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
|
||||
.SetRequestUri(HutaoEndpoints.PassportCancel)
|
||||
.PostJson(data);
|
||||
|
||||
HutaoResponse? resp = await builder
|
||||
.TryCatchSendAsync<HutaoResponse>(httpClient, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return HutaoResponse.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -102,7 +121,7 @@ internal sealed partial class HomaPassportClient
|
||||
/// <param name="verifyCode">验证码</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>响应,包含登录令牌</returns>
|
||||
public async ValueTask<Response<string>> ResetPasswordAsync(string email, string password, string verifyCode, CancellationToken token = default)
|
||||
public async ValueTask<HutaoResponse<string>> ResetPasswordAsync(string email, string password, string verifyCode, CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, string> data = new()
|
||||
{
|
||||
@@ -115,11 +134,11 @@ internal sealed partial class HomaPassportClient
|
||||
.SetRequestUri(HutaoEndpoints.PassportResetPassword)
|
||||
.PostJson(data);
|
||||
|
||||
Response<string>? resp = await builder
|
||||
.TryCatchSendAsync<Response<string>>(httpClient, logger, token)
|
||||
HutaoResponse<string>? resp = await builder
|
||||
.TryCatchSendAsync<HutaoResponse<string>>(httpClient, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
return HutaoResponse.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -129,7 +148,7 @@ internal sealed partial class HomaPassportClient
|
||||
/// <param name="password">密码</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>响应,包含登录令牌</returns>
|
||||
public async ValueTask<Response<string>> LoginAsync(string email, string password, CancellationToken token = default)
|
||||
public async ValueTask<HutaoResponse<string>> LoginAsync(string email, string password, CancellationToken token = default)
|
||||
{
|
||||
Dictionary<string, string> data = new()
|
||||
{
|
||||
@@ -141,11 +160,11 @@ internal sealed partial class HomaPassportClient
|
||||
.SetRequestUri(HutaoEndpoints.PassportLogin)
|
||||
.PostJson(data);
|
||||
|
||||
Response<string>? resp = await builder
|
||||
.TryCatchSendAsync<Response<string>>(httpClient, logger, token)
|
||||
HutaoResponse<string>? resp = await builder
|
||||
.TryCatchSendAsync<HutaoResponse<string>>(httpClient, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
return HutaoResponse.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -153,7 +172,7 @@ internal sealed partial class HomaPassportClient
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>用户信息</returns>
|
||||
public async ValueTask<Response<UserInfo>> GetUserInfoAsync(CancellationToken token = default)
|
||||
public async ValueTask<HutaoResponse<UserInfo>> 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<UserInfo>? resp = await builder
|
||||
.TryCatchSendAsync<Response<UserInfo>>(httpClient, logger, token)
|
||||
HutaoResponse<UserInfo>? resp = await builder
|
||||
.TryCatchSendAsync<HutaoResponse<UserInfo>>(httpClient, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
return HutaoResponse.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
private static string Encrypt(string text)
|
||||
|
||||
@@ -102,6 +102,11 @@ internal static class HutaoEndpoints
|
||||
/// </summary>
|
||||
public const string PassportRegister = $"{HomaSnapGenshinApi}/Passport/Register";
|
||||
|
||||
/// <summary>
|
||||
/// 注销账号
|
||||
/// </summary>
|
||||
public const string PassportCancel = $"{HomaSnapGenshinApi}/Passport/Cancel";
|
||||
|
||||
/// <summary>
|
||||
/// 重设密码
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user