Skip to content

Commit

Permalink
impl #1334
Browse files Browse the repository at this point in the history
  • Loading branch information
qhy040404 committed Feb 2, 2024
1 parent 7baf125 commit 974afa8
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -11,13 +12,12 @@ namespace Snap.Hutao.Core.Database;
internal sealed class ObservableReorderableDbCollection<T> : ObservableCollection<T>
where T : class, IReorderable
{
private readonly DbContext dbContext;
private bool previousChangeIsRemoved;
private readonly IServiceProvider serviceProvider;

public ObservableReorderableDbCollection(List<T> items, DbContext dbContext)
public ObservableReorderableDbCollection(List<T> items, IServiceProvider serviceProvider)
: base(AdjustIndex(items))
{
this.dbContext = dbContext;
this.serviceProvider = serviceProvider;
}

protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
Expand All @@ -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;
}
}
Expand All @@ -57,10 +49,15 @@ private void OnReorder()
{
AdjustIndex((List<T>)Items);

DbSet<T> dbSet = dbContext.Set<T>();
foreach (ref readonly T item in CollectionsMarshal.AsSpan((List<T>)Items))
using (IServiceScope scope = serviceProvider.CreateScope())
{
dbSet.UpdateAndSave(item);
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();

DbSet<T> dbSet = appDbContext.Set<T>();
foreach (ref readonly T item in CollectionsMarshal.AsSpan((List<T>)Items))
{
dbSet.UpdateAndSave(item);
}
}
}
}
8 changes: 8 additions & 0 deletions src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -113,6 +114,13 @@ public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable
return new ObservableCollection<T>(source);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ObservableReorderableDbCollection<T> ToObservableReorderableDbCollection<T>(this IEnumerable<T> source, IServiceProvider serviceProvider)
where T : class, IReorderable
{
return new ObservableReorderableDbCollection<T>([.. source], serviceProvider);
}

/// <summary>
/// Concatenates each element from the collection into single string.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -18,9 +19,9 @@ internal sealed partial class GameAccountService : IGameAccountService
private readonly IGameDbService gameDbService;
private readonly ITaskContext taskContext;

private ObservableCollection<GameAccount>? gameAccounts;
private ObservableReorderableDbCollection<GameAccount>? gameAccounts;

public ObservableCollection<GameAccount> GameAccountCollection
public ObservableReorderableDbCollection<GameAccount> GameAccountCollection
{
get => gameAccounts ??= gameDbService.GetGameAccountCollection();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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<GameAccount> GameAccountCollection { get; }
ObservableReorderableDbCollection<GameAccount> GameAccountCollection { get; }

void AttachGameAccountToUid(GameAccount gameAccount, string uid);

Expand Down
5 changes: 2 additions & 3 deletions src/Snap.Hutao/Snap.Hutao/Service/Game/GameDbService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -15,12 +14,12 @@ internal sealed partial class GameDbService : IGameDbService
{
private readonly IServiceProvider serviceProvider;

public ObservableCollection<GameAccount> GetGameAccountCollection()
public ObservableReorderableDbCollection<GameAccount> GetGameAccountCollection()
{
using (IServiceScope scope = serviceProvider.CreateScope())
{
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
return appDbContext.GameAccounts.AsNoTracking().ToObservableCollection();
return appDbContext.GameAccounts.AsNoTracking().OrderBy(account => account.Index).ToObservableReorderableDbCollection(serviceProvider);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -24,7 +24,7 @@ internal sealed partial class GameServiceFacade : IGameServiceFacade
private readonly IGamePathService gamePathService;

/// <inheritdoc/>
public ObservableCollection<GameAccount> GameAccountCollection
public ObservableReorderableDbCollection<GameAccount> GameAccountCollection
{
get => gameAccountService.GameAccountCollection;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Snap.Hutao/Snap.Hutao/Service/Game/IGameDbService.cs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -12,7 +12,7 @@ internal interface IGameDbService

ValueTask RemoveGameAccountByIdAsync(Guid id);

ObservableCollection<GameAccount> GetGameAccountCollection();
ObservableReorderableDbCollection<GameAccount> GetGameAccountCollection();

void UpdateGameAccount(GameAccount gameAccount);

Expand Down
4 changes: 2 additions & 2 deletions src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -17,7 +17,7 @@ internal interface IGameServiceFacade
/// <summary>
/// 游戏内账号集合
/// </summary>
ObservableCollection<GameAccount> GameAccountCollection { get; }
ObservableReorderableDbCollection<GameAccount> GameAccountCollection { get; }

/// <summary>
/// 将账号绑定到对应的Uid
Expand Down
2 changes: 2 additions & 0 deletions src/Snap.Hutao/Snap.Hutao/View/Page/LaunchGamePage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@
IsClickEnabled="True"/>
<Border Padding="0,1" Style="{StaticResource BorderCardStyle}">
<ListView
AllowDrop="True"
CanReorderItems="True"
ItemTemplate="{StaticResource GameAccountListTemplate}"
ItemsSource="{Binding GameAccountsView}"
SelectedItem="{Binding SelectedGameAccount, Mode=TwoWay}"/>
Expand Down
28 changes: 15 additions & 13 deletions src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -241,6 +241,8 @@ private async Task DetectGameAccountAsync()
{
await taskContext.SwitchToMainThreadAsync();
SelectedGameAccount = account;

await UpdateGameAccountsViewAsync().ConfigureAwait(false);
}
}
catch (UserdataCorruptedException ex)
Expand Down Expand Up @@ -326,18 +328,6 @@ async ValueTask UpdateGameResourceAsync(LaunchScheme? scheme)
GameResource = response.Data;
}
}

async ValueTask UpdateGameAccountsViewAsync()
{
gameAccountFilter = new(SelectedScheme?.GetSchemeType());
ObservableCollection<GameAccount> accounts = gameService.GameAccountCollection;

await taskContext.SwitchToMainThreadAsync();
GameAccountsView = new(accounts, true)
{
Filter = gameAccountFilter.Filter,
};
}
}

[Command("IdentifyMonitorsCommand")]
Expand All @@ -363,4 +353,16 @@ private async Task IdentifyMonitorsAsync()
window.Close();
}
}

private async ValueTask UpdateGameAccountsViewAsync()
{
gameAccountFilter = new(SelectedScheme?.GetSchemeType());
ObservableReorderableDbCollection<GameAccount> accounts = gameService.GameAccountCollection;

await taskContext.SwitchToMainThreadAsync();
GameAccountsView = new(accounts, true)
{
Filter = gameAccountFilter.Filter,
};
}
}

0 comments on commit 974afa8

Please sign in to comment.