Compare commits

...

11 Commits

Author SHA1 Message Date
wangyingpan bc19a02f4f 🐛 修复替换令牌时恢复代码不显示的问题
调整添加令牌时的提示信息
2024-04-29 18:07:05 +08:00
Aigio Liu d59d63d57e 🎨 vipEndTimeString 2024-04-29 16:13:40 +08:00
yingpanwang 9ad6e8fa8d Fix/authenticator verifycode UI (#3313)
* 🐛 修复添加令牌邮箱/短信验证ui显示

* 🎨 删除绑定手机号步骤
🐛 修复替换令牌逻辑验证码信息展示错误的问题

* 🐛 修复添加令牌邮箱/短信验证ui显示

* 🎨 删除绑定手机号步骤
🐛 修复替换令牌逻辑验证码信息展示错误的问题

* ✨ 替换令牌中添加绑定手机号窜哦做
2024-04-29 15:27:28 +08:00
Aigio Liu 45ef15b220 🎨 VipEndTimeString 2024-04-29 15:04:47 +08:00
Aigio Liu 25dfd1f888 🐛 VipEndTimeString 2024-04-29 15:01:57 +08:00
Aigio Liu 0495cd3079 💚 CI 2024-04-29 13:14:45 +08:00
Aigio Liu ea9c45d78b 🎨 VipEndTimeString 2024-04-29 13:11:51 +08:00
Aigio Liu 4427fd1a5f 🐛 VipEndTimeString 2024-04-29 12:18:03 +08:00
RMBGAME edf3c3a72c ⬆️ SteamClient 2024-04-29 12:10:10 +08:00
Aigio Liu 55490d2351 🐛 VipEndTimeString 2024-04-29 11:59:22 +08:00
Aigio Liu 17ae6655b4 🐛 VipEndTimeString 2024-04-29 11:55:34 +08:00
13 changed files with 630 additions and 262 deletions
+5 -5
View File
@@ -68,19 +68,19 @@ jobs:
run: dotnet --info
- name: Build BD.WTTS.Client.AppHost
run: dotnet build -c Release src\BD.WTTS.Client.AppHost\BD.WTTS.Client.AppHost.csproj --nologo -v q /property:WarningLevel=1
run: dotnet build -c Release src\BD.WTTS.Client.AppHost\BD.WTTS.Client.AppHost.csproj --nologo -v q --property:WarningLevel=1;DebugType=pdbonly
- name: Build BD.WTTS.Client.Plugins.Accelerator.ReverseProxy
run: dotnet build -c Release src\BD.WTTS.Client.Plugins.Accelerator.ReverseProxy\BD.WTTS.Client.Plugins.Accelerator.ReverseProxy.csproj --nologo -v q /property:WarningLevel=1
run: dotnet build -c Release src\BD.WTTS.Client.Plugins.Accelerator.ReverseProxy\BD.WTTS.Client.Plugins.Accelerator.ReverseProxy.csproj --nologo -v q --property:WarningLevel=1;DebugType=pdbonly
- name: Build BD.WTTS.Client.Avalonia.App
run: dotnet build -c Release src\BD.WTTS.Client.Avalonia.App\BD.WTTS.Client.Avalonia.App.csproj --nologo -v q /property:WarningLevel=1
run: dotnet build -c Release src\BD.WTTS.Client.Avalonia.App\BD.WTTS.Client.Avalonia.App.csproj --nologo -v q --property:WarningLevel=1;DebugType=pdbonly
- name: Build BD.WTTS.Client.Avalonia.Designer.HostApp
run: dotnet build -c Release src\BD.WTTS.Client.Avalonia.Designer.HostApp\BD.WTTS.Client.Avalonia.Designer.HostApp.csproj --nologo -v q /property:WarningLevel=1
run: dotnet build -c Release src\BD.WTTS.Client.Avalonia.Designer.HostApp\BD.WTTS.Client.Avalonia.Designer.HostApp.csproj --nologo -v q --property:WarningLevel=1;DebugType=pdbonly
- name: Test
run: dotnet test src/BD.WTTS.UnitTest/BD.WTTS.UnitTest.csproj -c Release -p:GeneratePackageOnBuild=false --nologo -v q /property:WarningLevel=1
run: dotnet test src/BD.WTTS.UnitTest/BD.WTTS.UnitTest.csproj -c Release -p:GeneratePackageOnBuild=false --nologo -v q --property:WarningLevel=1;DebugType=pdbonly
# release:
# name: Release
@@ -52,8 +52,10 @@ public sealed partial class GameAcceleratorService
[Reactive]
public DateTime? VipEndTime { get; set; }
const string VipEndTimeStringDef = "新用户免费试用 2 天";
[Reactive]
public string? VipEndTimeString { get; set; }
public string? VipEndTimeString { get; set; } = VipEndTimeStringDef;
GameAcceleratorService()
{
@@ -177,54 +179,51 @@ public sealed partial class GameAcceleratorService
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(async x =>
{
if (string.IsNullOrWhiteSpace(x?.WattOpenId))
return;
var vipEndTimeResult = await IMicroServiceClient.Instance.Manage.GetXunYouVipEndTime();
if (vipEndTimeResult == null)
string vipEndTimeString = VipEndTimeStringDef;
try
{
Log.Error(nameof(GameAcceleratorService),
"XunYouSDK.GetVipEndTime is null.");
return;
}
if (!vipEndTimeResult.IsSuccess || vipEndTimeResult.Content == null)
{
Toast.Show(ToastIcon.Error, "获取会员时间失败");
return;
}
if (vipEndTimeResult.Content.Code == XunYouBaseResponseCode.成功)
{
var etime = vipEndTimeResult.Content.Data?.ExpireTime;
if (etime.HasValue)
if (string.IsNullOrWhiteSpace(x?.WattOpenId))
{
VipEndTime = etime.Value.ToDateTime(UnixTimestampType.Seconds);
//var acc_order = (await IMicroServiceClient.Instance.Ordering.GetUserOrderCount([OrderStatus.Paid, OrderStatus.Completed], OrderBusinessType.XunYouOrder)).Content;
//if (acc_order <= 0)
//{
// if (VipEndTime.Value.AddDays(365).Date == DateTimeOffset.Now.Date)
// VipEndTimeString = "试用时长到期";
// else
// VipEndTimeString = "新用户试用2天";
//}
//else
//{
// VipEndTimeString = $"游戏加速会员有效期 {VipEndTime.Value:yyyy-MM-dd}";
//}
return;
}
if (VipEndTime.Value.AddDays(365).Date == DateTimeOffset.Now.Date)
VipEndTimeString = "新用户试用2天";
else
VipEndTimeString = $"游戏加速会员有效期 {VipEndTime.Value:yyyy-MM-dd}";
var vipEndTimeResult = await IMicroServiceClient.Instance.Manage.GetXunYouVipEndTime();
if (vipEndTimeResult == null)
{
Log.Error(nameof(GameAcceleratorService),
"XunYouSDK.GetVipEndTime is null.");
return;
}
if (!vipEndTimeResult.IsSuccess || vipEndTimeResult.Content == null)
{
Toast.Show(ToastIcon.Error, "获取会员时间失败");
return;
}
if (vipEndTimeResult.Content.Code == XunYouBaseResponseCode.成功)
{
var etime = vipEndTimeResult.Content.Data?.ExpireTime;
if (etime.HasValue)
{
VipEndTime = etime.Value.ToDateTime(UnixTimestampType.Seconds);
if (VipEndTime.Value > DateTime.Now)
{
vipEndTimeString = $"游戏加速会员有效期 {VipEndTime.Value:yyyy-MM-dd}";
}
}
}
else
{
Log.Error(nameof(GameAcceleratorService),
"XunYouSDK.GetVipEndTime is fail, message: {message}, code: {code}.",
vipEndTimeResult.Content.Message,
vipEndTimeResult.Content.Code);
}
}
else
finally
{
Log.Error(nameof(GameAcceleratorService),
"XunYouSDK.GetVipEndTime is fail, message: {message}, code: {code}.",
vipEndTimeResult.Content.Message,
vipEndTimeResult.Content.Code);
VipEndTimeString = vipEndTimeString;
}
});
@@ -0,0 +1,162 @@
using WinAuth;
using AppResources = BD.WTTS.Client.Resources.Strings;
namespace BD.WTTS.UI.ViewModels;
/// <summary>
/// 添加 Steam 账号手机号页面 VM
/// </summary>
public class AddSteamAccountPhoneNumberPageViewModel : WindowViewModel
{
#region 步骤 Index 定义
const int TAB_INDEX_BINDING = 0;
const int TAB_INDEX_CONFIRMATION_Email = 1;
const int TAB_INDEX_CONFIRMATION_SMS = 2;
#endregion 步骤 Index 定义
/// <summary>
/// 手机号文本
/// </summary>
[Reactive]
public string? PhoneNumberText { get; set; }
/// <summary>
/// 验证码文本
/// </summary>
[Reactive]
public string? CodeText { get; set; }
/// <summary>
/// 步骤 Index
/// </summary>
[Reactive]
public int SelectIndex { get; set; }
/// <summary>
/// 是否显示加载中
/// </summary>
[Reactive]
public bool IsLoading { get; set; }
private readonly SteamAuthenticator.EnrollState _enrollState;
private readonly SteamAuthenticator _steamAuthenticator;
public AddSteamAccountPhoneNumberPageViewModel(
SteamAuthenticator.EnrollState enrollState,
SteamAuthenticator steamAuthenticator
)
{
SelectIndex = TAB_INDEX_BINDING;
_steamAuthenticator = steamAuthenticator;
_enrollState = enrollState;
}
/// <summary>
/// 开始绑定手机号
/// </summary>
/// <returns></returns>
public async Task StartBindingAsync()
{
if (IsLoading)
{
Toast.Show(ToastIcon.Warning, AppResources.Warning_DoNotOperateFrequently);
return;
}
if (string.IsNullOrEmpty(PhoneNumberText))
{
Toast.Show(ToastIcon.Warning, AppResources.Warning_PleaseEnterTel);
return;
}
IsLoading = true;
try
{
string? msg = await _steamAuthenticator.AddPhoneNumberAsync(_enrollState, PhoneNumberText);
Toast.Show(ToastIcon.Info, msg ?? string.Empty);
if (_enrollState.RequiresEmailConfirmPhone)
{
SelectIndex = TAB_INDEX_CONFIRMATION_Email;
}
else
{
SelectIndex = TAB_INDEX_CONFIRMATION_SMS;
}
}
finally
{
IsLoading = false;
}
}
/// <summary>
/// 确认邮箱链接
/// </summary>
/// <returns></returns>
public async Task ConfirmBindingEmailAsync()
{
if (IsLoading)
{
Toast.Show(ToastIcon.Warning, AppResources.Warning_DoNotOperateFrequently);
return;
}
if (string.IsNullOrEmpty(PhoneNumberText))
{
Toast.Show(ToastIcon.Warning, AppResources.Warning_PleaseEnterTel);
return;
}
IsLoading = true;
try
{
var reslut = await _steamAuthenticator.AddPhoneNumberAsync(_enrollState, PhoneNumberText!);
if (_enrollState.RequiresEmailConfirmPhone == false && reslut == null)
{
SelectIndex = TAB_INDEX_CONFIRMATION_SMS;
}
}
finally
{
IsLoading = false;
}
}
/// <summary>
/// 验收短信验证码
/// </summary>
/// <returns></returns>
public async Task VerifyAccountPhoneWithCodeAsync()
{
if (string.IsNullOrEmpty(PhoneNumberText))
{
Toast.Show(ToastIcon.Warning, AppResources.Warning_PleaseEnterTel);
return;
}
if (string.IsNullOrEmpty(CodeText))
{
Toast.Show(ToastIcon.Warning, AppResources.Error_PleaseEnterTelCode);
return;
}
var verified = await _steamAuthenticator
.VerifyPhoneNumberAsync(PhoneNumberText!, CodeText!, _enrollState.AccessToken!);
if (verified)
{
Close?.Invoke(verified);
}
}
}
@@ -1,16 +1,22 @@
using AppResources = BD.WTTS.Client.Resources.Strings;
using BD.SteamClient.Models;
using BD.SteamClient.Services;
using BD.WTTS.UI.Views.Controls;
using WinAuth;
using AppResources = BD.WTTS.Client.Resources.Strings;
#if !ANDROID
using ToastLength = BD.Common.Enums.ToastLength;
#endif
namespace BD.WTTS.UI.ViewModels;
public sealed partial class SteamLoginImportPageViewModel : ViewModelBase
{
const int TAB_INDEX_LOGIN = 0;
const int TAB_INDEX_LOGINCONFIRM = 1;
const int TAB_INDEX_VERIFYCODE = 2;
const int TAB_INDEX_DONE = 3;
public static string Name => AppResources.Auth_SteamLoginImport;
readonly ISteamAccountService _steamAccountService = Ioc.Get<ISteamAccountService>();
@@ -94,7 +100,7 @@ public sealed partial class SteamLoginImportPageViewModel : ViewModelBase
{
if (string.IsNullOrEmpty(PhoneCodeText))
{
Toast.Show(ToastIcon.Error, AppResources.Error_PleaseEnterTelCode);
Toast.Show(ToastIcon.Error, AppResources.Error_PleaseEnterCode);
return false;
}
else
@@ -115,7 +121,7 @@ public sealed partial class SteamLoginImportPageViewModel : ViewModelBase
Created = DateTimeOffset.Now,
};
await AuthenticatorHelper.SaveAuthenticator(iADTO);
SelectIndex = 4;
SelectIndex = TAB_INDEX_DONE;
}
/// <summary>
@@ -136,15 +142,23 @@ public sealed partial class SteamLoginImportPageViewModel : ViewModelBase
if (_enrollState.NoPhoneNumber == true)
{
_enrollState.Error = null;
SelectIndex = 2;
//SelectIndex = 2;
// 正常情况下不会走到这里,因为已经不需要绑定手机的步骤了
return;
}
//导入最后一步,需要账号绑定的手机验证码确认
// 导入最后一步,需要账号绑定的手机验证码确认
// 2024-04-23 Steam绑定令牌不强制手机绑定 可以输入 邮箱者手机验证码
if (_enrollState.RequiresActivation == true)
{
// 查询账号手机号绑定状态
// IsVerifyAccountPhone = await _steamAccountService.CheckAccountPhoneStatus(_enrollState.AccessToken!) ?? false;
await CheckAccountPhoneStatus();
_enrollState.Error = null;
RevocationCodeText = _enrollState.RevocationCode;
SelectIndex = 3;
SelectIndex = TAB_INDEX_VERIFYCODE;
}
}
@@ -161,7 +175,7 @@ public sealed partial class SteamLoginImportPageViewModel : ViewModelBase
//Toast.Show(ToastIcon.Error, Strings.LocalAuth_SteamUser_Requires2FA);
//Reset();
Requires2FA = _steamLoginState.Requires2FA;
SelectIndex = 1;
SelectIndex = TAB_INDEX_LOGINCONFIRM;
return false;
}
//需要邮箱验证码
@@ -170,7 +184,7 @@ public sealed partial class SteamLoginImportPageViewModel : ViewModelBase
EmailDomainText = string.IsNullOrEmpty(_steamLoginState.EmailDomain) == false
? $"******@{_steamLoginState.EmailDomain}"
: string.Empty;
SelectIndex = 1;
SelectIndex = TAB_INDEX_LOGINCONFIRM;
return false;
}
else if (!string.IsNullOrEmpty(_steamLoginState.Message))
@@ -189,6 +203,12 @@ public sealed partial class SteamLoginImportPageViewModel : ViewModelBase
return !string.IsNullOrEmpty(_steamLoginState.AccessToken);
}
async ValueTask CheckAccountPhoneStatus()
{
// 查询账号手机号绑定状态
IsVerifyAccountPhone = await _steamAccountService.CheckAccountPhoneStatus(_enrollState.AccessToken!) ?? false;
}
public async Task LoginSteamImport()
{
if (IsLoading)
@@ -200,7 +220,7 @@ public sealed partial class SteamLoginImportPageViewModel : ViewModelBase
try
{
if (SelectIndex == 0)
if (SelectIndex == TAB_INDEX_LOGIN)
{
await LoginSteamFirstAsync();
}
@@ -224,22 +244,63 @@ public sealed partial class SteamLoginImportPageViewModel : ViewModelBase
//已有令牌情况下执行替换令牌逻辑
if (_enrollState.ReplaceAuth)
{
if (SelectIndex == 1 && await steamAuthenticator.RemoveAuthenticatorViaChallengeStartSync(_enrollState.AccessToken!))
if (SelectIndex == TAB_INDEX_LOGINCONFIRM && await steamAuthenticator.RemoveAuthenticatorViaChallengeStartSync(_enrollState.AccessToken!))
{
SelectIndex = 3;
await CheckAccountPhoneStatus();
SelectIndex = TAB_INDEX_VERIFYCODE;
if (!IsVerifyAccountPhone)
{
Toast.Show(ToastIcon.Warning, "只绑定邮箱的情况下无法直接替换令牌");
// 弹出绑定手机号流程
var added = await IWindowManager.Instance.ShowTaskDialogAsync(
viewModel: new AddSteamAccountPhoneNumberPageViewModel(_enrollState, steamAuthenticator),
pageContent: new AddSteamAccountPhoneNumberPage(),
isCancelButton: false,
isOkButton: false,
isRetryButton: false
);
// 查询账号手机号绑定状态
await CheckAccountPhoneStatus();
// 如果通过弹出的绑定手机号绑定成功 开始执行替换令牌
if (added && IsVerifyAccountPhone)
{
/*
* 绑定手机号会发送验证码
* 执行开始替换令牌操作也会发送验证码
* 如果两个操作间隔太短会导致 Steam 不发送验证码
*/
await Task.Delay(TimeSpan.FromSeconds(30));
await steamAuthenticator.RemoveAuthenticatorViaChallengeStartSync(_enrollState.AccessToken!);
}
// 取消了绑定手机号流程 无法执行替换令牌操作
else
{
SelectIndex = TAB_INDEX_LOGIN;
}
return;
}
return;
}
else if (SelectIndex == 3)
else if (SelectIndex == TAB_INDEX_VERIFYCODE)
{
if (string.IsNullOrEmpty(PhoneCodeText))
{
Toast.Show(ToastIcon.Error, Strings.Error_PleaseEnterTelCode);
Toast.Show(ToastIcon.Error, Strings.Error_PleaseEnterCode);
return;
}
if (await steamAuthenticator.RemoveAuthenticatorViaChallengeContinueSync(PhoneCodeText, _enrollState.AccessToken!))
{
await SaveAuthenticatorAsync();
RevocationCodeText = steamAuthenticator.RecoveryCode;
return;
}
}
@@ -319,4 +380,4 @@ public sealed partial class SteamLoginImportPageViewModel : ViewModelBase
IsLoading = false;
}
}
}
}
@@ -1,9 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BD.WTTS.UI.ViewModels;
public sealed partial class SteamLoginImportPageViewModel
@@ -67,4 +61,10 @@ public sealed partial class SteamLoginImportPageViewModel
[Reactive]
public string? PhoneNumberText { get; set; }
}
/// <summary>
/// 是否已验证账号的手机号
/// </summary>
[Reactive]
public bool IsVerifyAccountPhone { get; set; }
}
@@ -0,0 +1,93 @@
<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:spp="https://steampp.net/ui"
xmlns:s="https://steampp.net/services"
d:DesignWidth="400"
d:DesignHeight="250"
x:DataType="spp:AddSteamAccountPhoneNumberPageViewModel"
x:CompileBindings="True"
x:Class="BD.WTTS.UI.Views.Controls.AddSteamAccountPhoneNumberPage"
mc:Ignorable="d">
<Grid RowDefinitions="Auto,*">
<spp:Stepper SelectedIndex="{Binding SelectIndex}">
<spp:StepperItem Content="{Binding Path=Res.Steam_BindTel, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<spp:StepperItem Content="{Binding Path=Res.Steam_ConfirmEmailLink, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<spp:StepperItem Content="{Binding Path=Res.TelCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</spp:Stepper>
<spp:ContentLoader
Grid.Row="1"
MinWidth="400"
MinHeight="250"
IsLoading="{Binding IsLoading}"
IsShowNoResultText="False">
<Carousel IsVisible="{Binding !IsLoading}" SelectedIndex="{Binding SelectIndex}">
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="10">
<DockPanel>
<TextBlock
Margin="0,0,0,6"
DockPanel.Dock="Top"
Text="{Binding Path=Res.User_Phone, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
Name="PhoneNumberText"
MaxWidth="300"
Text="{Binding PhoneNumberText}"
Watermark="+8601234567890" />
</DockPanel>
<Button
MinWidth="280"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Command="{Binding StartBindingAsync}"
Content="{Binding Path=Res.Continue, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="10">
<Button
MinWidth="280"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Command="{Binding ConfirmBindingEmailAsync}"
Content="{Binding Path=Res.Continue, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="10">
<DockPanel>
<TextBlock
Margin="0,0,0,6"
DockPanel.Dock="Top"
Text="{Binding Path=Res.Error_PleaseEnterTelCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
Name="CodeText"
MaxWidth="300"
Text="{Binding CodeText}" />
</DockPanel>
<Button
MinWidth="280"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Command="{Binding VerifyAccountPhoneWithCodeAsync}"
Content="{Binding Path=Res.Continue, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
</Carousel>
</spp:ContentLoader>
</Grid>
</UserControl>
@@ -0,0 +1,11 @@
using Avalonia.Controls;
namespace BD.WTTS.UI.Views.Controls;
public partial class AddSteamAccountPhoneNumberPage : UserControl
{
public AddSteamAccountPhoneNumberPage()
{
InitializeComponent();
}
}
@@ -11,85 +11,86 @@
x:CompileBindings="True"
x:DataType="spp:SteamLoginImportPageViewModel"
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.LoginVerify, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<spp:StepperItem Content="{Binding Path=Res.Steam_BindTel, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<spp:StepperItem Content="{Binding Path=Res.TelCode, 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>
<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.LoginVerify, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<!--隐藏绑定手机号步骤-->
<!--<spp:StepperItem IsVisible="false" Content="{Binding Path=Res.Steam_BindTel, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
<spp:StepperItem Content="{Binding Path=Res.LocalAuth_VerifyCode, 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 IsLoading}"
IsShowNoResultText="False">
<Carousel IsVisible="{Binding !IsLoading}" SelectedIndex="{Binding SelectIndex}">
<!-- 登录 -->
<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}}" />
<Button
MinWidth="280"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
HorizontalContentAlignment="Center"
Command="{Binding LoginSteamImport}"
Content="{Binding Path=Res.Login, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
<spp:ContentLoader
Grid.Row="1"
MinWidth="600"
MinHeight="400"
IsLoading="{Binding IsLoading}"
IsShowNoResultText="False">
<Carousel IsVisible="{Binding !IsLoading}" SelectedIndex="{Binding SelectIndex}">
<!-- 登录 -->
<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}}" />
<Button
MinWidth="280"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
HorizontalContentAlignment="Center"
Command="{Binding LoginSteamImport}"
Content="{Binding Path=Res.Login, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
<!-- 邮箱验证 -->
<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 !Requires2FA}"
Message="{Binding Path=Res.LocalAuth_EmailCodeTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Severity="Warning" />
<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 Requires2FA}"
Message="{Binding Path=Res.LocalAuth_Steam2FACodeTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Severity="Warning" />
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="10">
<TextBlock IsVisible="{Binding !Requires2FA}" Text="{Binding Path=Res.EmailCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBlock IsVisible="{Binding Requires2FA}" Text="{Binding Path=Res.Steam2FACode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
Name="EmailAuthText"
MinWidth="300"
FontSize="24"
Text="{Binding EmailAuthText}" />
<!--<TextBlock
<!-- 邮箱验证 -->
<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 !Requires2FA}"
Message="{Binding Path=Res.LocalAuth_EmailCodeTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Severity="Warning" />
<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 Requires2FA}"
Message="{Binding Path=Res.LocalAuth_Steam2FACodeTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Severity="Warning" />
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="10">
<TextBlock IsVisible="{Binding !Requires2FA}" Text="{Binding Path=Res.EmailCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBlock IsVisible="{Binding Requires2FA}" Text="{Binding Path=Res.Steam2FACode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
Name="EmailAuthText"
MinWidth="300"
FontSize="24"
Text="{Binding EmailAuthText}" />
<!--<TextBlock
Margin="10,0"
HorizontalAlignment="Center"
Text="{Binding EmailDomainText}" />-->
<!--<TextBlock
<!--<TextBlock
Margin="10,0"
HorizontalAlignment="Center"
Text="{Binding Path=Res.LocalAuth_EmailCodeTip,
@@ -97,121 +98,138 @@
Source={x:Static s:ResourceService.Current}}"
TextAlignment="Center"
TextWrapping="WrapWithOverflow" />-->
<Button
MinWidth="280"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Command="{Binding LoginSteamImport}"
Content="{Binding Path=Res.Continue, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
</Panel>
<Button
MinWidth="280"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Command="{Binding LoginSteamImport}"
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.Warning_SteamAuthPhoneBind, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Severity="Warning" />
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="10">
<!-- 绑定手机 -->
<!--
<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.Warning_SteamAuthPhoneBind, 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.User_Phone, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
Name="PhoneNumberText"
MaxWidth="300"
Text="{Binding PhoneNumberText}"
Watermark="+8601234567890" />
</DockPanel>
<DockPanel>
<TextBlock
Margin="0,0,0,6"
DockPanel.Dock="Top"
Text="{Binding Path=Res.User_Phone, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
Name="PhoneNumberText"
MaxWidth="300"
Text="{Binding PhoneNumberText}"
Watermark="+8601234567890" />
</DockPanel>
<Button
MinWidth="280"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Command="{Binding LoginSteamImport}"
Content="{Binding Path=Res.Continue, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
</Panel>
<Button
MinWidth="280"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Command="{Binding LoginSteamImport}"
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.LocalAuth_SMSCodeTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Severity="Warning" />
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="10">
<DockPanel IsVisible="{Binding RevocationCodeText, Mode=OneWay, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}">
<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"
IsReadOnly="True"
Text="{Binding RevocationCodeText, Mode=OneWay}" />
</DockPanel>
<!--<CheckBox Content="{Binding Path=Res.RecoveryCode_Remember, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
<DockPanel>
<TextBlock
Margin="0,0,0,6"
DockPanel.Dock="Top"
Text="{Binding Path=Res.SMSCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
Name="PhoneCodeText"
MaxWidth="300"
Text="{Binding PhoneCodeText}" />
</DockPanel>
<Button
MinWidth="280"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Command="{Binding LoginSteamImport}"
Content="{Binding Path=Res.Continue, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
</Panel>
<!-- 验证手机 或 邮箱 -->
<!-- 2024-04-23 Steam绑定令牌不强制手机绑定 可以输入 邮箱者手机验证码 -->
<Panel>
<spp:Snackbar
Title="{Binding Path=Res.Notice_Tray_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
VerticalAlignment="Top"
IsClosable="False"
IsVisible="{Binding IsVerifyAccountPhone}"
IsOpen="True"
Message="{Binding Path=Res.LocalAuth_SMSCodeTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Severity="Warning" />
<spp:Snackbar
Title="{Binding Path=Res.Notice_Tray_Title, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
VerticalAlignment="Top"
IsClosable="False"
IsVisible="{Binding !IsVerifyAccountPhone}"
IsOpen="True"
Message="{Binding Path=Res.LocalAuth_EmailCodeTip, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
Severity="Warning" />
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="10">
<DockPanel IsVisible="{Binding RevocationCodeText, Mode=OneWay, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}">
<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"
IsReadOnly="True"
Text="{Binding RevocationCodeText, Mode=OneWay}" />
</DockPanel>
<!--<CheckBox Content="{Binding Path=Res.RecoveryCode_Remember, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />-->
<DockPanel>
<TextBlock
Margin="0,0,0,6"
DockPanel.Dock="Top"
IsVisible="{Binding IsVerifyAccountPhone}"
Text="{Binding Path=Res.SMSCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBlock
Margin="0,0,0,6"
DockPanel.Dock="Top"
IsVisible="{Binding !IsVerifyAccountPhone}"
Text="{Binding Path=Res.EmailCode, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
<TextBox
Name="PhoneCodeText"
MaxWidth="300"
Text="{Binding PhoneCodeText}" />
</DockPanel>
<Button
MinWidth="280"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
Command="{Binding LoginSteamImport}"
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 VerticalAlignment="Center" Spacing="10">
<DockPanel IsVisible="{Binding RevocationCodeText, Mode=OneWay, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}">
<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"
IsReadOnly="True"
Text="{Binding RevocationCodeText, Mode=OneWay}" />
</DockPanel>
<Button
MinWidth="280"
HorizontalAlignment="Center"
Command="{Binding Reset}"
Content="{Binding Path=Res.Confirm, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
</Panel>
</Carousel>
</spp:ContentLoader>
</Grid>
</UserControl>
<!-- 完成 -->
<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 VerticalAlignment="Center" Spacing="10">
<DockPanel IsVisible="{Binding RevocationCodeText, Mode=OneWay, Converter={StaticResource IsNullConverter}, ConverterParameter=invert}">
<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"
IsReadOnly="True"
Text="{Binding RevocationCodeText, Mode=OneWay}" />
</DockPanel>
<Button
MinWidth="280"
HorizontalAlignment="Center"
Command="{Binding Reset}"
Content="{Binding Path=Res.Confirm, Mode=OneWay, Source={x:Static s:ResourceService.Current}}" />
</StackPanel>
</Panel>
</Carousel>
</spp:ContentLoader>
</Grid>
</UserControl>
@@ -14,7 +14,7 @@ public partial class SteamLoginImportPage : ReactiveUserControl<SteamLoginImport
DataContext ??= new SteamLoginImportPageViewModel();
PasswordText.KeyUp += PasswordTextOnKeyUp;
EmailAuthText.KeyUp += PasswordTextOnKeyUp;
PhoneNumberText.KeyUp += PasswordTextOnKeyUp;
//PhoneNumberText.KeyUp += PasswordTextOnKeyUp;
PhoneCodeText.KeyUp += PasswordTextOnKeyUp;
EmailAuthText.TextInput += EmailAuthText_TextInput;
PhoneCodeText.TextInput += EmailAuthText_TextInput;
@@ -34,4 +34,4 @@ public partial class SteamLoginImportPage : ReactiveUserControl<SteamLoginImport
e.Handled = true;
}
}
}
}
+18
View File
@@ -4484,6 +4484,15 @@ namespace BD.WTTS.Client.Resources {
}
}
/// <summary>
/// 查找类似 验证码 的本地化字符串。
/// </summary>
public static string LocalAuth_VerifyCode {
get {
return ResourceManager.GetString("LocalAuth_VerifyCode", resourceCulture);
}
}
/// <summary>
/// 查找类似 使用 Steam++ V1 版本工具箱导出的文件导入令牌 的本地化字符串。
/// </summary>
@@ -6702,6 +6711,15 @@ namespace BD.WTTS.Client.Resources {
}
}
/// <summary>
/// 查找类似 确认邮箱链接 的本地化字符串。
/// </summary>
public static string Steam_ConfirmEmailLink {
get {
return ResourceManager.GetString("Steam_ConfirmEmailLink", resourceCulture);
}
}
/// <summary>
/// 查找类似 Steam 客户端登录区域: 的本地化字符串。
/// </summary>
@@ -2945,6 +2945,12 @@
</data>
<data name="Idle_PIN_NotBeNull" xml:space="preserve">
<value>PIN CODE 不能为空</value>
</data>
<data name="LocalAuth_VerifyCode" xml:space="preserve">
<value>验证码</value>
</data>
<data name="Steam_ConfirmEmailLink" xml:space="preserve">
<value>确认邮箱链接</value>
</data>
<data name="CommunityFix_Starting" xml:space="preserve">
<value>正在启动加速...</value>