mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
style improvement
This commit is contained in:
@@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -19,6 +20,9 @@ namespace Snap.Hutao.SourceGeneration.DedendencyInjection;
|
||||
[Generator]
|
||||
public class InjectionGenerator : ISourceGenerator
|
||||
{
|
||||
private const string InjectAsSingletonName = "Snap.Hutao.Core.DependencyInjection.InjectAs.Singleton";
|
||||
private const string InjectAsTransientName = "Snap.Hutao.Core.DependencyInjection.InjectAs.Transient";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Initialize(GeneratorInitializationContext context)
|
||||
{
|
||||
@@ -63,9 +67,14 @@ internal static partial class ServiceCollectionExtensions
|
||||
|
||||
private static void FillWithInjectionServices(InjectionSyntaxContextReceiver receiver, StringBuilder sourceCodeBuilder)
|
||||
{
|
||||
foreach (INamedTypeSymbol classSymbol in receiver.Classes.OrderByDescending(symbol => symbol.ToDisplayString()))
|
||||
List<string> lines = new();
|
||||
StringBuilder lineBuilder = new();
|
||||
|
||||
foreach (INamedTypeSymbol classSymbol in receiver.Classes)
|
||||
{
|
||||
sourceCodeBuilder.Append("\r\n");
|
||||
lineBuilder
|
||||
.Clear()
|
||||
.Append("\r\n");
|
||||
|
||||
AttributeData injectionInfo = classSymbol
|
||||
.GetAttributes()
|
||||
@@ -77,11 +86,11 @@ internal static partial class ServiceCollectionExtensions
|
||||
string injectAsName = injectAs.ToCSharpString();
|
||||
switch (injectAsName)
|
||||
{
|
||||
case "Snap.Hutao.Core.DependencyInjection.InjectAs.Singleton":
|
||||
sourceCodeBuilder.Append(@" .AddSingleton(");
|
||||
case InjectAsSingletonName:
|
||||
lineBuilder.Append(@" .AddSingleton(");
|
||||
break;
|
||||
case "Snap.Hutao.Core.DependencyInjection.InjectAs.Transient":
|
||||
sourceCodeBuilder.Append(@" .AddTransient(");
|
||||
case InjectAsTransientName:
|
||||
lineBuilder.Append(@" .AddTransient(");
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"非法的InjectAs值: [{injectAsName}]。");
|
||||
@@ -90,10 +99,17 @@ internal static partial class ServiceCollectionExtensions
|
||||
if (arguments.Length == 2)
|
||||
{
|
||||
TypedConstant interfaceType = arguments[1];
|
||||
sourceCodeBuilder.Append($"{interfaceType.ToCSharpString()}, ");
|
||||
lineBuilder.Append($"{interfaceType.ToCSharpString()}, ");
|
||||
}
|
||||
|
||||
sourceCodeBuilder.Append($"typeof({classSymbol.ToDisplayString()}))");
|
||||
lineBuilder.Append($"typeof({classSymbol.ToDisplayString()}))");
|
||||
|
||||
lines.Add(lineBuilder.ToString());
|
||||
}
|
||||
|
||||
foreach (string line in lines.OrderByDescending(x => x))
|
||||
{
|
||||
sourceCodeBuilder.Append(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
<StaticResource x:Key="WindowCaptionForeground" ResourceKey="SystemControlForegroundBaseHighBrush" />
|
||||
<StaticResource x:Key="WindowCaptionForegroundDisabled" ResourceKey="SystemControlForegroundBaseHighBrush" />
|
||||
|
||||
<Thickness x:Key="InfoBarIconMargin">6,16,16,16</Thickness>
|
||||
<Thickness x:Key="InfoBarContentRootPadding">16,0,0,0</Thickness>
|
||||
|
||||
<CornerRadius x:Key="CompatCornerRadius">4</CornerRadius>
|
||||
<CornerRadius x:Key="CompatCornerRadiusTop">4,4,0,0</CornerRadius>
|
||||
<CornerRadius x:Key="CompatCornerRadiusRight">0,4,4,0</CornerRadius>
|
||||
|
||||
@@ -21,7 +21,6 @@ internal class AutoHeightBehavior : BehaviorBase<FrameworkElement>
|
||||
public double TargetWidth
|
||||
{
|
||||
get => (double)GetValue(TargetWidthProperty);
|
||||
|
||||
set => SetValue(TargetWidthProperty, value);
|
||||
}
|
||||
|
||||
@@ -31,15 +30,14 @@ internal class AutoHeightBehavior : BehaviorBase<FrameworkElement>
|
||||
public double TargetHeight
|
||||
{
|
||||
get => (double)GetValue(TargetHeightProperty);
|
||||
|
||||
set => SetValue(TargetHeightProperty, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnAssociatedObjectLoaded()
|
||||
{
|
||||
AssociatedObject.SizeChanged += OnSizeChanged;
|
||||
UpdateElementHeight();
|
||||
AssociatedObject.SizeChanged += OnSizeChanged;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -27,7 +27,7 @@ public class CancellablePage : Page
|
||||
/// <inheritdoc/>
|
||||
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
|
||||
{
|
||||
viewLoadingConcellationTokenSource.Cancel();
|
||||
base.OnNavigatingFrom(e);
|
||||
viewLoadingConcellationTokenSource.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,9 @@ public sealed partial class MainWindow : Window
|
||||
private void MainWindowClosed(object sender, WindowEventArgs args)
|
||||
{
|
||||
// save datebase
|
||||
Ioc.Default.GetRequiredService<AppDbContext>().SaveChanges();
|
||||
AppDbContext appDbContext = Ioc.Default.GetRequiredService<AppDbContext>();
|
||||
int changes = appDbContext.SaveChanges();
|
||||
|
||||
Verify.Operation(changes == 0, "存在可避免的未经处理的数据库更改");
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.Web.Hoyolab.Bbs.User;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
|
||||
namespace Snap.Hutao.Model.Entity;
|
||||
|
||||
@@ -21,6 +24,7 @@ public class User : Observable
|
||||
/// 无用户
|
||||
/// </summary>
|
||||
public static readonly User None = new();
|
||||
private bool isInitialized = false;
|
||||
private UserGameRole? selectedUserGameRole;
|
||||
|
||||
/// <summary>
|
||||
@@ -68,6 +72,12 @@ public class User : Observable
|
||||
[NotMapped]
|
||||
public ICommand? RemoveCommand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 复制Cookie命令
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public ICommand? CopyCookieCommand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 判断用户是否为空用户
|
||||
/// </summary>
|
||||
@@ -110,6 +120,12 @@ public class User : Observable
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isInitialized)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
CopyCookieCommand = new RelayCommand(CopyCookie);
|
||||
Must.NotNull(RemoveCommand!);
|
||||
|
||||
UserInfo = await userClient
|
||||
@@ -122,6 +138,8 @@ public class User : Observable
|
||||
|
||||
SelectedUserGameRole = UserGameRoles.FirstOrFirstOrDefault(role => role.IsChosen);
|
||||
|
||||
isInitialized = true;
|
||||
|
||||
return UserInfo != null && UserGameRoles.Any();
|
||||
}
|
||||
|
||||
@@ -141,4 +159,21 @@ public class User : Observable
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
private void CopyCookie()
|
||||
{
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
try
|
||||
{
|
||||
DataPackage content = new();
|
||||
content.SetText(Must.NotNull(Cookie!));
|
||||
Clipboard.SetContent(content);
|
||||
|
||||
infoBarService.Success($"{UserInfo?.Nickname} 的 Cookie 复制成功");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
infoBarService.Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ public interface IUserService
|
||||
|
||||
/// <summary>
|
||||
/// 异步添加用户
|
||||
/// 通常用户是未初始化的
|
||||
/// </summary>
|
||||
/// <param name="user">待添加的用户</param>
|
||||
/// <returns>用户初始化是否成功</returns>
|
||||
@@ -37,7 +38,8 @@ public interface IUserService
|
||||
/// 异步移除用户
|
||||
/// </summary>
|
||||
/// <param name="user">待移除的用户</param>
|
||||
void RemoveUser(User user);
|
||||
/// <returns>任务</returns>
|
||||
Task RemoveUserAsync(User user);
|
||||
|
||||
/// <summary>
|
||||
/// 将cookie的字符串形式转换为字典
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Service.Abstraction.Navigation;
|
||||
|
||||
/// <summary>
|
||||
/// 表示导航等待器
|
||||
/// </summary>
|
||||
public interface INavigationAwaiter
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认的等待器
|
||||
/// </summary>
|
||||
static readonly INavigationAwaiter Default = new NavigationExtra();
|
||||
|
||||
/// <summary>
|
||||
/// 等待导航完成,或直到抛出异常
|
||||
/// </summary>
|
||||
/// <returns>导航完成的任务</returns>
|
||||
Task WaitForCompletionAsync();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Service.Abstraction.Navigation;
|
||||
|
||||
public interface INavigationExtra
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
object? Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通知导航服务导航已经结束
|
||||
/// </summary>
|
||||
void NotifyNavigationCompleted();
|
||||
|
||||
/// <summary>
|
||||
/// 通知导航服务导航异常
|
||||
/// </summary>
|
||||
/// <param name="exception">异常</param>
|
||||
void NotifyNavigationException(Exception exception);
|
||||
}
|
||||
@@ -41,29 +41,29 @@ public interface INavigationService
|
||||
/// 导航到指定类型的页面
|
||||
/// </summary>
|
||||
/// <param name="pageType">指定的页面类型</param>
|
||||
/// <param name="isSyncTabRequested">是否同步标签,当在代码中调用时应设为 true</param>
|
||||
/// <param name="data">要传递的数据</param>
|
||||
/// <param name="isSyncTabRequested">是否同步标签,当在代码中调用时应设为 true</param>
|
||||
/// <returns>是否导航成功</returns>
|
||||
NavigationResult Navigate(Type pageType, bool isSyncTabRequested = false, NavigationExtra? data = null);
|
||||
NavigationResult Navigate(Type pageType, INavigationAwaiter data, bool isSyncTabRequested = false);
|
||||
|
||||
/// <summary>
|
||||
/// 导航到指定类型的页面
|
||||
/// </summary>
|
||||
/// <typeparam name="T">指定的页面类型</typeparam>
|
||||
/// <param name="isSyncTabRequested">是否同步标签,当在代码中调用时应设为 true</param>
|
||||
/// <param name="data">要传递的数据</param>
|
||||
/// <param name="isSyncTabRequested">是否同步标签,当在代码中调用时应设为 true</param>
|
||||
/// <returns>是否导航成功</returns>
|
||||
NavigationResult Navigate<T>(bool isSyncTabRequested = false, NavigationExtra? data = null)
|
||||
NavigationResult Navigate<T>(INavigationAwaiter data, bool isSyncTabRequested = false)
|
||||
where T : Page;
|
||||
|
||||
/// <summary>
|
||||
/// 异步的导航到指定类型的页面
|
||||
/// </summary>
|
||||
/// <typeparam name="TPage">指定的页面类型</typeparam>
|
||||
/// <param name="syncNavigationViewItem">是否同步标签,当在代码中调用时应设为 true</param>
|
||||
/// <param name="data">要传递的数据</param>
|
||||
/// <param name="syncNavigationViewItem">是否同步标签,当在代码中调用时应设为 true</param>
|
||||
/// <returns>是否导航成功</returns>
|
||||
Task<NavigationResult> NavigateAsync<TPage>(bool syncNavigationViewItem = false, NavigationExtra? data = null)
|
||||
Task<NavigationResult> NavigateAsync<TPage>(INavigationAwaiter data, bool syncNavigationViewItem = false)
|
||||
where TPage : Page;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -6,8 +6,13 @@ namespace Snap.Hutao.Service.Abstraction.Navigation;
|
||||
/// <summary>
|
||||
/// 导航额外信息
|
||||
/// </summary>
|
||||
public class NavigationExtra
|
||||
public class NavigationExtra : INavigationExtra, INavigationAwaiter
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务完成源
|
||||
/// </summary>
|
||||
private readonly TaskCompletionSource navigationCompletedTaskCompletionSource = new();
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的导航额外信息
|
||||
/// </summary>
|
||||
@@ -17,13 +22,24 @@ public class NavigationExtra
|
||||
Data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
/// <inheritdoc/>
|
||||
public object? Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务完成源
|
||||
/// </summary>
|
||||
public TaskCompletionSource NavigationCompletedTaskCompletionSource { get; } = new();
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public Task WaitForCompletionAsync()
|
||||
{
|
||||
return navigationCompletedTaskCompletionSource.Task;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void NotifyNavigationCompleted()
|
||||
{
|
||||
navigationCompletedTaskCompletionSource.TrySetResult();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void NotifyNavigationException(Exception exception)
|
||||
{
|
||||
navigationCompletedTaskCompletionSource.TrySetException(exception);
|
||||
}
|
||||
}
|
||||
@@ -25,11 +25,11 @@ internal class NavigationService : INavigationService
|
||||
/// <summary>
|
||||
/// 构造一个新的导航服务
|
||||
/// </summary>
|
||||
/// <param name="infobarService">信息条服务</param>
|
||||
/// <param name="infoBarService">信息条服务</param>
|
||||
/// <param name="logger">日志器</param>
|
||||
public NavigationService(IInfoBarService infobarService, ILogger<INavigationService> logger)
|
||||
public NavigationService(IInfoBarService infoBarService, ILogger<INavigationService> logger)
|
||||
{
|
||||
this.infoBarService = infobarService;
|
||||
this.infoBarService = infoBarService;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ internal class NavigationService : INavigationService
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public NavigationResult Navigate(Type pageType, bool syncNavigationViewItem = false, NavigationExtra? data = null)
|
||||
public NavigationResult Navigate(Type pageType, INavigationAwaiter data, bool syncNavigationViewItem = false)
|
||||
{
|
||||
Type? currentType = Frame?.Content?.GetType();
|
||||
|
||||
@@ -123,22 +123,28 @@ internal class NavigationService : INavigationService
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public NavigationResult Navigate<TPage>(bool syncNavigationViewItem = false, NavigationExtra? data = null)
|
||||
public NavigationResult Navigate<TPage>(INavigationAwaiter data, bool syncNavigationViewItem = false)
|
||||
where TPage : Page
|
||||
{
|
||||
return Navigate(typeof(TPage), syncNavigationViewItem, data);
|
||||
return Navigate(typeof(TPage), data, syncNavigationViewItem);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<NavigationResult> NavigateAsync<TPage>(bool syncNavigationViewItem = false, NavigationExtra? data = null)
|
||||
public async Task<NavigationResult> NavigateAsync<TPage>(INavigationAwaiter data, bool syncNavigationViewItem = false)
|
||||
where TPage : Page
|
||||
{
|
||||
data ??= new NavigationExtra();
|
||||
NavigationResult result = Navigate<TPage>(syncNavigationViewItem, data);
|
||||
NavigationResult result = Navigate<TPage>(data, syncNavigationViewItem);
|
||||
|
||||
if (result is NavigationResult.Succeed)
|
||||
{
|
||||
await data.NavigationCompletedTaskCompletionSource.Task;
|
||||
try
|
||||
{
|
||||
await data.WaitForCompletionAsync();
|
||||
}
|
||||
catch (AggregateException)
|
||||
{
|
||||
return NavigationResult.Failed;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -158,7 +164,8 @@ internal class NavigationService : INavigationService
|
||||
? typeof(SettingPage)
|
||||
: NavHelper.GetNavigateTo(Selected);
|
||||
|
||||
Navigate(Must.NotNull(targetType!), false, new(NavHelper.GetExtraData(Selected)));
|
||||
INavigationAwaiter navigationAwaiter = new NavigationExtra(NavHelper.GetExtraData(Selected));
|
||||
Navigate(Must.NotNull(targetType!), navigationAwaiter, false);
|
||||
}
|
||||
|
||||
private void OnBackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
|
||||
|
||||
@@ -24,7 +24,7 @@ internal class UserService : IUserService
|
||||
private readonly UserGameRoleClient userGameRoleClient;
|
||||
|
||||
private User? currentUser;
|
||||
private ObservableCollection<User>? cachedUser = null;
|
||||
private ObservableCollection<User>? cachedUsers = null;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的用户服务
|
||||
@@ -52,6 +52,7 @@ internal class UserService : IUserService
|
||||
{
|
||||
User.SetSelectionState(currentUser, false);
|
||||
appDbContext.Users.Update(currentUser);
|
||||
appDbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +63,7 @@ internal class UserService : IUserService
|
||||
{
|
||||
User.SetSelectionState(currentUser, true);
|
||||
appDbContext.Users.Update(currentUser);
|
||||
appDbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +74,7 @@ internal class UserService : IUserService
|
||||
if (await user.InitializeAsync(userClient, userGameRoleClient))
|
||||
{
|
||||
appDbContext.Users.Add(user);
|
||||
await appDbContext.SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -79,20 +82,21 @@ internal class UserService : IUserService
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void RemoveUser(User user)
|
||||
public async Task RemoveUserAsync(User user)
|
||||
{
|
||||
appDbContext.Users.Remove(user);
|
||||
await appDbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<ObservableCollection<User>> GetInitializedUsersAsync(ICommand removeCommand)
|
||||
{
|
||||
if (cachedUser == null)
|
||||
if (cachedUsers == null)
|
||||
{
|
||||
appDbContext.Users.Load();
|
||||
cachedUser = appDbContext.Users.Local.ToObservableCollection();
|
||||
cachedUsers = appDbContext.Users.Local.ToObservableCollection();
|
||||
|
||||
foreach (User user in cachedUser)
|
||||
foreach (User user in cachedUsers)
|
||||
{
|
||||
user.RemoveCommand = removeCommand;
|
||||
await user.InitializeAsync(userClient, userGameRoleClient);
|
||||
@@ -101,7 +105,7 @@ internal class UserService : IUserService
|
||||
CurrentUser = await appDbContext.Users.SingleOrDefaultAsync(user => user.IsSelected);
|
||||
}
|
||||
|
||||
return cachedUser;
|
||||
return cachedUsers;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<NavigationView
|
||||
x:Name="NavView"
|
||||
CompactPaneLength="48"
|
||||
OpenPaneLength="200"
|
||||
OpenPaneLength="244"
|
||||
CompactModeThresholdWidth="128"
|
||||
ExpandedModeThresholdWidth="720"
|
||||
IsPaneOpen="True"
|
||||
|
||||
@@ -27,6 +27,6 @@ public sealed partial class MainView : UserControl
|
||||
|
||||
navigationService = Ioc.Default.GetRequiredService<INavigationService>();
|
||||
navigationService.Initialize(NavView, ContentFrame);
|
||||
navigationService.Navigate<Page.AnnouncementPage>(true);
|
||||
navigationService.Navigate<Page.AnnouncementPage>(INavigationAwaiter.Default, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,14 +35,14 @@ openInWebview: function(url){ location.href = url }}";
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
|
||||
if (e.Parameter is NavigationExtra extra)
|
||||
if (e.Parameter is INavigationExtra extra)
|
||||
{
|
||||
targetContent = extra.Data as string;
|
||||
LoadAnnouncementAsync(extra).Forget();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadAnnouncementAsync(NavigationExtra extra)
|
||||
private async Task LoadAnnouncementAsync(INavigationExtra extra)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -51,12 +51,13 @@ openInWebview: function(url){ location.href = url }}";
|
||||
await WebView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(MihoyoSDKDefinition);
|
||||
WebView.CoreWebView2.WebMessageReceived += (_, e) => Browser.Open(e.TryGetWebMessageAsString);
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
extra.NotifyNavigationException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
WebView.NavigateToString(targetContent);
|
||||
extra.NavigationCompletedTaskCompletionSource.TrySetResult();
|
||||
extra.NotifyNavigationCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
xmlns:shvc="using:Snap.Hutao.View.Converter"
|
||||
mc:Ignorable="d"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<mxi:Interaction.Behaviors>
|
||||
<mxic:EventTriggerBehavior EventName="Loaded">
|
||||
<mxic:InvokeCommandAction Command="{Binding OpenUICommand}"/>
|
||||
@@ -46,7 +45,7 @@
|
||||
<cwucont:AdaptiveGridView
|
||||
cwua:ItemsReorderAnimation.Duration="0:0:0.06"
|
||||
SelectionMode="None"
|
||||
DesiredWidth="320"
|
||||
DesiredWidth="280"
|
||||
HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding List}"
|
||||
Margin="0,0,2,0">
|
||||
@@ -70,7 +69,6 @@
|
||||
<Border
|
||||
cwu:UIElementExtensions.ClipToBounds="True">
|
||||
<Border
|
||||
CompositeMode="SourceOver"
|
||||
VerticalAlignment="Top"
|
||||
cwu:VisualExtensions.NormalizedCenterPoint="0.5">
|
||||
<mxi:Interaction.Behaviors>
|
||||
@@ -176,4 +174,4 @@
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</shcc:CancellablePage>
|
||||
</shcc:CancellablePage>
|
||||
@@ -2,7 +2,6 @@
|
||||
x:Class="Snap.Hutao.View.UserView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:Snap.Hutao.View"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
||||
@@ -14,157 +13,188 @@
|
||||
<mxic:InvokeCommandAction Command="{Binding OpenUICommand}"/>
|
||||
</mxic:EventTriggerBehavior>
|
||||
</mxi:Interaction.Behaviors>
|
||||
<Grid Height="48">
|
||||
<Grid Height="48">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<PersonPicture
|
||||
ProfilePicture="{Binding SelectedUser.UserInfo.AvatarUrl,Mode=OneWay}"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="4,0,4,0"
|
||||
Height="40"/>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,0,2"
|
||||
Grid.Column="1"
|
||||
Text="{Binding SelectedUser.UserInfo.Nickname,Mode=OneWay}"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
<Button
|
||||
x:Name="UsersFlyoutButton"
|
||||
Background="Transparent"
|
||||
BorderBrush="{x:Null}"
|
||||
Height="38.4"
|
||||
Content=""
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
Grid.Column="2"
|
||||
Margin="4">
|
||||
<Button.Flyout>
|
||||
<Flyout
|
||||
Placement="TopEdgeAlignedRight"
|
||||
LightDismissOverlayMode="On">
|
||||
<Flyout.FlyoutPresenterStyle>
|
||||
<Style
|
||||
TargetType="FlyoutPresenter"
|
||||
BasedOn="{StaticResource DefaultFlyoutPresenterStyle}">
|
||||
<Setter Property="Padding" Value="0,2,0,2"/>
|
||||
</Style>
|
||||
</Flyout.FlyoutPresenterStyle>
|
||||
<StackPanel Width="192">
|
||||
<ListView
|
||||
Grid.Row="1"
|
||||
Margin="4"
|
||||
SelectionMode="Single"
|
||||
CanReorderItems="True"
|
||||
ItemsSource="{Binding SelectedUser.UserGameRoles}"
|
||||
SelectedItem="{Binding SelectedUser.SelectedUserGameRole,Mode=TwoWay}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Padding="0,6">
|
||||
<TextBlock Text="{Binding Nickname}"/>
|
||||
<TextBlock
|
||||
Margin="0,2,0,0"
|
||||
Opacity="0.6"
|
||||
Text="{Binding Description}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<MenuFlyoutSeparator/>
|
||||
<ListView
|
||||
MaxHeight="224"
|
||||
Grid.Row="1"
|
||||
Margin="4"
|
||||
SelectionMode="Single"
|
||||
ItemsSource="{Binding Users}"
|
||||
SelectedItem="{Binding SelectedUser,Mode=TwoWay}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Padding="0,12" Background="Transparent">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<PersonPicture
|
||||
ProfilePicture="{Binding UserInfo.AvatarUrl,Mode=OneWay}"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="0,0"
|
||||
Height="32"/>
|
||||
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding UserInfo.Nickname}"/>
|
||||
|
||||
<Grid Height="58">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<PersonPicture
|
||||
ProfilePicture="{Binding SelectedUser.UserInfo.AvatarUrl,Mode=OneWay}"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="4,0,4,0"
|
||||
Height="40"/>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,0,2"
|
||||
Grid.Column="1"
|
||||
Text="{Binding SelectedUser.UserInfo.Nickname,Mode=OneWay}"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
<Button
|
||||
x:Name="UsersFlyoutButton"
|
||||
Background="Transparent"
|
||||
BorderBrush="{x:Null}"
|
||||
Height="38.4"
|
||||
Content=""
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
Grid.Column="2"
|
||||
Margin="4">
|
||||
<Button.Flyout>
|
||||
<Flyout
|
||||
Placement="TopEdgeAlignedRight"
|
||||
LightDismissOverlayMode="On">
|
||||
<Flyout.FlyoutPresenterStyle>
|
||||
<Style
|
||||
TargetType="FlyoutPresenter"
|
||||
BasedOn="{StaticResource DefaultFlyoutPresenterStyle}">
|
||||
<Setter Property="Padding" Value="0,2,0,2"/>
|
||||
</Style>
|
||||
</Flyout.FlyoutPresenterStyle>
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
Margin="10,6,0,6"
|
||||
Style="{StaticResource BaseTextBlockStyle}"
|
||||
Text="角色"/>
|
||||
<ListView
|
||||
Grid.Row="1"
|
||||
Margin="4"
|
||||
SelectionMode="Single"
|
||||
CanReorderItems="True"
|
||||
ItemsSource="{Binding SelectedUser.UserGameRoles}"
|
||||
SelectedItem="{Binding SelectedUser.SelectedUserGameRole,Mode=TwoWay}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Padding="0,6">
|
||||
<TextBlock Text="{Binding Nickname}"/>
|
||||
<TextBlock
|
||||
Margin="0,2,0,0"
|
||||
Opacity="0.6"
|
||||
Text="{Binding Description}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<MenuFlyoutSeparator/>
|
||||
<TextBlock
|
||||
Margin="10,6,0,6"
|
||||
Style="{StaticResource BaseTextBlockStyle}"
|
||||
Text="账号"/>
|
||||
<ListView
|
||||
MaxHeight="224"
|
||||
Grid.Row="1"
|
||||
Margin="4"
|
||||
SelectionMode="Single"
|
||||
ItemsSource="{Binding Users}"
|
||||
SelectedItem="{Binding SelectedUser,Mode=TwoWay}">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid
|
||||
Width="200"
|
||||
Padding="0,12"
|
||||
Background="Transparent">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<PersonPicture
|
||||
ProfilePicture="{Binding UserInfo.AvatarUrl,Mode=OneWay}"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="0,0"
|
||||
Height="32"/>
|
||||
<TextBlock
|
||||
Margin="12,0,0,0"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding UserInfo.Nickname}"/>
|
||||
<StackPanel
|
||||
x:Name="ButtonPanel"
|
||||
Orientation="Horizontal"
|
||||
Grid.Column="2"
|
||||
Visibility="Collapsed">
|
||||
<Button
|
||||
x:Name="RemoveUserButton"
|
||||
Content=""
|
||||
Content=""
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Stretch"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
BorderBrush="{x:Null}"
|
||||
Margin="12,0,0,0"
|
||||
Visibility="Collapsed"
|
||||
Command="{Binding CopyCookieCommand}"
|
||||
ToolTipService.ToolTip="复制 Cookie"/>
|
||||
<Button
|
||||
Content=""
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
BorderBrush="{x:Null}"
|
||||
Margin="6,0,0,0"
|
||||
Command="{Binding RemoveCommand}"
|
||||
CommandParameter="{Binding}"/>
|
||||
|
||||
<Grid.Resources>
|
||||
<Storyboard x:Name="RemoveUserButtonVisibleStoryboard">
|
||||
<ObjectAnimationUsingKeyFrames
|
||||
Storyboard.TargetName="RemoveUserButton"
|
||||
Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<Visibility>Visible</Visibility>
|
||||
</DiscreteObjectKeyFrame.Value>
|
||||
</DiscreteObjectKeyFrame>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
CommandParameter="{Binding}"
|
||||
ToolTipService.ToolTip="移除用户"/>
|
||||
</StackPanel>
|
||||
|
||||
<Storyboard x:Name="RemoveUserButtonCollapsedStoryboard">
|
||||
<ObjectAnimationUsingKeyFrames
|
||||
Storyboard.TargetName="RemoveUserButton"
|
||||
Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<Visibility>Collapsed</Visibility>
|
||||
</DiscreteObjectKeyFrame.Value>
|
||||
</DiscreteObjectKeyFrame>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</Grid.Resources>
|
||||
<mxi:Interaction.Behaviors>
|
||||
<mxic:EventTriggerBehavior EventName="PointerEntered">
|
||||
<mxim:ControlStoryboardAction Storyboard="{StaticResource RemoveUserButtonVisibleStoryboard}"/>
|
||||
</mxic:EventTriggerBehavior>
|
||||
<mxic:EventTriggerBehavior EventName="PointerExited">
|
||||
<mxim:ControlStoryboardAction Storyboard="{StaticResource RemoveUserButtonCollapsedStoryboard}"/>
|
||||
</mxic:EventTriggerBehavior>
|
||||
</mxi:Interaction.Behaviors>
|
||||
</Grid>
|
||||
<Grid.Resources>
|
||||
<Storyboard x:Name="ButtonPanelVisibleStoryboard">
|
||||
<ObjectAnimationUsingKeyFrames
|
||||
Storyboard.TargetName="ButtonPanel"
|
||||
Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<Visibility>Visible</Visibility>
|
||||
</DiscreteObjectKeyFrame.Value>
|
||||
</DiscreteObjectKeyFrame>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
|
||||
<Storyboard x:Name="ButtonPanelCollapsedStoryboard">
|
||||
<ObjectAnimationUsingKeyFrames
|
||||
Storyboard.TargetName="ButtonPanel"
|
||||
Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0">
|
||||
<DiscreteObjectKeyFrame.Value>
|
||||
<Visibility>Collapsed</Visibility>
|
||||
</DiscreteObjectKeyFrame.Value>
|
||||
</DiscreteObjectKeyFrame>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</Grid.Resources>
|
||||
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<CommandBar DefaultLabelPosition="Right">
|
||||
<AppBarButton
|
||||
Icon="Add"
|
||||
Label="添加新用户"
|
||||
Command="{Binding AddUserCommand}"
|
||||
CommandParameter="{x:Bind UsersFlyoutButton.Flyout}"/>
|
||||
</CommandBar>
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</Grid>
|
||||
<mxi:Interaction.Behaviors>
|
||||
<mxic:EventTriggerBehavior EventName="PointerEntered">
|
||||
<mxim:ControlStoryboardAction Storyboard="{StaticResource ButtonPanelVisibleStoryboard}"/>
|
||||
</mxic:EventTriggerBehavior>
|
||||
<mxic:EventTriggerBehavior EventName="PointerExited">
|
||||
<mxim:ControlStoryboardAction Storyboard="{StaticResource ButtonPanelCollapsedStoryboard}"/>
|
||||
</mxic:EventTriggerBehavior>
|
||||
</mxi:Interaction.Behaviors>
|
||||
</Grid>
|
||||
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<CommandBar DefaultLabelPosition="Right">
|
||||
<AppBarButton
|
||||
Icon="Add"
|
||||
Label="添加新用户"
|
||||
Command="{Binding AddUserCommand}"
|
||||
CommandParameter="{x:Bind UsersFlyoutButton.Flyout}"/>
|
||||
</CommandBar>
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
<NavigationViewItemSeparator
|
||||
Margin="0,4,0,0"
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="3"
|
||||
VerticalAlignment="Bottom"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -99,7 +99,7 @@ internal class AnnouncementViewModel : ObservableObject, ISupportCancellation
|
||||
|
||||
if (WebView2Helper.IsSupported)
|
||||
{
|
||||
navigationService.Navigate<View.Page.AnnouncementContentPage>(data: new(content));
|
||||
navigationService.Navigate<View.Page.AnnouncementContentPage>(data: new NavigationExtra(content));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Core.Threading;
|
||||
using Snap.Hutao.Factory.Abstraction;
|
||||
@@ -23,8 +22,7 @@ internal class UserViewModel : ObservableObject
|
||||
{
|
||||
private readonly IUserService userService;
|
||||
private readonly IInfoBarService infoBarService;
|
||||
|
||||
private ICommand removeUserCommand;
|
||||
private readonly ICommand removeUserCommandCache;
|
||||
|
||||
private User? selectedUser;
|
||||
private ObservableCollection<User>? userInfos;
|
||||
@@ -43,7 +41,7 @@ internal class UserViewModel : ObservableObject
|
||||
OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
|
||||
AddUserCommand = asyncRelayCommandFactory.Create<Flyout>(AddUserAsync);
|
||||
|
||||
removeUserCommand = new RelayCommand<User>(RemoveUser);
|
||||
removeUserCommandCache = asyncRelayCommandFactory.Create<User>(RemoveUserAsync);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -76,46 +74,36 @@ internal class UserViewModel : ObservableObject
|
||||
/// </summary>
|
||||
public ICommand AddUserCommand { get; }
|
||||
|
||||
private static bool TryValidateCookie(IDictionary<string, string> map, [NotNullWhen(true)] out SortedDictionary<string, string>? filteredCookie)
|
||||
private static bool TryValidateCookie(IDictionary<string, string> map, [NotNullWhen(true)] out IDictionary<string, string>? filteredCookie)
|
||||
{
|
||||
int validFlag = 4;
|
||||
|
||||
filteredCookie = new();
|
||||
filteredCookie = new SortedDictionary<string, string>();
|
||||
|
||||
// O(1) to validate cookie
|
||||
foreach ((string key, string value) in map)
|
||||
{
|
||||
if (key == "account_id")
|
||||
{
|
||||
validFlag--;
|
||||
filteredCookie[key] = value;
|
||||
}
|
||||
|
||||
if (key == "cookie_token")
|
||||
{
|
||||
validFlag--;
|
||||
filteredCookie[key] = value;
|
||||
}
|
||||
|
||||
if (key == "ltoken")
|
||||
{
|
||||
validFlag--;
|
||||
filteredCookie[key] = value;
|
||||
}
|
||||
|
||||
if (key == "ltuid")
|
||||
if (key == "account_id" || key == "cookie_token" || key == "ltoken" || key == "ltuid")
|
||||
{
|
||||
validFlag--;
|
||||
filteredCookie[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return validFlag == 0;
|
||||
if (validFlag == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredCookie = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OpenUIAsync()
|
||||
{
|
||||
Users = await userService.GetInitializedUsersAsync(removeUserCommand);
|
||||
Users = await userService.GetInitializedUsersAsync(removeUserCommandCache);
|
||||
SelectedUser = userService.CurrentUser;
|
||||
}
|
||||
|
||||
@@ -131,28 +119,37 @@ internal class UserViewModel : ObservableObject
|
||||
{
|
||||
IDictionary<string, string> map = userService.ParseCookie(result.Value);
|
||||
|
||||
if (TryValidateCookie(map, out SortedDictionary<string, string>? filteredCookie))
|
||||
if (TryValidateCookie(map, out IDictionary<string, string>? filteredCookie))
|
||||
{
|
||||
string simplifiedCookie = string.Join(';', filteredCookie.Select(kvp => $"{kvp.Key}={kvp.Value}"));
|
||||
User user = new()
|
||||
{
|
||||
Cookie = simplifiedCookie,
|
||||
RemoveCommand = removeUserCommand,
|
||||
RemoveCommand = removeUserCommandCache,
|
||||
};
|
||||
|
||||
if (!await userService.TryAddUserAsync(user))
|
||||
{
|
||||
infoBarService.Warning("提供的Cookie无效!");
|
||||
infoBarService.Warning("此Cookie无法获取用户信息,请重新输入");
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBarService.Success($"成功添加用户 [{user.UserInfo!.Nickname}]");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBarService.Warning("提供的字符串并不是有效的Cookie,请重新输入");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveUser(User? user)
|
||||
private async Task RemoveUserAsync(User? user)
|
||||
{
|
||||
if (!User.IsNone(user))
|
||||
{
|
||||
userService.RemoveUser(user);
|
||||
await userService.RemoveUserAsync(user);
|
||||
infoBarService.Success($"成功移除用户 [{user.UserInfo!.Nickname}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,11 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
/// <inheritdoc/>
|
||||
public async Task<bool> InitializeAsync(CancellationToken token = default)
|
||||
{
|
||||
if (isInitialized)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Auth auth = new(
|
||||
"08d9e212-0cb3-4d71-8ed7-003606da7b20",
|
||||
"7ueWgZGn53dDhrm8L5ZRw+YWfOeSWtgQmJWquRgaygw=");
|
||||
@@ -185,7 +190,7 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取队伍出场次数
|
||||
/// 异步获取队伍出场次数 层间
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>队伍出场列表</returns>
|
||||
@@ -201,7 +206,7 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取队伍出场次数
|
||||
/// 异步获取队伍出场次数 层
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>队伍出场列表</returns>
|
||||
@@ -217,7 +222,7 @@ internal class HutaoClient : ISupportAsyncInitialization
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取队伍出场次数
|
||||
/// 按角色列表异步获取推荐队伍
|
||||
/// </summary>
|
||||
/// <param name="floor">楼层</param>
|
||||
/// <param name="avatarIds">期望的角色,按期望出现顺序排序</param>
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 队伍上场率
|
||||
/// 层间上场率
|
||||
/// </summary>
|
||||
public record TeamCombination
|
||||
{
|
||||
@@ -15,22 +16,6 @@ public record TeamCombination
|
||||
/// </summary>
|
||||
public LevelInfo Level { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 队伍
|
||||
/// </summary>
|
||||
public IEnumerable<Rate<Team>> Teams { get; set; } = null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 队伍上场率2
|
||||
/// </summary>
|
||||
public record TeamCombination2
|
||||
{
|
||||
/// <summary>
|
||||
/// 带有层的间
|
||||
/// </summary>
|
||||
public int Floor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 队伍
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Snap.Hutao.Web.Hutao.Model;
|
||||
|
||||
/// <summary>
|
||||
/// 队伍上场率2
|
||||
/// 层上场率
|
||||
/// </summary>
|
||||
public record TeamCombination2
|
||||
{
|
||||
/// <summary>
|
||||
/// 带有层的间
|
||||
/// </summary>
|
||||
public int Floor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 队伍
|
||||
/// </summary>
|
||||
public IEnumerable<Rate<Team>> Teams { get; set; } = null!;
|
||||
}
|
||||
@@ -27,7 +27,14 @@ public class Response : ISupportValidation
|
||||
{
|
||||
Ioc.Default
|
||||
.GetRequiredService<IInfoBarService>()
|
||||
.Information(ToString());
|
||||
.Error(ToString());
|
||||
}
|
||||
|
||||
if (ReturnCode != 0)
|
||||
{
|
||||
Ioc.Default
|
||||
.GetRequiredService<IInfoBarService>()
|
||||
.Warning(ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ public class Response<TData> : Response
|
||||
/// <param name="returnCode">返回代码</param>
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="data">数据</param>
|
||||
[JsonConstructor]
|
||||
public Response(int returnCode, string message, TData? data)
|
||||
: base(returnCode, message)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user