From 974afa86ee08cce01e04f7fb0879d8c6fa40d219 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Fri, 2 Feb 2024 11:06:08 +0800 Subject: [PATCH] impl #1334 --- .../ObservableReorderableDbCollection.cs | 27 ++++++++---------- .../Extension/EnumerableExtension.cs | 8 ++++++ .../Game/Account/GameAccountService.cs | 5 ++-- .../Game/Account/IGameAccountService.cs | 4 +-- .../Snap.Hutao/Service/Game/GameDbService.cs | 5 ++-- .../Service/Game/GameServiceFacade.cs | 4 +-- .../Snap.Hutao/Service/Game/IGameDbService.cs | 4 +-- .../Service/Game/IGameServiceFacade.cs | 4 +-- .../Snap.Hutao/View/Page/LaunchGamePage.xaml | 2 ++ .../ViewModel/Game/LaunchGameViewModel.cs | 28 ++++++++++--------- 10 files changed, 50 insertions(+), 41 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Database/ObservableReorderableDbCollection.cs b/src/Snap.Hutao/Snap.Hutao/Core/Database/ObservableReorderableDbCollection.cs index 19a19dac97..971dd9516f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Database/ObservableReorderableDbCollection.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Database/ObservableReorderableDbCollection.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.EntityFrameworkCore; +using Snap.Hutao.Model.Entity.Database; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Runtime.InteropServices; @@ -11,13 +12,12 @@ namespace Snap.Hutao.Core.Database; internal sealed class ObservableReorderableDbCollection : ObservableCollection where T : class, IReorderable { - private readonly DbContext dbContext; - private bool previousChangeIsRemoved; + private readonly IServiceProvider serviceProvider; - public ObservableReorderableDbCollection(List items, DbContext dbContext) + public ObservableReorderableDbCollection(List items, IServiceProvider serviceProvider) : base(AdjustIndex(items)) { - this.dbContext = dbContext; + this.serviceProvider = serviceProvider; } protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) @@ -27,16 +27,8 @@ protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) switch (e.Action) { case NotifyCollectionChangedAction.Remove: - previousChangeIsRemoved = true; - break; case NotifyCollectionChangedAction.Add: - if (!previousChangeIsRemoved) - { - return; - } - OnReorder(); - previousChangeIsRemoved = false; break; } } @@ -57,10 +49,15 @@ private void OnReorder() { AdjustIndex((List)Items); - DbSet dbSet = dbContext.Set(); - foreach (ref readonly T item in CollectionsMarshal.AsSpan((List)Items)) + using (IServiceScope scope = serviceProvider.CreateScope()) { - dbSet.UpdateAndSave(item); + AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService(); + + DbSet dbSet = appDbContext.Set(); + foreach (ref readonly T item in CollectionsMarshal.AsSpan((List)Items)) + { + dbSet.UpdateAndSave(item); + } } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs index a9a99041c5..8d3c4f534a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.Database; using System.Collections.ObjectModel; using System.Runtime.CompilerServices; using System.Text; @@ -113,6 +114,13 @@ public static ObservableCollection ToObservableCollection(this IEnumerable return new ObservableCollection(source); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ObservableReorderableDbCollection ToObservableReorderableDbCollection(this IEnumerable source, IServiceProvider serviceProvider) + where T : class, IReorderable + { + return new ObservableReorderableDbCollection([.. source], serviceProvider); + } + /// /// Concatenates each element from the collection into single string. /// diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs index ff08a1a01f..114dd3bd74 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs @@ -1,6 +1,7 @@ // 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.Factory.ContentDialog; using Snap.Hutao.Model.Entity; @@ -18,9 +19,9 @@ internal sealed partial class GameAccountService : IGameAccountService private readonly IGameDbService gameDbService; private readonly ITaskContext taskContext; - private ObservableCollection? gameAccounts; + private ObservableReorderableDbCollection? gameAccounts; - public ObservableCollection GameAccountCollection + public ObservableReorderableDbCollection GameAccountCollection { get => gameAccounts ??= gameDbService.GetGameAccountCollection(); } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs index eaf88f1f57..eb132170e4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs @@ -1,15 +1,15 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.Database; using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity.Primitive; -using System.Collections.ObjectModel; namespace Snap.Hutao.Service.Game.Account; internal interface IGameAccountService { - ObservableCollection GameAccountCollection { get; } + ObservableReorderableDbCollection GameAccountCollection { get; } void AttachGameAccountToUid(GameAccount gameAccount, string uid); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameDbService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameDbService.cs index 220d5401d7..b65dd98dd6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameDbService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameDbService.cs @@ -5,7 +5,6 @@ using Snap.Hutao.Core.Database; using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity.Database; -using System.Collections.ObjectModel; namespace Snap.Hutao.Service.Game; @@ -15,12 +14,12 @@ internal sealed partial class GameDbService : IGameDbService { private readonly IServiceProvider serviceProvider; - public ObservableCollection GetGameAccountCollection() + public ObservableReorderableDbCollection GetGameAccountCollection() { using (IServiceScope scope = serviceProvider.CreateScope()) { AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService(); - return appDbContext.GameAccounts.AsNoTracking().ToObservableCollection(); + return appDbContext.GameAccounts.AsNoTracking().OrderBy(account => account.Index).ToObservableReorderableDbCollection(serviceProvider); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs index 6247aeed99..83958a87cc 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs @@ -1,13 +1,13 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.Database; using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity.Primitive; using Snap.Hutao.Service.Game.Account; using Snap.Hutao.Service.Game.Configuration; using Snap.Hutao.Service.Game.Launching.Handler; using Snap.Hutao.Service.Game.PathAbstraction; -using System.Collections.ObjectModel; namespace Snap.Hutao.Service.Game; @@ -24,7 +24,7 @@ internal sealed partial class GameServiceFacade : IGameServiceFacade private readonly IGamePathService gamePathService; /// - public ObservableCollection GameAccountCollection + public ObservableReorderableDbCollection GameAccountCollection { get => gameAccountService.GameAccountCollection; } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameDbService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameDbService.cs index 0ee216f54e..5550d0180a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameDbService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameDbService.cs @@ -1,8 +1,8 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.Database; using Snap.Hutao.Model.Entity; -using System.Collections.ObjectModel; namespace Snap.Hutao.Service.Game; @@ -12,7 +12,7 @@ internal interface IGameDbService ValueTask RemoveGameAccountByIdAsync(Guid id); - ObservableCollection GetGameAccountCollection(); + ObservableReorderableDbCollection GetGameAccountCollection(); void UpdateGameAccount(GameAccount gameAccount); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs index b3e98cbcb5..ecb0342145 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs @@ -1,10 +1,10 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.Database; using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity.Primitive; using Snap.Hutao.Service.Game.Configuration; -using System.Collections.ObjectModel; namespace Snap.Hutao.Service.Game; @@ -17,7 +17,7 @@ internal interface IGameServiceFacade /// /// 游戏内账号集合 /// - ObservableCollection GameAccountCollection { get; } + ObservableReorderableDbCollection GameAccountCollection { get; } /// /// 将账号绑定到对应的Uid diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/LaunchGamePage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/LaunchGamePage.xaml index b8134ef684..5561b78e73 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/LaunchGamePage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/LaunchGamePage.xaml @@ -202,6 +202,8 @@ IsClickEnabled="True"/> diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs index 8378e5f01e..db52d5dce2 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Caching.Memory; using Microsoft.UI.Windowing; using Snap.Hutao.Core; +using Snap.Hutao.Core.Database; using Snap.Hutao.Core.Diagnostics.CodeAnalysis; using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Model.Entity; @@ -18,7 +19,6 @@ using Snap.Hutao.Service.User; using Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher; using System.Collections.Immutable; -using System.Collections.ObjectModel; using System.IO; namespace Snap.Hutao.ViewModel.Game; @@ -241,6 +241,8 @@ private async Task DetectGameAccountAsync() { await taskContext.SwitchToMainThreadAsync(); SelectedGameAccount = account; + + await UpdateGameAccountsViewAsync().ConfigureAwait(false); } } catch (UserdataCorruptedException ex) @@ -326,18 +328,6 @@ async ValueTask UpdateGameResourceAsync(LaunchScheme? scheme) GameResource = response.Data; } } - - async ValueTask UpdateGameAccountsViewAsync() - { - gameAccountFilter = new(SelectedScheme?.GetSchemeType()); - ObservableCollection accounts = gameService.GameAccountCollection; - - await taskContext.SwitchToMainThreadAsync(); - GameAccountsView = new(accounts, true) - { - Filter = gameAccountFilter.Filter, - }; - } } [Command("IdentifyMonitorsCommand")] @@ -363,4 +353,16 @@ private async Task IdentifyMonitorsAsync() window.Close(); } } + + private async ValueTask UpdateGameAccountsViewAsync() + { + gameAccountFilter = new(SelectedScheme?.GetSchemeType()); + ObservableReorderableDbCollection accounts = gameService.GameAccountCollection; + + await taskContext.SwitchToMainThreadAsync(); + GameAccountsView = new(accounts, true) + { + Filter = gameAccountFilter.Filter, + }; + } } \ No newline at end of file