mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-19 15:21:26 +08:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a726e151b | |||
| 979cd83662 | |||
| 48234a8a7e | |||
| 513f32c309 | |||
| bbe6e4f68f | |||
| 58e5147e14 | |||
| 11ea59fb3b | |||
| 8b6010b36a |
@@ -90,6 +90,9 @@
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="UI\Views\Pages\JoinSteamAuthenticatorPage.axaml.cs">
|
||||
<DependentUpon>JoinSteamAuthenticatorPage.axaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
+5
-1
@@ -1,6 +1,6 @@
|
||||
using SJsonSerializer = System.Text.Json.JsonSerializer;
|
||||
using BD.WTTS.UI.Views.Pages;
|
||||
using WinAuth;
|
||||
using SJsonSerializer = System.Text.Json.JsonSerializer;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
@@ -26,6 +26,8 @@ public class AuthenticatorImportPageViewModel : ViewModelBase
|
||||
if (await AuthenticatorHelper.VerifyMaxValue())
|
||||
await ImportFromSdaFile();
|
||||
})),
|
||||
new AuthenticatorImportMethod(Strings.LocalAuth_Import.Format(Strings.LocalAuth_JoinSteamAuthenticator), Strings.LocalAuth_JoinSteamAuthenticatorDesc,
|
||||
PageType: typeof(JoinSteamAuthenticatorPage)),
|
||||
new AuthenticatorImportMethod(Strings.LocalAuth_Import.Format(Strings.WattToolKitV2), Strings.LocalAuth_WattToolKitV2Import,
|
||||
Command: ReactiveCommand.Create(async () =>
|
||||
{
|
||||
@@ -123,6 +125,7 @@ public class AuthenticatorImportPageViewModel : ViewModelBase
|
||||
? Strings.LocalAuth_AddAuthSuccess
|
||||
: Strings.LocalAuth_AddAuth_PartSuccess);
|
||||
break;
|
||||
|
||||
case IAccountPlatformAuthenticatorRepository.ImportResultCode.SecondaryPasswordFail:
|
||||
Toast.Show(ToastIcon.Warning, Strings.LocalAuth_ProtectionAuth_PasswordErrorTip);
|
||||
var textViewModel =
|
||||
@@ -136,6 +139,7 @@ public class AuthenticatorImportPageViewModel : ViewModelBase
|
||||
}
|
||||
await ImportFromWattToolKitV2(exportPassword, password, isLocalProtect, filePath);
|
||||
break;
|
||||
|
||||
default:
|
||||
Toast.Show(ToastIcon.Error, Strings.LocalAuth_ExportAuth_Error.Format(result.resultCode));
|
||||
break;
|
||||
|
||||
+442
@@ -0,0 +1,442 @@
|
||||
using BD.SteamClient.Models;
|
||||
using BD.SteamClient.Services;
|
||||
using WinAuth;
|
||||
using AppResources = BD.WTTS.Client.Resources.Strings;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
/// <summary>
|
||||
/// 联合Steam令牌页面
|
||||
/// </summary>
|
||||
public sealed partial class JoinSteamAuthenticatorPageViewModel : ViewModelBase
|
||||
{
|
||||
#region 步骤索引常量
|
||||
|
||||
const int STEPINDEX_LOGIN = 0;
|
||||
|
||||
const int STEPINDEX_VERIFY = 1;
|
||||
|
||||
const int STEPINDEX_DONE = 2;
|
||||
|
||||
#endregion 步骤索引常量
|
||||
|
||||
#region 页面属性
|
||||
|
||||
/// <summary>
|
||||
/// 用户填入的 Steam 令牌验证码
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
public string? Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
public string? UserNameText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
public string? PasswordText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证码
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
public string? VerifyCodeText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 恢复代码
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
public string? RevocationCodeText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前步骤
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
public int SelectIndex { get; set; } = STEPINDEX_LOGIN;
|
||||
|
||||
/// <summary>
|
||||
/// 加载
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
public bool Loading { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否需要验证码
|
||||
/// </summary>
|
||||
[Reactive]
|
||||
public bool RequireVerifyCode { get; set; } = false;
|
||||
|
||||
#endregion 页面属性
|
||||
|
||||
#region 私有变量
|
||||
|
||||
/// <summary>
|
||||
/// Steam 账号服务
|
||||
/// </summary>
|
||||
private static readonly ISteamAccountService _steamAccountService = Ioc.Get<ISteamAccountService>();
|
||||
|
||||
/// <summary>
|
||||
/// 当前页面待导入的 Steam Authenticator
|
||||
/// </summary>
|
||||
private SteamAuthenticator? _currentSteamAuthenticator;
|
||||
|
||||
private SteamLoginState? _currentSteamLoginState;
|
||||
|
||||
#endregion 私有变量
|
||||
|
||||
#region 联合 Steam令牌 页面流程
|
||||
|
||||
/// <summary>
|
||||
/// 登录
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task LoginAsync()
|
||||
{
|
||||
if (Loading)
|
||||
return;
|
||||
|
||||
Loading = true;
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(UserNameText) || string.IsNullOrEmpty(PasswordText))
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, AppResources.Error_PleaseEnterUsernamePassword);
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化登录状态
|
||||
var loginState = _currentSteamLoginState ??= new SteamLoginState();
|
||||
|
||||
loginState.Username = UserNameText;
|
||||
loginState.Password = PasswordText;
|
||||
loginState.Language = ResourceService.GetCurrentCultureSteamLanguageName();
|
||||
|
||||
if (RequireVerifyCode && loginState.RequiresEmailAuth)
|
||||
{
|
||||
loginState.EmailCode = VerifyCodeText;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 开始登录
|
||||
await _steamAccountService.DoLoginV2Async(loginState);
|
||||
}
|
||||
catch (HttpRequestException)
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_JoinSteamAuthenticator_LoginRequestError);
|
||||
return;
|
||||
}
|
||||
|
||||
// 登陆结果
|
||||
if (!loginState.Success)
|
||||
{
|
||||
if (loginState.RequiresEmailAuth)
|
||||
{
|
||||
RequireVerifyCode = true;
|
||||
Toast.Show(ToastIcon.Info, Strings.LocalAuth_EmailCodeTip);
|
||||
return;
|
||||
}
|
||||
else if (loginState.Requires2FA)
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_SteamUser_Requires2FA);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, loginState.Message ?? string.Empty);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据登录信息 获取/初始化 TwoFA Steam Authenticator 信息
|
||||
var (initialized, errMsg) = await InitTwoFASteamAuthenticatorAsync(loginState);
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, errMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
RevocationCodeText = _currentSteamAuthenticator!.RecoveryCode;
|
||||
// 跳转到验证页面
|
||||
SelectIndex = STEPINDEX_VERIFY;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验验证码
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task VerifyCodeAsync()
|
||||
{
|
||||
if (Loading)
|
||||
return;
|
||||
|
||||
Loading = true;
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Code))
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_JoinSteamAuthenticator_SteamGuardCodeEmptyError);
|
||||
return;
|
||||
}
|
||||
|
||||
var equals = await CompareCodeAsync();
|
||||
|
||||
if (!equals)
|
||||
{
|
||||
Toast.Show(ToastIcon.Warning,
|
||||
$@"{AppResources.LocalAuth_JoinSteamAuthenticator_VerifySteamGuardCodeError}: {Code} != {_currentSteamAuthenticator?.CurrentCode}");
|
||||
return;
|
||||
}
|
||||
|
||||
RevocationCodeText = _currentSteamAuthenticator!.RecoveryCode;
|
||||
SelectIndex = STEPINDEX_DONE;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存令牌
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task SaveAsync()
|
||||
{
|
||||
if (Loading)
|
||||
return;
|
||||
|
||||
Loading = true;
|
||||
|
||||
try
|
||||
{
|
||||
if (_currentSteamAuthenticator == null)
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_JoinSteamAuthenticator_InitLocalAuthenticatorError);
|
||||
SelectIndex = STEPINDEX_LOGIN;
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(Code))
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_JoinSteamAuthenticator_SteamGuardCodeEmptyError);
|
||||
SelectIndex = STEPINDEX_VERIFY;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await SaveAuthenticatorAsync(UserNameText!, _currentSteamAuthenticator))
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, AppResources.LocalAuth_JoinSteamAuthenticator_SaveLocalAuthenticatorError);
|
||||
return;
|
||||
}
|
||||
|
||||
// 保存完成重置
|
||||
Reset();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置恢复代码
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task ResetRevocationCodeAsync()
|
||||
{
|
||||
if (_currentSteamLoginState == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据登录信息 获取/初始化 TwoFA Steam Authenticator 信息
|
||||
var (initialized, errMsg) = await InitTwoFASteamAuthenticatorAsync(_currentSteamLoginState);
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, errMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
RevocationCodeText = _currentSteamAuthenticator!.RecoveryCode;
|
||||
}
|
||||
|
||||
#endregion 联合 Steam令牌 页面流程
|
||||
|
||||
#region 辅助方法
|
||||
|
||||
/// <summary>
|
||||
/// 初始化 TwoFA Steam Authenticator 信息
|
||||
/// </summary>
|
||||
/// <param name="loginState"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<(bool initialized, string errorMsg)> InitTwoFASteamAuthenticatorAsync(SteamLoginState loginState)
|
||||
{
|
||||
_currentSteamAuthenticator = new SteamAuthenticator();
|
||||
|
||||
string? steamId = loginState.SteamId != default
|
||||
? loginState.SteamId.ToString()
|
||||
: null;
|
||||
|
||||
if (string.IsNullOrEmpty(steamId))
|
||||
return (false, $"{AppResources.LocalAuth_JoinSteamAuthenticator_InitLocalAuthenticatorError}:{nameof(steamId)}");
|
||||
|
||||
string deviceId = CreateNewDeviceId();
|
||||
|
||||
var client = _currentSteamAuthenticator.GetClient();
|
||||
|
||||
string authenticatorJson;
|
||||
|
||||
try
|
||||
{
|
||||
authenticatorJson = await client
|
||||
.AddAuthenticatorAsync(
|
||||
steamId,
|
||||
DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(),
|
||||
deviceId,
|
||||
loginState.AccessToken ?? string.Empty
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (false, $"{AppResources.LocalAuth_JoinSteamAuthenticator_RequestUser2FAInfoError}:{ex.Message}");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(authenticatorJson))
|
||||
return (false, AppResources.LocalAuth_JoinSteamAuthenticator_RequestUser2FAInfoError);
|
||||
|
||||
var (initialized, msg) = TryParseSteamAuthenticator(authenticatorJson, out var parsedSteamData)
|
||||
? (true, string.Empty)
|
||||
: (false, AppResources.LocalAuth_JoinSteamAuthenticator_ParseUser2FAInfoError);
|
||||
|
||||
// 解析响应之后赋值给当前本地令牌
|
||||
if (initialized)
|
||||
{
|
||||
_currentSteamAuthenticator.DeviceId = deviceId;
|
||||
_currentSteamAuthenticator.SteamData = SystemTextJsonSerializer.Serialize(parsedSteamData!, SteamJsonContext.Default.SteamConvertSteamDataJsonStruct);
|
||||
_currentSteamAuthenticator.SecretKey = Base64Extensions.Base64DecodeToByteArray_Nullable(parsedSteamData!.SharedSecret);
|
||||
_currentSteamAuthenticator.Serial = parsedSteamData.SerialNumber;
|
||||
}
|
||||
|
||||
return (initialized, msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证令牌验证码
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task<bool> CompareCodeAsync()
|
||||
{
|
||||
if (_currentSteamAuthenticator == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Yield();
|
||||
|
||||
_currentSteamAuthenticator.Sync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.LogAndShowT();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool compareResult = string.Equals(Code, _currentSteamAuthenticator?.CurrentCode, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
return compareResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析 Steam Authenticator json响应
|
||||
/// </summary>
|
||||
/// <param name="authenticatorJson"></param>
|
||||
/// <param name="parsedSteamAuthenticator">已解析的响应信息</param>
|
||||
/// <returns></returns>
|
||||
private static bool TryParseSteamAuthenticator(string authenticatorJson, out SteamConvertSteamDataJsonStruct? parsedSteamAuthenticator)
|
||||
{
|
||||
parsedSteamAuthenticator = default;
|
||||
|
||||
SteamDoLoginTfaJsonStruct? authenticatorDataResp;
|
||||
|
||||
try
|
||||
{
|
||||
authenticatorDataResp = SystemTextJsonSerializer.Deserialize(
|
||||
authenticatorJson,
|
||||
SteamJsonContext.Default.SteamDoLoginTfaJsonStruct
|
||||
);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (authenticatorDataResp == null || authenticatorDataResp.Response == null)
|
||||
return false;
|
||||
|
||||
parsedSteamAuthenticator = authenticatorDataResp.Response;
|
||||
|
||||
// 目前只需要知道是否含有令牌数据信息
|
||||
// 不需要知道当前状态可不可以绑定,绑定操作在 Steam App 中完成
|
||||
// 这里只是将令牌数据保存到本地 以便后续计算
|
||||
return parsedSteamAuthenticator != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存令牌
|
||||
/// </summary>
|
||||
/// <param name="authenticatorName"></param>
|
||||
/// <param name="authenticator"></param>
|
||||
/// <returns></returns>
|
||||
private static Task<bool> SaveAuthenticatorAsync(string authenticatorName, SteamAuthenticator authenticator)
|
||||
{
|
||||
var iADTO = new AuthenticatorDTO
|
||||
{
|
||||
Name = $"Steam({authenticatorName})",
|
||||
Value = authenticator,
|
||||
Created = DateTimeOffset.Now,
|
||||
};
|
||||
|
||||
return AuthenticatorHelper.SaveAuthenticator(iADTO);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建新的设备ID
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static string CreateNewDeviceId() => $"android:{Guid.NewGuid()}";
|
||||
|
||||
/// <summary>
|
||||
/// 重置页面绑定信息
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
UserNameText = default;
|
||||
PasswordText = default;
|
||||
Code = default;
|
||||
VerifyCodeText = default;
|
||||
RequireVerifyCode = default;
|
||||
RevocationCodeText = default;
|
||||
SelectIndex = STEPINDEX_LOGIN;
|
||||
|
||||
_currentSteamAuthenticator = default;
|
||||
_currentSteamLoginState = default;
|
||||
}
|
||||
|
||||
#endregion 辅助方法
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
<UserControl
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
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:s="https://steampp.net/services"
|
||||
xmlns:spp="https://steampp.net/ui"
|
||||
x:CompileBindings="True"
|
||||
x:DataType="spp:JoinSteamAuthenticatorPageViewModel"
|
||||
x:Class="BD.WTTS.UI.Views.Pages.JoinSteamAuthenticatorPage"
|
||||
mc:Ignorable="d">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<spp:Stepper SelectedIndex="{Binding SelectIndex}">
|
||||
<spp:StepperItem Content="{Binding Path=Res.Steam_Login, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<spp:StepperItem Content="{Binding Path=Res.LocalAuth_JoinSteamAuthenticator_ConfirmSteamAppAuthenticatorCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<spp:StepperItem Content="{Binding Path=Res.Btn_Text_Complete, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</spp:Stepper>
|
||||
|
||||
<spp:ContentLoader
|
||||
Grid.Row="1"
|
||||
MinWidth="600"
|
||||
MinHeight="400"
|
||||
IsLoading="{Binding Loading}"
|
||||
IsShowNoResultText="False">
|
||||
<Carousel IsVisible="{Binding !Loading}" SelectedIndex="{Binding SelectIndex}">
|
||||
<Panel>
|
||||
<spp:Snackbar
|
||||
Title="{Binding Path=Res.Notice_Tray_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
VerticalAlignment="Top"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
IsVisible="{Binding RequireVerifyCode}"
|
||||
Message="{Binding Path=Res.LocalAuth_EmailCodeTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Severity="Warning" />
|
||||
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="10">
|
||||
<PathIcon
|
||||
Width="88"
|
||||
Height="88"
|
||||
Data="{StaticResource Steam}" />
|
||||
<TextBox
|
||||
MaxWidth="280"
|
||||
Text="{Binding UserNameText}"
|
||||
Watermark="{Binding Path=Res.Steam_User, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox
|
||||
Name="PasswordText"
|
||||
MaxWidth="280"
|
||||
Classes="revealPasswordButton"
|
||||
PasswordChar="{StaticResource PasswordChar}"
|
||||
Text="{Binding PasswordText}"
|
||||
Watermark="{Binding Path=Res.Steam_Password, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox
|
||||
IsVisible="{Binding RequireVerifyCode}"
|
||||
Watermark="{Binding Path=Res.EmailCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Text="{Binding VerifyCodeText}" />
|
||||
<Button
|
||||
MinWidth="280"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalContentAlignment="Center"
|
||||
Command="{Binding LoginAsync}"
|
||||
Content="{Binding Path=Res.Login, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</StackPanel>
|
||||
</Panel>
|
||||
|
||||
<Panel>
|
||||
<spp:Snackbar
|
||||
Title="{Binding Path=Res.Notice_Tray_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
VerticalAlignment="Top"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
Message="{Binding Path=Res.LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCodeTips, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Severity="Warning" />
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="10">
|
||||
<DockPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,0,6"
|
||||
DockPanel.Dock="Top"
|
||||
Text="{Binding Path=Res.RecoveryCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox
|
||||
MaxWidth="300"
|
||||
Text="{Binding RevocationCodeText}"
|
||||
IsReadOnly="True" />
|
||||
<!--<Button
|
||||
Content="重新生成"
|
||||
Command="{Binding ResetRevocationCodeAsync}" />-->
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,0,6"
|
||||
DockPanel.Dock="Top"
|
||||
Text="{Binding Path=Res.LocalAuth_JoinSteamAuthenticator_SteamAppAuthenticatorCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox
|
||||
MaxWidth="300"
|
||||
Watermark="{Binding Path=Res.LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Text="{Binding Code}" />
|
||||
</DockPanel>
|
||||
|
||||
<Button
|
||||
MinWidth="280"
|
||||
HorizontalAlignment="Center"
|
||||
HorizontalContentAlignment="Center"
|
||||
Command="{Binding VerifyCodeAsync}"
|
||||
Content="{Binding Path=Res.Continue, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</StackPanel>
|
||||
</Panel>
|
||||
|
||||
<Panel>
|
||||
<spp:Snackbar
|
||||
Title="{Binding Path=Res.Notice_Tray_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
VerticalAlignment="Top"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
Message="{Binding Path=Res.RecoveryCode_RememberTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
Severity="Success" />
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="10">
|
||||
|
||||
<DockPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,0,6"
|
||||
DockPanel.Dock="Top"
|
||||
Text="{Binding Path=Res.RecoveryCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
<TextBox
|
||||
MaxWidth="300"
|
||||
Text="{Binding RevocationCodeText}"
|
||||
IsReadOnly="True" />
|
||||
</DockPanel>
|
||||
|
||||
<Button
|
||||
MinWidth="280"
|
||||
HorizontalAlignment="Center"
|
||||
HorizontalContentAlignment="Center"
|
||||
Command="{Binding SaveAsync}"
|
||||
Content="{Binding Path=Res.Confirm, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
|
||||
</StackPanel>
|
||||
</Panel>
|
||||
</Carousel>
|
||||
</spp:ContentLoader>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace BD.WTTS.UI.Views.Pages;
|
||||
|
||||
public partial class JoinSteamAuthenticatorPage : UserControl
|
||||
{
|
||||
public JoinSteamAuthenticatorPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
DataContext = new JoinSteamAuthenticatorPageViewModel();
|
||||
}
|
||||
}
|
||||
+117
@@ -4195,6 +4195,123 @@ namespace BD.WTTS.Client.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 共存令牌 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 确认 Steam App 令牌验证码 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator_ConfirmSteamAppAuthenticatorCode {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_ConfirmSteamAppAuthenticatorCode", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 初始化本地令牌错误 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator_InitLocalAuthenticatorError {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_InitLocalAuthenticatorError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 请输入 Steam App 中显示的令牌验证码 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCode {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCode", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 打开 Steam App 绑定令牌后在此页面输入验证 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCodeTips {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_InputSteamAppAuthenticatorCodeTips", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 登录请求错误 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator_LoginRequestError {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_LoginRequestError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 解析用户 Steam 令牌信息失败 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator_ParseUser2FAInfoError {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_ParseUser2FAInfoError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 获取用户 Steam 令牌信息失败 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator_RequestUser2FAInfoError {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_RequestUser2FAInfoError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 保存令牌失败 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator_SaveLocalAuthenticatorError {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_SaveLocalAuthenticatorError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Steam App 令牌验证码 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator_SteamAppAuthenticatorCode {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_SteamAppAuthenticatorCode", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 请输入已在 Steam App 中绑定的令牌当前的令牌验证码 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator_SteamGuardCodeEmptyError {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_SteamGuardCodeEmptyError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 验证令牌错误 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticator_VerifySteamGuardCodeError {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticator_VerifySteamGuardCodeError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 在 Watt Toolkit 中与官方 Steam App 中使用相同的令牌信息 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LocalAuth_JoinSteamAuthenticatorDesc {
|
||||
get {
|
||||
return ResourceManager.GetString("LocalAuth_JoinSteamAuthenticatorDesc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 确定要注销当前令牌登录的账号信息吗? 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user