From b8895d82501b3f4843f1237f2f7fbe0c1df5d25f Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Fri, 14 Apr 2023 15:48:00 +0800 Subject: [PATCH] update to was 1.3 and fix upload spiralabyss --- .../ExceptionService/ExceptionRecorder.cs | 6 + .../Core/Windowing/ExtendedWindow.cs | 48 ++- .../Core/Windowing/SystemBackdrop.cs | 181 ----------- .../Core/Windowing/WindowOptions.cs | 9 +- .../Factory/GachaStatisticsFactory.cs | 123 ++++---- .../Factory/GachaStatisticsSlimFactory.cs | 87 ++++++ .../GachaLog/Factory/HistoryWishBuilder.cs | 13 +- .../Factory/IGachaStatisticsFactory.cs | 3 +- .../Factory/IGachaStatisticsSlimFactory.cs | 21 ++ .../Factory/TypedWishSummaryBuilder.cs | 2 +- .../Service/GachaLog/GachaLogImportService.cs | 28 +- .../Service/GachaLog/GachaLogService.cs | 54 ++-- .../Service/GachaLog/IGachaLogService.cs | 6 + .../Service/Hutao/HutaoUserOptions.cs | 2 +- .../Service/Hutao/HutaoUserService.cs | 1 - src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 26 +- .../View/Card/GachaStatisticsCard.xaml | 286 ++++++++++++++++++ .../View/Card/GachaStatisticsCard.xaml.cs | 20 ++ .../Snap.Hutao/View/Card/LaunchGameCard.xaml | 73 +++++ .../View/Card/LaunchGameCard.xaml.cs | 20 ++ .../View/Control/LoadingViewSlim.xaml | 13 + .../View/Control/LoadingViewSlim.xaml.cs | 20 ++ .../View/Page/AnnouncementPage.xaml | 138 +-------- .../ViewModel/Abstraction/ViewModel.cs | 1 - .../ViewModel/Abstraction/ViewModelSlim.cs | 7 + .../ViewModel/AnnouncementViewModel.cs | 6 + .../GachaLog/GachaLogViewModelSlim.cs | 14 +- .../ViewModel/GachaLog/GachaStatisticsSlim.cs | 6 +- .../GachaLog/TypedWishSummarySlim.cs | 13 + .../Event/GachaInfo/GachaLogQueryOptions.cs | 16 +- .../Web/Hutao/Model/Post/SimpleRecord.cs | 1 + .../Snap.Hutao/Web/HutaoEndpoints.cs | 1 + 32 files changed, 770 insertions(+), 475 deletions(-) delete mode 100644 src/Snap.Hutao/Snap.Hutao/Core/Windowing/SystemBackdrop.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsSlimFactory.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsSlimFactory.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml create mode 100644 src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml create mode 100644 src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/View/Control/LoadingViewSlim.xaml create mode 100644 src/Snap.Hutao/Snap.Hutao/View/Control/LoadingViewSlim.xaml.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionRecorder.cs b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionRecorder.cs index a41c515f..306f54a2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionRecorder.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ExceptionRecorder.cs @@ -26,6 +26,7 @@ internal sealed class ExceptionRecorder application.UnhandledException += OnAppUnhandledException; application.DebugSettings.BindingFailed += OnXamlBindingFailed; + application.DebugSettings.XamlResourceReferenceFailed += OnXamlResourceReferenceFailed; } private void OnAppUnhandledException(object? sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) @@ -51,4 +52,9 @@ internal sealed class ExceptionRecorder { logger.LogCritical("XAML绑定失败: {message}", e.Message); } + + private void OnXamlResourceReferenceFailed(DebugSettings sender, XamlResourceReferenceFailedEventArgs e) + { + logger.LogCritical("XAML资源引用失败: {message}", e.Message); + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs index 1ba026b5..5b847406 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/ExtendedWindow.cs @@ -3,9 +3,12 @@ using CommunityToolkit.Mvvm.Messaging; using Microsoft.UI; +using Microsoft.UI.Composition.SystemBackdrops; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Media; using Snap.Hutao.Message; +using Snap.Hutao.Service; using Snap.Hutao.Win32; using System.IO; using Windows.Graphics; @@ -27,8 +30,6 @@ internal sealed class ExtendedWindow : IRecipient> logger; private readonly WindowSubclass subclass; - private SystemBackdrop? systemBackdrop; - private ExtendedWindow(TWindow window, FrameworkElement titleBar, IServiceProvider serviceProvider) { options = new(window, titleBar); @@ -54,7 +55,7 @@ internal sealed class ExtendedWindow : IRecipient public void Receive(FlyoutOpenCloseMessage message) { - UpdateDragRectangles(options.AppWindow.TitleBar, message.IsOpen); + UpdateDragRectangles(message.IsOpen); } private void InitializeWindow() @@ -69,9 +70,9 @@ internal sealed class ExtendedWindow : IRecipient(); + UpdateSystemBackdrop(appOptions.BackdropType); + appOptions.PropertyChanged += OnOptionsPropertyChanged; bool subClassApplied = subclass.Initialize(); logger.LogInformation("Apply {name} : {result}", nameof(WindowSubclass), subClassApplied ? "succeed" : "failed"); @@ -82,6 +83,14 @@ internal sealed class ExtendedWindow : IRecipient : IRecipient UpdateTitleButtonColor(appTitleBar); - options.TitleBar.SizeChanged += (s, e) => UpdateDragRectangles(appTitleBar); + UpdateTitleButtonColor(); + UpdateDragRectangles(); + options.TitleBar.ActualThemeChanged += (s, e) => UpdateTitleButtonColor(); + options.TitleBar.SizeChanged += (s, e) => UpdateDragRectangles(); } } - private void UpdateTitleButtonColor(AppWindowTitleBar appTitleBar) + private void UpdateSystemBackdrop(BackdropType backdropType) { + options.Window.SystemBackdrop = backdropType switch + { + BackdropType.MicaAlt => new MicaBackdrop() { Kind = MicaKind.BaseAlt }, + BackdropType.Mica => new MicaBackdrop() { Kind = MicaKind.Base }, + BackdropType.Acrylic => new DesktopAcrylicBackdrop(), + _ => null, + }; + } + + private void UpdateTitleButtonColor() + { + AppWindowTitleBar appTitleBar = options.AppWindow.TitleBar; + appTitleBar.ButtonBackgroundColor = Colors.Transparent; appTitleBar.ButtonInactiveBackgroundColor = Colors.Transparent; @@ -137,8 +159,10 @@ internal sealed class ExtendedWindow : IRecipient -/// 系统背景帮助类 -/// -internal sealed class SystemBackdrop -{ - private readonly Window window; - - private DispatcherQueueHelper? dispatcherQueueHelper; - private ISystemBackdropControllerWithTargets? backdropController; - private SystemBackdropConfiguration? configuration; - - private BackdropType type; - - /// - /// 构造一个新的系统背景帮助类 - /// - /// 窗体 - /// 服务提供器 - public SystemBackdrop(Window window, IServiceProvider serviceProvider) - { - this.window = window; - AppOptions appOptions = serviceProvider.GetRequiredService(); - type = appOptions.BackdropType; - appOptions.PropertyChanged += OnOptionsPropertyChanged; - } - - /// - /// 尝试设置背景 - /// - /// 是否设置成功 - public bool Update() - { - bool isSupport = type switch - { - BackdropType.Acrylic => DesktopAcrylicController.IsSupported(), - BackdropType.Mica or BackdropType.MicaAlt => MicaController.IsSupported(), - _ => false, - }; - - if (!isSupport) - { - return false; - } - else - { - // Previous one - if (backdropController != null) - { - backdropController.RemoveAllSystemBackdropTargets(); - } - else - { - dispatcherQueueHelper = new(); - dispatcherQueueHelper.Ensure(); - } - - // Hooking up the policy object - configuration = new() - { - IsInputActive = true, // Initial configuration state. - }; - SetConfigurationSourceTheme(configuration); - - window.Activated += OnWindowActivated; - window.Closed += OnWindowClosed; - ((FrameworkElement)window.Content).ActualThemeChanged += OnWindowThemeChanged; - - backdropController = type switch - { - BackdropType.Acrylic => new DesktopAcrylicController(), - BackdropType.Mica => new MicaController() { Kind = MicaKind.Base }, - BackdropType.MicaAlt => new MicaController() { Kind = MicaKind.BaseAlt }, - _ => throw Must.NeverHappen(), - }; - - backdropController.AddSystemBackdropTarget(window.As()); - backdropController.SetSystemBackdropConfiguration(configuration); - - return true; - } - } - - private void OnOptionsPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(AppOptions.BackdropType)) - { - type = ((AppOptions)sender!).BackdropType; - Update(); - } - } - - private void OnWindowActivated(object sender, WindowActivatedEventArgs args) - { - configuration!.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated; - } - - private void OnWindowClosed(object sender, WindowEventArgs args) - { - // Make sure any Mica/Acrylic controller is disposed so it doesn't try to - // use this closed window. - if (backdropController != null) - { - backdropController.Dispose(); - backdropController = null; - } - - window.Activated -= OnWindowActivated; - configuration = null; - } - - private void OnWindowThemeChanged(FrameworkElement sender, object args) - { - if (configuration != null) - { - SetConfigurationSourceTheme(configuration); - } - } - - private void SetConfigurationSourceTheme(SystemBackdropConfiguration configuration) - { - configuration.Theme = ThemeHelper.ElementToSystemBackdrop(((FrameworkElement)window.Content).ActualTheme); - } - - private class DispatcherQueueHelper - { - private object? dispatcherQueueController; - - /// - /// 确保系统调度队列控制器存在 - /// - public unsafe void Ensure() - { - if (DispatcherQueue.GetForCurrentThread() != null) - { - // one already exists, so we'll just use it. - return; - } - - if (dispatcherQueueController == null) - { - DispatcherQueueOptions options = new() - { - DwSize = sizeof(DispatcherQueueOptions), - ThreadType = 2, // DQTYPE_THREAD_CURRENT - ApartmentType = 2, // DQTAT_COM_STA - }; - - _ = CreateDispatcherQueueController(options, ref dispatcherQueueController); - } - } - - [DllImport("CoreMessaging.dll")] - private static extern int CreateDispatcherQueueController( - [In] DispatcherQueueOptions options, - [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object? dispatcherQueueController); - - private struct DispatcherQueueOptions - { - internal int DwSize; - internal int ThreadType; - internal int ApartmentType; - } - } -} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs index 00866ee0..6d8bc291 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowOptions.cs @@ -41,13 +41,16 @@ internal readonly struct WindowOptions /// public readonly bool UseLegacyDragBarImplementation = !AppWindowTitleBar.IsCustomizationSupported(); + /// + /// 构造一个新的窗体选项 + /// + /// 窗体 + /// 标题栏 public WindowOptions(TWindow window, FrameworkElement titleBar) { Window = window; Hwnd = (HWND)WindowNative.GetWindowHandle(window); - WindowId windowId = Win32Interop.GetWindowIdFromWindow(Hwnd); - AppWindow = AppWindow.GetFromWindowId(windowId); - + AppWindow = window.AppWindow; TitleBar = titleBar; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs index 0f3d2908..16830a52 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsFactory.cs @@ -1,10 +1,8 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Snap.Hutao.Core.Database; using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Model.Entity; -using Snap.Hutao.Model.Entity.Database; using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata; using Snap.Hutao.Model.Metadata.Avatar; @@ -37,31 +35,22 @@ internal sealed class GachaStatisticsFactory : IGachaStatisticsFactory } /// - public async Task CreateAsync(IEnumerable items) + public async Task CreateAsync(IOrderedQueryable items, GachaLogServiceContext context) { - Dictionary idAvatarMap = await metadataService.GetIdToAvatarMapAsync().ConfigureAwait(false); - Dictionary idWeaponMap = await metadataService.GetIdToWeaponMapAsync().ConfigureAwait(false); - - Dictionary nameAvatarMap = await metadataService.GetNameToAvatarMapAsync().ConfigureAwait(false); - Dictionary nameWeaponMap = await metadataService.GetNameToWeaponMapAsync().ConfigureAwait(false); - List gachaEvents = await metadataService.GetGachaEventsAsync().ConfigureAwait(false); - List historyWishBuilders = gachaEvents.Select(g => new HistoryWishBuilder(g, nameAvatarMap, nameWeaponMap)).ToList(); + List historyWishBuilders = gachaEvents.Select(g => new HistoryWishBuilder(g, context)).ToList(); - IOrderedEnumerable orderedItems = items.OrderBy(i => i.Id); - await ThreadHelper.SwitchToBackgroundAsync(); - return CreateCore(orderedItems, historyWishBuilders, idAvatarMap, idWeaponMap, options.IsEmptyHistoryWishVisible); + return CreateCore(items, historyWishBuilders, context, options.IsEmptyHistoryWishVisible); } private static GachaStatistics CreateCore( - IOrderedEnumerable items, + IOrderedQueryable items, List historyWishBuilders, - Dictionary avatarMap, - Dictionary weaponMap, + GachaLogServiceContext context, bool isEmptyHistoryWishVisible) { - TypedWishSummaryBuilder standardWishBuilder = new(SH.ServiceGachaLogFactoryPermanentWishName, TypedWishSummaryBuilder.IsPermanentWish, 90, 10); + TypedWishSummaryBuilder standardWishBuilder = new(SH.ServiceGachaLogFactoryPermanentWishName, TypedWishSummaryBuilder.IsStandardWish, 90, 10); TypedWishSummaryBuilder avatarWishBuilder = new(SH.ServiceGachaLogFactoryAvatarWishName, TypedWishSummaryBuilder.IsAvatarEventWish, 90, 10); TypedWishSummaryBuilder weaponWishBuilder = new(SH.ServiceGachaLogFactoryWeaponWishName, TypedWishSummaryBuilder.IsWeaponEventWish, 80, 10); @@ -81,58 +70,62 @@ internal sealed class GachaStatisticsFactory : IGachaStatisticsFactory .SingleOrDefault(w => w.From <= item.Time && w.To >= item.Time); // It's an avatar - if (item.ItemId.Place() == 8) + switch (item.ItemId.Place()) { - Avatar avatar = avatarMap[item.ItemId]; + case 8: + { + Avatar avatar = context.IdAvatarMap[item.ItemId]; - bool isUp = false; - switch (avatar.Quality) - { - case ItemQuality.QUALITY_ORANGE: - orangeAvatarCounter.Increase(avatar); - isUp = targetHistoryWishBuilder?.IncreaseOrange(avatar) ?? false; - break; - case ItemQuality.QUALITY_PURPLE: - purpleAvatarCounter.Increase(avatar); - targetHistoryWishBuilder?.IncreasePurple(avatar); - break; - } + bool isUp = false; + switch (avatar.Quality) + { + case ItemQuality.QUALITY_ORANGE: + orangeAvatarCounter.Increase(avatar); + isUp = targetHistoryWishBuilder?.IncreaseOrange(avatar) ?? false; + break; + case ItemQuality.QUALITY_PURPLE: + purpleAvatarCounter.Increase(avatar); + targetHistoryWishBuilder?.IncreasePurple(avatar); + break; + } - standardWishBuilder.Track(item, avatar, isUp); - avatarWishBuilder.Track(item, avatar, isUp); - weaponWishBuilder.Track(item, avatar, isUp); - } - - // It's a weapon - else if (item.ItemId.Place() == 5) - { - Weapon weapon = weaponMap[item.ItemId]; - - bool isUp = false; - switch (weapon.RankLevel) - { - case ItemQuality.QUALITY_ORANGE: - isUp = targetHistoryWishBuilder?.IncreaseOrange(weapon) ?? false; - orangeWeaponCounter.Increase(weapon); + standardWishBuilder.Track(item, avatar, isUp); + avatarWishBuilder.Track(item, avatar, isUp); + weaponWishBuilder.Track(item, avatar, isUp); break; - case ItemQuality.QUALITY_PURPLE: - targetHistoryWishBuilder?.IncreasePurple(weapon); - purpleWeaponCounter.Increase(weapon); - break; - case ItemQuality.QUALITY_BLUE: - targetHistoryWishBuilder?.IncreaseBlue(weapon); - blueWeaponCounter.Increase(weapon); - break; - } + } - standardWishBuilder.Track(item, weapon, isUp); - avatarWishBuilder.Track(item, weapon, isUp); - weaponWishBuilder.Track(item, weapon, isUp); - } - else - { - // ItemId place not correct. - ThrowHelper.UserdataCorrupted(string.Format(SH.ServiceGachaStatisticsFactoryItemIdInvalid, item.ItemId), null!); + case 5: + { + Weapon weapon = context.IdWeaponMap[item.ItemId]; + + bool isUp = false; + switch (weapon.RankLevel) + { + case ItemQuality.QUALITY_ORANGE: + isUp = targetHistoryWishBuilder?.IncreaseOrange(weapon) ?? false; + orangeWeaponCounter.Increase(weapon); + break; + case ItemQuality.QUALITY_PURPLE: + targetHistoryWishBuilder?.IncreasePurple(weapon); + purpleWeaponCounter.Increase(weapon); + break; + case ItemQuality.QUALITY_BLUE: + targetHistoryWishBuilder?.IncreaseBlue(weapon); + blueWeaponCounter.Increase(weapon); + break; + } + + standardWishBuilder.Track(item, weapon, isUp); + avatarWishBuilder.Track(item, weapon, isUp); + weaponWishBuilder.Track(item, weapon, isUp); + break; + } + + default: + // ItemId place not correct. + ThrowHelper.UserdataCorrupted(string.Format(SH.ServiceGachaStatisticsFactoryItemIdInvalid, item.ItemId), null!); + break; } } @@ -161,4 +154,4 @@ internal sealed class GachaStatisticsFactory : IGachaStatisticsFactory WeaponWish = weaponWishBuilder.ToTypedWishSummary(), }; } -} +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsSlimFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsSlimFactory.cs new file mode 100644 index 00000000..d3660c5c --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaStatisticsSlimFactory.cs @@ -0,0 +1,87 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Model.Entity; +using Snap.Hutao.Model.Intrinsic; +using Snap.Hutao.Model.Metadata.Abstraction; +using Snap.Hutao.ViewModel.GachaLog; +using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo; + +namespace Snap.Hutao.Service.GachaLog.Factory; + +/// +/// 简化的祈愿统计工厂 +/// +[Injection(InjectAs.Scoped, typeof(IGachaStatisticsSlimFactory))] +internal sealed class GachaStatisticsSlimFactory : IGachaStatisticsSlimFactory +{ + /// + public async Task CreateAsync(IOrderedQueryable items, GachaLogServiceContext context) + { + await ThreadHelper.SwitchToBackgroundAsync(); + + int standardOrangeTracker = 0; + int standardPurpleTracker = 0; + TypedWishSummarySlim standardWish = new(SH.ServiceGachaLogFactoryPermanentWishName, 90, 10); + + int avatarOrangeTracker = 0; + int avatarPurpleTracker = 0; + TypedWishSummarySlim avatarWish = new(SH.ServiceGachaLogFactoryAvatarWishName, 90, 10); + + int weaponOrangeTracker = 0; + int weaponPurpleTracker = 0; + TypedWishSummarySlim weaponWish = new(SH.ServiceGachaLogFactoryWeaponWishName, 80, 10); + + // O(n) operation + foreach (GachaItem item in items) + { + INameQuality nameQuality = context.GetNameQualityByItemId(item.ItemId); + switch (item.QueryType) + { + case GachaConfigType.StandardWish: + Track(nameQuality, ref standardOrangeTracker, ref standardPurpleTracker); + break; + case GachaConfigType.AvatarEventWish: + case GachaConfigType.AvatarEventWish2: + Track(nameQuality, ref avatarOrangeTracker, ref avatarPurpleTracker); + break; + case GachaConfigType.WeaponEventWish: + Track(nameQuality, ref weaponOrangeTracker, ref weaponPurpleTracker); + break; + } + } + + standardWish.LastOrangePull = standardOrangeTracker; + standardWish.LastPurplePull = standardPurpleTracker; + avatarWish.LastOrangePull = avatarOrangeTracker; + avatarWish.LastPurplePull = avatarPurpleTracker; + weaponWish.LastOrangePull = weaponOrangeTracker; + weaponWish.LastPurplePull = weaponPurpleTracker; + + return new() + { + AvatarWish = avatarWish, + WeaponWish = weaponWish, + StandardWish = standardWish, + }; + } + + private static void Track(INameQuality nameQuality, ref int orangeTracker, ref int purpleTracker) + { + switch (nameQuality.Quality) + { + case ItemQuality.QUALITY_ORANGE: + orangeTracker = 0; + ++purpleTracker; + break; + case ItemQuality.QUALITY_PURPLE: + ++orangeTracker; + purpleTracker = 0; + break; + case ItemQuality.QUALITY_BLUE: + ++orangeTracker; + ++purpleTracker; + break; + } + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HistoryWishBuilder.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HistoryWishBuilder.cs index 8c7709a4..50717092 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HistoryWishBuilder.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/HistoryWishBuilder.cs @@ -31,22 +31,21 @@ internal sealed class HistoryWishBuilder /// 构造一个新的卡池历史记录建造器 /// /// 卡池配置 - /// 命名角色映射 - /// 命名武器映射 - public HistoryWishBuilder(GachaEvent gachaEvent, Dictionary nameAvatarMap, Dictionary nameWeaponMap) + /// 祈愿记录上下文 + public HistoryWishBuilder(GachaEvent gachaEvent, GachaLogServiceContext context) { this.gachaEvent = gachaEvent; configType = gachaEvent.Type; if (configType == GachaConfigType.AvatarEventWish || configType == GachaConfigType.AvatarEventWish2) { - orangeUpCounter = gachaEvent.UpOrangeList.Select(name => nameAvatarMap[name]).ToDictionary(a => (IStatisticsItemSource)a, a => 0); - purpleUpCounter = gachaEvent.UpPurpleList.Select(name => nameAvatarMap[name]).ToDictionary(a => (IStatisticsItemSource)a, a => 0); + orangeUpCounter = gachaEvent.UpOrangeList.Select(name => context.NameAvatarMap[name]).ToDictionary(a => (IStatisticsItemSource)a, a => 0); + purpleUpCounter = gachaEvent.UpPurpleList.Select(name => context.NameAvatarMap[name]).ToDictionary(a => (IStatisticsItemSource)a, a => 0); } else if (configType == GachaConfigType.WeaponEventWish) { - orangeUpCounter = gachaEvent.UpOrangeList.Select(name => nameWeaponMap[name]).ToDictionary(w => (IStatisticsItemSource)w, w => 0); - purpleUpCounter = gachaEvent.UpPurpleList.Select(name => nameWeaponMap[name]).ToDictionary(w => (IStatisticsItemSource)w, w => 0); + orangeUpCounter = gachaEvent.UpOrangeList.Select(name => context.NameWeaponMap[name]).ToDictionary(w => (IStatisticsItemSource)w, w => 0); + purpleUpCounter = gachaEvent.UpPurpleList.Select(name => context.NameWeaponMap[name]).ToDictionary(w => (IStatisticsItemSource)w, w => 0); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsFactory.cs index bb66ee88..0d100e87 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsFactory.cs @@ -16,6 +16,7 @@ internal interface IGachaStatisticsFactory /// 异步创建祈愿统计对象 /// /// 物品列表 + /// 祈愿记录上下文 /// 祈愿统计对象 - Task CreateAsync(IEnumerable items); + Task CreateAsync(IOrderedQueryable items, GachaLogServiceContext context); } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsSlimFactory.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsSlimFactory.cs new file mode 100644 index 00000000..c7e8df33 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/IGachaStatisticsSlimFactory.cs @@ -0,0 +1,21 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Model.Entity; +using Snap.Hutao.ViewModel.GachaLog; + +namespace Snap.Hutao.Service.GachaLog.Factory; + +/// +/// 简化的祈愿统计工厂 +/// +internal interface IGachaStatisticsSlimFactory +{ + /// + /// 异步创建一个新的简化的祈愿统计 + /// + /// 排序的物品 + /// 祈愿记录服务上下文 + /// 简化的祈愿统计 + Task CreateAsync(IOrderedQueryable items, GachaLogServiceContext context); +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/TypedWishSummaryBuilder.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/TypedWishSummaryBuilder.cs index eb0b1f87..07501fa8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/TypedWishSummaryBuilder.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/TypedWishSummaryBuilder.cs @@ -18,7 +18,7 @@ internal sealed class TypedWishSummaryBuilder /// /// 常驻祈愿 /// - public static readonly Func IsPermanentWish = type => type is GachaConfigType.StandardWish; + public static readonly Func IsStandardWish = type => type is GachaConfigType.StandardWish; /// /// 角色活动 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogImportService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogImportService.cs index 4c0bb935..dd9691d4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogImportService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogImportService.cs @@ -1,26 +1,10 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using CommunityToolkit.Mvvm.Messaging; -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; using Snap.Hutao.Core.Database; -using Snap.Hutao.Core.Diagnostics; -using Snap.Hutao.Core.ExceptionService; -using Snap.Hutao.Model.Binding; using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity.Database; using Snap.Hutao.Model.InterChange.GachaLog; -using Snap.Hutao.Model.Metadata.Abstraction; -using Snap.Hutao.Model.Primitive; -using Snap.Hutao.Service.GachaLog.Factory; -using Snap.Hutao.Service.GachaLog.QueryProvider; -using Snap.Hutao.Service.Metadata; -using Snap.Hutao.ViewModel.GachaLog; -using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo; -using Snap.Hutao.Web.Response; -using System.Collections.Immutable; -using System.Collections.ObjectModel; namespace Snap.Hutao.Service.GachaLog; @@ -61,19 +45,9 @@ internal sealed class GachaLogImportService : IGachaLogImportService IEnumerable toAdd = list .OrderByDescending(i => i.Id) .Where(i => i.Id < trimId) - .Select(i => GachaItem.Create(archiveId, i, GetItemId(context, i))); + .Select(i => GachaItem.Create(archiveId, i, context.GetItemId(i))); await appDbContext.GachaItems.AddRangeAndSaveAsync(toAdd).ConfigureAwait(false); return archive; } - - private static int GetItemId(GachaLogServiceContext context, GachaLogItem item) - { - return item.ItemType switch - { - "角色" => context.NameAvatarMap.GetValueOrDefault(item.Name)?.Id ?? 0, - "武器" => context.NameWeaponMap.GetValueOrDefault(item.Name)?.Id ?? 0, - _ => 0, - }; - } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs index 54606666..6b326d5d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/GachaLogService.cs @@ -34,11 +34,10 @@ internal sealed class GachaLogService : IGachaLogService private readonly AppDbContext appDbContext; private readonly IGachaLogExportService gachaLogExportService; private readonly IGachaLogImportService gachaLogImportService; - - private readonly IEnumerable urlProviders; private readonly GachaInfoClient gachaInfoClient; private readonly IMetadataService metadataService; private readonly IGachaStatisticsFactory gachaStatisticsFactory; + private readonly IGachaStatisticsSlimFactory gachaStatisticsSlimFactory; private readonly ILogger logger; private readonly DbCurrent dbCurrent; @@ -48,32 +47,17 @@ internal sealed class GachaLogService : IGachaLogService /// 构造一个新的祈愿记录服务 /// /// 服务提供器 - /// 数据库上下文 - /// Url提供器集合 - /// 祈愿记录客户端 - /// 元数据服务 - /// 祈愿统计工厂 - /// 日志器 /// 消息器 - public GachaLogService( - IServiceProvider serviceProvider, - AppDbContext appDbContext, - IEnumerable urlProviders, - GachaInfoClient gachaInfoClient, - IMetadataService metadataService, - IGachaStatisticsFactory gachaStatisticsFactory, - ILogger logger, - IMessenger messenger) + public GachaLogService(IServiceProvider serviceProvider, IMessenger messenger) { gachaLogExportService = serviceProvider.GetRequiredService(); gachaLogImportService = serviceProvider.GetRequiredService(); - - this.appDbContext = appDbContext; - this.urlProviders = urlProviders; - this.gachaInfoClient = gachaInfoClient; - this.metadataService = metadataService; - this.logger = logger; - this.gachaStatisticsFactory = gachaStatisticsFactory; + appDbContext = serviceProvider.GetRequiredService(); + gachaInfoClient = serviceProvider.GetRequiredService(); + metadataService = serviceProvider.GetRequiredService(); + logger = serviceProvider.GetRequiredService>(); + gachaStatisticsFactory = serviceProvider.GetRequiredService(); + gachaStatisticsSlimFactory = serviceProvider.GetRequiredService(); dbCurrent = new(appDbContext.GachaArchives, messenger); } @@ -127,8 +111,8 @@ internal sealed class GachaLogService : IGachaLogService { using (ValueStopwatch.MeasureExecution(logger)) { - IQueryable items = appDbContext.GachaItems.Where(i => i.ArchiveId == archive.InnerId); - return await gachaStatisticsFactory.CreateAsync(items).ConfigureAwait(false); + IOrderedQueryable items = appDbContext.GachaItems.Where(i => i.ArchiveId == archive.InnerId).OrderBy(i => i.Id); + return await gachaStatisticsFactory.CreateAsync(items, context).ConfigureAwait(false); } } else @@ -137,6 +121,24 @@ internal sealed class GachaLogService : IGachaLogService } } + /// + public async Task> GetStatisticsSlimsAsync() + { + List statistics = new(); + foreach (GachaArchive archive in appDbContext.GachaArchives) + { + IOrderedQueryable items = appDbContext.GachaItems + .Where(i => i.ArchiveId == archive.InnerId) + .OrderBy(i => i.Id); + + GachaStatisticsSlim slim = await gachaStatisticsSlimFactory.CreateAsync(items, context).ConfigureAwait(false); + slim.Uid = archive.Uid; + statistics.Add(slim); + } + + return statistics; + } + /// public Task ExportToUIGFAsync(GachaArchive archive) { diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IGachaLogService.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IGachaLogService.cs index f9b8421a..7385494c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IGachaLogService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/IGachaLogService.cs @@ -40,6 +40,12 @@ internal interface IGachaLogService /// 祈愿统计 Task GetStatisticsAsync(GachaArchive? archive); + /// + /// 异步获取简化的祈愿统计列表 + /// + /// 简化的祈愿统计列表 + Task> GetStatisticsSlimsAsync(); + /// /// 异步从UIGF导入数据 /// diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs index 569a8e5f..60258322 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs @@ -25,7 +25,7 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions /// 真正的用户名 /// - public string? ActualUserName { get => IsLoggedIn ? null : UserName; } + public string? ActualUserName { get => IsLoggedIn ? UserName : null; } /// /// 访问令牌 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserService.cs index 38648cfe..12480546 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserService.cs @@ -51,7 +51,6 @@ internal sealed class HutaoUserService : IHutaoUserService, IHutaoUserServiceIni { await ThreadHelper.SwitchToMainThreadAsync(); options.LoginSucceed(userName, response.Data); - isInitialized = true; } else diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 29f73ff5..387d4852 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -106,12 +106,15 @@ + + + @@ -236,8 +239,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -254,7 +257,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -293,6 +296,18 @@ + + + MSBuild:Compile + + + + + + MSBuild:Compile + + + MSBuild:Compile @@ -540,4 +555,9 @@ MSBuild:Compile + + + MSBuild:Compile + + diff --git a/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml b/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml new file mode 100644 index 00000000..a8f85e48 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml @@ -0,0 +1,286 @@ + diff --git a/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml.cs new file mode 100644 index 00000000..90563b17 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml.cs @@ -0,0 +1,20 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.UI.Xaml.Controls; + +namespace Snap.Hutao.View.Card; + +/// +/// Ը¼Ƭ +/// +internal sealed partial class GachaStatisticsCard : Button +{ + /// + /// һµԸ¼Ƭ + /// + public GachaStatisticsCard() + { + InitializeComponent(); + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml b/src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml new file mode 100644 index 00000000..1f2af0fa --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml @@ -0,0 +1,73 @@ + diff --git a/src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml.cs new file mode 100644 index 00000000..aea7e9bb --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/View/Card/LaunchGameCard.xaml.cs @@ -0,0 +1,20 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.UI.Xaml.Controls; + +namespace Snap.Hutao.View.Card; + +/// +/// 启动游戏卡片 +/// +internal sealed partial class LaunchGameCard : Button +{ + /// + /// 构造一个新的启动游戏卡片 + /// + public LaunchGameCard() + { + InitializeComponent(); + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/View/Control/LoadingViewSlim.xaml b/src/Snap.Hutao/Snap.Hutao/View/Control/LoadingViewSlim.xaml new file mode 100644 index 00000000..405dc406 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/View/Control/LoadingViewSlim.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/src/Snap.Hutao/Snap.Hutao/View/Control/LoadingViewSlim.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Control/LoadingViewSlim.xaml.cs new file mode 100644 index 00000000..bfb48998 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/View/Control/LoadingViewSlim.xaml.cs @@ -0,0 +1,20 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using CommunityToolkit.WinUI.UI.Controls; + +namespace Snap.Hutao.View.Control; + +/// +/// 򵥵ļͼ +/// +public sealed partial class LoadingViewSlim : Loading +{ + /// + /// һµļ򵥵ļͼ + /// + public LoadingViewSlim() + { + InitializeComponent(); + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml index 62c73c69..81582109 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml @@ -17,7 +17,8 @@ xmlns:shci="using:Snap.Hutao.Control.Image" xmlns:shcm="using:Snap.Hutao.Control.Markup" xmlns:shv="using:Snap.Hutao.ViewModel" - xmlns:shvc="using:Snap.Hutao.View.Control" + xmlns:shvca="using:Snap.Hutao.View.Card" + xmlns:shvco="using:Snap.Hutao.View.Control" d:DataContext="{d:DesignInstance shv:AnnouncementViewModel}" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" mc:Ignorable="d"> @@ -132,7 +133,7 @@ - + @@ -168,137 +169,8 @@ DesiredWidth="300" ItemContainerStyle="{StaticResource LargeGridViewItemStyle}" SelectionMode="None"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Abstraction/ViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Abstraction/ViewModel.cs index 39904b18..138efb94 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Abstraction/ViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Abstraction/ViewModel.cs @@ -3,7 +3,6 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using Snap.Hutao.Service.Navigation; namespace Snap.Hutao.ViewModel.Abstraction; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Abstraction/ViewModelSlim.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Abstraction/ViewModelSlim.cs index f3bd113a..e9a91cf3 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Abstraction/ViewModelSlim.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Abstraction/ViewModelSlim.cs @@ -14,6 +14,8 @@ namespace Snap.Hutao.ViewModel.Abstraction; internal abstract class ViewModelSlim : ObservableObject where TPage : Microsoft.UI.Xaml.Controls.Page { + private bool isInitialized; + /// /// 构造一个新的简化的视图模型抽象类 /// @@ -26,6 +28,11 @@ internal abstract class ViewModelSlim : ObservableObject NavigateCommand = new RelayCommand(Navigate); } + /// + /// 是否初始化完成 + /// + public bool IsInitialized { get => isInitialized; set => SetProperty(ref isInitialized, value); } + /// /// 打开页面命令 /// diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AnnouncementViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AnnouncementViewModel.cs index a79b24d3..bb947279 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AnnouncementViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AnnouncementViewModel.cs @@ -26,6 +26,7 @@ internal sealed class AnnouncementViewModel : Abstraction.ViewModel announcementService = serviceProvider.GetRequiredService(); LaunchGameViewModelSlim = serviceProvider.GetRequiredService(); + GachaLogViewModelSlim = serviceProvider.GetRequiredService(); } /// @@ -38,6 +39,11 @@ internal sealed class AnnouncementViewModel : Abstraction.ViewModel /// public Game.LaunchGameViewModelSlim LaunchGameViewModelSlim { get; } + /// + /// 祈愿记录视图模型 + /// + public GachaLog.GachaLogViewModelSlim GachaLogViewModelSlim { get; } + /// protected override async Task OpenUIAsync() { diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModelSlim.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModelSlim.cs index bda9b161..09cc2e14 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModelSlim.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaLogViewModelSlim.cs @@ -1,6 +1,8 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Service.GachaLog; + namespace Snap.Hutao.ViewModel.GachaLog; /// @@ -26,8 +28,16 @@ internal sealed class GachaLogViewModelSlim : Abstraction.ViewModelSlim? StatisticsList { get => statisticsList; set => SetProperty(ref statisticsList, value); } /// - protected override Task OpenUIAsync() + protected override async Task OpenUIAsync() { - return Task.CompletedTask; + IGachaLogService gachaLogService = ServiceProvider.GetRequiredService(); + + if (await gachaLogService.InitializeAsync(default).ConfigureAwait(false)) + { + List list = await gachaLogService.GetStatisticsSlimsAsync().ConfigureAwait(false); + await ThreadHelper.SwitchToMainThreadAsync(); + StatisticsList = list; + IsInitialized = true; + } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaStatisticsSlim.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaStatisticsSlim.cs index 21b39696..75beb5f3 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaStatisticsSlim.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/GachaStatisticsSlim.cs @@ -16,15 +16,15 @@ internal sealed class GachaStatisticsSlim /// /// 角色活动 /// - public TypedWishSummary AvatarWish { get; set; } = default!; + public TypedWishSummarySlim AvatarWish { get; set; } = default!; /// /// 神铸赋形 /// - public TypedWishSummary WeaponWish { get; set; } = default!; + public TypedWishSummarySlim WeaponWish { get; set; } = default!; /// /// 奔行世间 /// - public TypedWishSummary StandardWish { get; set; } = default!; + public TypedWishSummarySlim StandardWish { get; set; } = default!; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/TypedWishSummarySlim.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/TypedWishSummarySlim.cs index bb205ac6..d7464770 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/TypedWishSummarySlim.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/GachaLog/TypedWishSummarySlim.cs @@ -8,6 +8,19 @@ namespace Snap.Hutao.ViewModel.GachaLog; /// internal sealed class TypedWishSummarySlim { + /// + /// 构造一个新的简化的类型化的祈愿概览 + /// + /// 卡池名称 + /// 五星保底阈值 + /// 四星保底阈值 + public TypedWishSummarySlim(string name, int guaranteeOrangeThreshold, int guaranteePurpleThreshold) + { + Name = name; + GuaranteeOrangeThreshold = guaranteeOrangeThreshold; + GuaranteePurpleThreshold = guaranteePurpleThreshold; + } + /// /// 卡池名称 /// diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Event/GachaInfo/GachaLogQueryOptions.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Event/GachaInfo/GachaLogQueryOptions.cs index d9ed5dd5..571b234c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Event/GachaInfo/GachaLogQueryOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Event/GachaInfo/GachaLogQueryOptions.cs @@ -23,6 +23,14 @@ internal struct GachaLogQueryOptions /// public readonly bool IsOversea; + /// + /// 结束Id + /// 控制API返回的分页 + /// 米哈游使用了 keyset pagination 来实现这一目标 + /// https://learn.microsoft.com/en-us/ef/core/querying/pagination#keyset-pagination + /// + public long EndId; + /// /// Keys required: /// authkey_ver @@ -37,14 +45,6 @@ internal struct GachaLogQueryOptions /// private readonly QueryString innerQuery; - /// - /// 结束Id - /// 控制API返回的分页 - /// 米哈游使用了 keyset pagination 来实现这一目标 - /// https://learn.microsoft.com/en-us/ef/core/querying/pagination#keyset-pagination - /// - public long EndId; - /// /// 构造一个新的祈愿记录请求配置 /// diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Model/Post/SimpleRecord.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Model/Post/SimpleRecord.cs index e199dce6..1e96e5f6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Model/Post/SimpleRecord.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/Model/Post/SimpleRecord.cs @@ -18,6 +18,7 @@ internal sealed class SimpleRecord /// uid /// 详细的角色信息 /// 深渊信息 + /// 用户名 public SimpleRecord(string uid, List characters, SpiralAbyss spiralAbyss, string? reservedUserName) { Uid = uid; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/HutaoEndpoints.cs b/src/Snap.Hutao/Snap.Hutao/Web/HutaoEndpoints.cs index 42001d2f..5d652bd1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/HutaoEndpoints.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/HutaoEndpoints.cs @@ -48,6 +48,7 @@ internal static class HutaoEndpoints /// /// 删除祈愿记录 /// + /// uid /// 删除祈愿记录 Url public static string GachaLogDelete(string uid) {