add hutao passport

This commit is contained in:
DismissedLight
2023-03-29 17:35:43 +08:00
parent 0a7bd55dab
commit 98b3f2d202
15 changed files with 527 additions and 24 deletions

View File

@@ -102,6 +102,7 @@
<shvc:EmptyObjectToVisibilityRevertConverter x:Key="EmptyObjectToVisibilityRevertConverter"/>
<shvc:Int32ToVisibilityConverter x:Key="Int32ToVisibilityConverter"/>
<shvc:Int32ToVisibilityRevertConverter x:Key="Int32ToVisibilityRevertConverter"/>
<shvc:StringBoolConverter x:Key="StringBoolConverter"/>
<!-- Styles -->
<Style

View File

@@ -28,4 +28,9 @@ internal static class BoxedValues
/// <see cref="true"/>
/// </summary>
public static readonly object True = true;
/// <summary>
/// <see cref="false"/>
/// </summary>
public static readonly object False = false;
}

View File

@@ -7,6 +7,7 @@ using Microsoft.Windows.AppLifecycle;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.DailyNote;
using Snap.Hutao.Service.Hutao;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Service.Navigation;
using System.Diagnostics;
@@ -182,15 +183,23 @@ internal static class Activation
private static async Task WaitMainWindowAsync()
{
await ThreadHelper.SwitchToMainThreadAsync();
Ioc.Default.GetRequiredService<MainWindow>().Activate();
IServiceProvider serviceProvider = Ioc.Default;
await Ioc.Default.GetRequiredService<IInfoBarService>().WaitInitializationAsync().ConfigureAwait(false);
serviceProvider.GetRequiredService<MainWindow>().Activate();
Ioc.Default
await serviceProvider.GetRequiredService<IInfoBarService>().WaitInitializationAsync().ConfigureAwait(false);
serviceProvider
.GetRequiredService<IMetadataService>()
.As<IMetadataServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
serviceProvider
.GetRequiredService<IHutaoUserService>()
.As<IHutaoUserServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
}
private static async Task HandleUrlActivationAsync(Uri uri, bool isRedirected)

View File

@@ -3606,6 +3606,69 @@ namespace Snap.Hutao.Resource.Localization {
}
}
/// <summary>
/// 查找类似 登录 的本地化字符串。
/// </summary>
internal static string ViewPageHutaoPassportLoginHeader {
get {
return ResourceManager.GetString("ViewPageHutaoPassportLoginHeader", resourceCulture);
}
}
/// <summary>
/// 查找类似 请输入密码 的本地化字符串。
/// </summary>
internal static string ViewPageHutaoPassportPasswordHint {
get {
return ResourceManager.GetString("ViewPageHutaoPassportPasswordHint", resourceCulture);
}
}
/// <summary>
/// 查找类似 注册 的本地化字符串。
/// </summary>
internal static string ViewPageHutaoPassportRegisterHeader {
get {
return ResourceManager.GetString("ViewPageHutaoPassportRegisterHeader", resourceCulture);
}
}
/// <summary>
/// 查找类似 重置密码 的本地化字符串。
/// </summary>
internal static string ViewPageHutaoPassportResetPasswordHeader {
get {
return ResourceManager.GetString("ViewPageHutaoPassportResetPasswordHeader", resourceCulture);
}
}
/// <summary>
/// 查找类似 请输入邮箱 的本地化字符串。
/// </summary>
internal static string ViewPageHutaoPassportUserNameHint {
get {
return ResourceManager.GetString("ViewPageHutaoPassportUserNameHint", resourceCulture);
}
}
/// <summary>
/// 查找类似 获取验证码 的本地化字符串。
/// </summary>
internal static string ViewPageHutaoPassportVerifyCodeAction {
get {
return ResourceManager.GetString("ViewPageHutaoPassportVerifyCodeAction", resourceCulture);
}
}
/// <summary>
/// 查找类似 请输入验证码 的本地化字符串。
/// </summary>
internal static string ViewPageHutaoPassportVerifyCodeHint {
get {
return ResourceManager.GetString("ViewPageHutaoPassportVerifyCodeHint", resourceCulture);
}
}
/// <summary>
/// 查找类似 启动游戏 的本地化字符串。
/// </summary>

View File

@@ -1821,4 +1821,25 @@
<data name="ViewUserCookieOperation2" xml:space="preserve">
<value>HoYoLab</value>
</data>
<data name="ViewPageHutaoPassportLoginHeader" xml:space="preserve">
<value>登录</value>
</data>
<data name="ViewPageHutaoPassportPasswordHint" xml:space="preserve">
<value>请输入密码</value>
</data>
<data name="ViewPageHutaoPassportRegisterHeader" xml:space="preserve">
<value>注册</value>
</data>
<data name="ViewPageHutaoPassportResetPasswordHeader" xml:space="preserve">
<value>重置密码</value>
</data>
<data name="ViewPageHutaoPassportUserNameHint" xml:space="preserve">
<value>请输入邮箱</value>
</data>
<data name="ViewPageHutaoPassportVerifyCodeAction" xml:space="preserve">
<value>获取验证码</value>
</data>
<data name="ViewPageHutaoPassportVerifyCodeHint" xml:space="preserve">
<value>请输入验证码</value>
</data>
</root>

View File

@@ -0,0 +1,30 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.Extensions.Options;
namespace Snap.Hutao.Service.Hutao;
/// <summary>
/// 胡桃用户选项
/// </summary>
[Injection(InjectAs.Singleton)]
internal sealed class HutaoUserOptions : ObservableObject, IOptions<HutaoUserOptions>
{
private string? userName;
private string? token;
/// <summary>
/// 用户名
/// </summary>
public string? UserName { get => userName; set => SetProperty(ref userName, value); }
/// <summary>
/// 访问令牌
/// </summary>
public string? Token { get => token; set => SetProperty(ref token, value); }
/// <inheritdoc/>
public HutaoUserOptions Value { get => this; }
}

View File

@@ -12,30 +12,24 @@ namespace Snap.Hutao.Service.Hutao;
[Injection(InjectAs.Singleton, typeof(IHutaoUserService))]
internal sealed class HutaoUserService : IHutaoUserService, IHutaoUserServiceInitialization
{
private readonly HomaPassportClient passportClient;
private readonly TaskCompletionSource initializeCompletionSource = new();
private readonly HomaPassportClient passportClient;
private readonly HutaoUserOptions options;
private bool isInitialized;
/// <summary>
/// 构造一个新的胡桃用户服务
/// </summary>
/// <param name="passportClient">通行证客户端</param>
public HutaoUserService(HomaPassportClient passportClient)
/// <param name="options">选项</param>
public HutaoUserService(HomaPassportClient passportClient, HutaoUserOptions options)
{
this.passportClient = passportClient;
this.options = options;
}
/// <summary>
/// 用户名
/// </summary>
public string? UserName { get; private set; }
/// <summary>
/// 访问令牌
/// </summary>
public string? Token { get; private set; }
/// <summary>
/// 异步初始化
/// </summary>
@@ -52,26 +46,30 @@ internal sealed class HutaoUserService : IHutaoUserService, IHutaoUserServiceIni
string userName = LocalSetting.Get(SettingKeys.PassportUserName, string.Empty);
string passport = LocalSetting.Get(SettingKeys.PassportPassword, string.Empty);
string? accessToken = null;
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(passport))
{
Web.Response.Response<string> response = await passportClient.LoginAsync(userName, passport, token).ConfigureAwait(false);
if (response.IsOk())
{
Token = response.Data;
UserName = userName;
isInitialized = true;
}
else
{
UserName = SH.ViewServiceHutaoUserLoginFailHint;
userName = SH.ViewServiceHutaoUserLoginFailHint;
}
}
else
{
UserName = SH.ViewServiceHutaoUserLoginOrRegisterHint;
userName = SH.ViewServiceHutaoUserLoginOrRegisterHint;
}
await ThreadHelper.SwitchToMainThreadAsync();
options.Token = accessToken;
options.UserName = userName;
initializeCompletionSource.TrySetResult();
}
}

View File

@@ -136,6 +136,7 @@
<None Remove="View\Page\DailyNotePage.xaml" />
<None Remove="View\Page\GachaLogPage.xaml" />
<None Remove="View\Page\HutaoDatabasePage.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" />
@@ -287,6 +288,12 @@
<LastGenOutput>SH.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Page Update="View\Page\HutaoPassportPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<!-- Pages -->
<ItemGroup>

View File

@@ -20,4 +20,4 @@ internal sealed class EmptyObjectToVisibilityRevertConverter : EmptyObjectToObje
EmptyValue = Visibility.Visible;
NotEmptyValue = Visibility.Collapsed;
}
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.UI.Converters;
using Snap.Hutao.Control;
namespace Snap.Hutao.View.Converter;
/// <summary>
/// 字符串空检查转换器
/// </summary>
internal sealed class StringBoolConverter : EmptyStringToObjectConverter
{
/// <summary>
/// 构造一个新的字符串空检查转换器
/// </summary>
public StringBoolConverter()
{
EmptyValue = BoxedValues.False;
NotEmptyValue = BoxedValues.True;
}
}

View File

@@ -0,0 +1,105 @@
<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 CompatCornerRadius}">
<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}"/>
<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}"/>
<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>

View File

@@ -0,0 +1,22 @@
// 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>
/// <20><><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>֤ҳ<D6A4><D2B3>
/// </summary>
internal sealed partial class HutaoPassportPage : ScopedPage
{
/// <summary>
/// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>µĺ<C2B5><C4BA><EFBFBD>ͨ<EFBFBD><CDA8>֤ҳ<D6A4><D2B3>
/// </summary>
public HutaoPassportPage()
{
InitializeWith<HutaoPassportViewModel>();
InitializeComponent();
}
}

View File

@@ -73,9 +73,11 @@
Header="{shcm:ResourceString Name=AppName}"
HeaderIcon="{shcm:FontIcon Glyph=&#xECAA;}"/>
<clw:SettingsCard
Description="{Binding AppVersion}"
Command="{Binding NavigateToHutaoPassportCommand}"
Description="{Binding UserOptions.UserName}"
Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE716;}"/>
HeaderIcon="{shcm:FontIcon Glyph=&#xE716;}"
IsClickEnabled="True"/>
<clw:SettingsCard
ActionIcon="{shcm:FontIcon Glyph=&#xE8C8;}"
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingCopyDeviceIdAction}"

View File

@@ -0,0 +1,196 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.Input;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.Hutao;
using Snap.Hutao.Service.Navigation;
using Snap.Hutao.Web.Hutao;
using Snap.Hutao.Web.Response;
namespace Snap.Hutao.ViewModel;
/// <summary>
/// 胡桃通行证视图模型
/// </summary>
[Injection(InjectAs.Scoped)]
internal sealed class HutaoPassportViewModel : Abstraction.ViewModel
{
private readonly IServiceProvider serviceProvider;
private readonly HomaPassportClient homaPassportClient;
private string? userName;
private string? password;
private string? verifyCode;
/// <summary>
/// 构造一个新的胡桃通行证视图模型
/// </summary>
/// <param name="serviceProvider">服务提供器</param>
public HutaoPassportViewModel(IServiceProvider serviceProvider)
{
homaPassportClient = serviceProvider.GetRequiredService<HomaPassportClient>();
this.serviceProvider = serviceProvider;
RegisterVerifyCommand = new AsyncRelayCommand(RegisterVerifyAsync);
RegisterCommand = new AsyncRelayCommand(RegisterAsync);
ResetPasswordVerifyCommand = new AsyncRelayCommand(ResetPasswordVerifyAsync);
ResetPasswordCommand = new AsyncRelayCommand(ResetPasswordAsync);
LoginCommand = new AsyncRelayCommand(LoginAsync);
}
/// <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); }
/// <summary>
/// 注册验证命令
/// </summary>
public ICommand RegisterVerifyCommand { get; }
/// <summary>
/// 注册命令
/// </summary>
public ICommand RegisterCommand { get; }
/// <summary>
/// 注册验证命令
/// </summary>
public ICommand ResetPasswordVerifyCommand { get; }
/// <summary>
/// 注册命令
/// </summary>
public ICommand ResetPasswordCommand { get; }
/// <summary>
/// 登录命令
/// </summary>
public ICommand LoginCommand { get; }
/// <inheritdoc/>
protected override Task OpenUIAsync()
{
return Task.CompletedTask;
}
private Task RegisterVerifyAsync()
{
return VerifyAsync(false);
}
private async Task RegisterAsync()
{
if (UserName == null || Password == null || VerifyCode == null)
{
return;
}
Response<string> response = await homaPassportClient.RegisterAsync(UserName, Password, VerifyCode).ConfigureAwait(false);
if (response.IsOk())
{
SaveUserNameAndPassword();
serviceProvider.GetRequiredService<IInfoBarService>().Information(response.Message);
HutaoUserOptions options = serviceProvider.GetRequiredService<HutaoUserOptions>();
await ThreadHelper.SwitchToMainThreadAsync();
options.UserName = UserName;
options.Token = response.Data;
await serviceProvider
.GetRequiredService<INavigationService>()
.NavigateAsync<View.Page.SettingPage>(INavigationAwaiter.Default, true)
.ConfigureAwait(false);
}
}
private Task ResetPasswordVerifyAsync()
{
return VerifyAsync(true);
}
private async Task ResetPasswordAsync()
{
if (UserName == null || Password == null || VerifyCode == null)
{
return;
}
Response<string> response = await homaPassportClient.ResetPasswordAsync(UserName, Password, VerifyCode).ConfigureAwait(false);
if (response.IsOk())
{
SaveUserNameAndPassword();
serviceProvider.GetRequiredService<IInfoBarService>().Information(response.Message);
HutaoUserOptions options = serviceProvider.GetRequiredService<HutaoUserOptions>();
await ThreadHelper.SwitchToMainThreadAsync();
options.UserName = UserName;
options.Token = response.Data;
await serviceProvider
.GetRequiredService<INavigationService>()
.NavigateAsync<View.Page.SettingPage>(INavigationAwaiter.Default, true)
.ConfigureAwait(false);
}
}
private async Task LoginAsync()
{
if (UserName == null || Password == null)
{
return;
}
Response<string> response = await homaPassportClient.LoginAsync(UserName, Password).ConfigureAwait(false);
if (response.IsOk())
{
SaveUserNameAndPassword();
serviceProvider.GetRequiredService<IInfoBarService>().Information(response.Message);
HutaoUserOptions options = serviceProvider.GetRequiredService<HutaoUserOptions>();
await ThreadHelper.SwitchToMainThreadAsync();
options.UserName = UserName;
options.Token = response.Data;
await serviceProvider
.GetRequiredService<INavigationService>()
.NavigateAsync<View.Page.SettingPage>(INavigationAwaiter.Default, true)
.ConfigureAwait(false);
}
}
private async Task VerifyAsync(bool isResetPassword)
{
if (UserName == null)
{
return;
}
Response response = await homaPassportClient.VerifyAsync(UserName, isResetPassword).ConfigureAwait(false);
serviceProvider.GetRequiredService<IInfoBarService>().Information(response.Message);
}
private void SaveUserNameAndPassword()
{
if (UserName != null && Password != null)
{
LocalSetting.Set(SettingKeys.PassportUserName, UserName);
LocalSetting.Set(SettingKeys.PassportPassword, Password);
}
}
}

View File

@@ -16,6 +16,8 @@ using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.GachaLog.QueryProvider;
using Snap.Hutao.Service.Game;
using Snap.Hutao.Service.Game.Locator;
using Snap.Hutao.Service.Hutao;
using Snap.Hutao.Service.Navigation;
using Snap.Hutao.View.Dialog;
using System.Globalization;
using System.IO;
@@ -64,6 +66,7 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
logger = serviceProvider.GetRequiredService<ILogger<SettingViewModel>>();
Experimental = serviceProvider.GetRequiredService<ExperimentalFeaturesViewModel>();
Options = serviceProvider.GetRequiredService<AppOptions>();
UserOptions = serviceProvider.GetRequiredService<HutaoUserOptions>();
this.serviceProvider = serviceProvider;
selectedCulture = cultures.FirstOrDefault(c => c.Value == Options.CurrentCulture.Name);
@@ -76,6 +79,7 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
SetDataFolderCommand = new AsyncRelayCommand(SetDataFolderAsync);
ResetStaticResourceCommand = new RelayCommand(ResetStaticResource);
CopyDeviceIdCommand = new RelayCommand(CopyDeviceId);
NavigateToHutaoPassportCommand = new RelayCommand(NavigateToHutaoPassport);
}
/// <summary>
@@ -110,6 +114,11 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
/// </summary>
public AppOptions Options { get; }
/// <summary>
/// 胡桃用户选项
/// </summary>
public HutaoUserOptions UserOptions { get; }
/// <summary>
/// 背景类型
/// </summary>
@@ -203,6 +212,11 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
/// </summary>
public ICommand CopyDeviceIdCommand { get; }
/// <summary>
/// 导航到胡桃通行证界面
/// </summary>
public ICommand NavigateToHutaoPassportCommand { get; }
/// <inheritdoc/>
protected override Task OpenUIAsync()
{
@@ -299,13 +313,21 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
private void CopyDeviceId()
{
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
try
{
Clipboard.SetText(DeviceId);
serviceProvider.GetRequiredService<IInfoBarService>().Success(SH.ViewModelSettingCopyDeviceIdSuccess);
infoBarService.Success(SH.ViewModelSettingCopyDeviceIdSuccess);
}
catch (COMException)
catch (COMException ex)
{
infoBarService.Error(ex);
}
}
private void NavigateToHutaoPassport()
{
serviceProvider.GetRequiredService<INavigationService>().Navigate<View.Page.HutaoPassportPage>(INavigationAwaiter.Default);
}
}