mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Compare commits
5 Commits
feat/custo
...
refactor/h
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5182fd8577 | ||
|
|
ff2521c02c | ||
|
|
5954c1a0ab | ||
|
|
4dc753bf5a | ||
|
|
bd3617c15a |
@@ -104,6 +104,7 @@ internal class ScopedPage : Page
|
||||
|
||||
// Dispose the scope
|
||||
pageScope.Dispose();
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Aggressive, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Snap.Hutao.Model.Entity;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[Table("cultivate_entries")]
|
||||
internal sealed class CultivateEntry : IDbMappingForeignKeyFrom<CultivateEntry, CultivateType, uint>
|
||||
internal sealed class CultivateEntry : IDbMappingForeignKeyFrom<CultivateEntry, CultivateType, uint>, IAppDbEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 内部Id
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using Snap.Hutao.Core.Abstraction;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Model.Entity.Abstraction;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
@@ -13,7 +14,7 @@ namespace Snap.Hutao.Model.Entity;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[Table("cultivate_projects")]
|
||||
internal sealed class CultivateProject : ISelectable, IMappingFrom<CultivateProject, string, string>
|
||||
internal sealed class CultivateProject : ISelectable, IMappingFrom<CultivateProject, string, string>, IAppDbEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 内部Id
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Model.Entity.Abstraction;
|
||||
|
||||
namespace Snap.Hutao.Service.Abstraction;
|
||||
@@ -12,13 +11,25 @@ internal static class AppDbServiceAppDbEntityExtension
|
||||
public static int DeleteByInnerId<TEntity>(this IAppDbService<TEntity> service, TEntity entity)
|
||||
where TEntity : class, IAppDbEntity
|
||||
{
|
||||
return service.Execute(dbset => dbset.ExecuteDeleteWhere(e => e.InnerId == entity.InnerId));
|
||||
return service.DeleteByInnerId(entity.InnerId);
|
||||
}
|
||||
|
||||
public static int DeleteByInnerId<TEntity>(this IAppDbService<TEntity> service, Guid innerId)
|
||||
where TEntity : class, IAppDbEntity
|
||||
{
|
||||
return service.Delete(e => e.InnerId == innerId);
|
||||
}
|
||||
|
||||
public static ValueTask<int> DeleteByInnerIdAsync<TEntity>(this IAppDbService<TEntity> service, TEntity entity, CancellationToken token = default)
|
||||
where TEntity : class, IAppDbEntity
|
||||
{
|
||||
return service.ExecuteAsync((dbset, token) => dbset.ExecuteDeleteWhereAsync(e => e.InnerId == entity.InnerId, token), token);
|
||||
return service.DeleteByInnerIdAsync(entity.InnerId, token);
|
||||
}
|
||||
|
||||
public static ValueTask<int> DeleteByInnerIdAsync<TEntity>(this IAppDbService<TEntity> service, Guid innerId, CancellationToken token = default)
|
||||
where TEntity : class, IAppDbEntity
|
||||
{
|
||||
return service.DeleteAsync(e => e.InnerId == innerId, token);
|
||||
}
|
||||
|
||||
public static List<TEntity> ListByArchiveId<TEntity>(this IAppDbService<TEntity> service, Guid archiveId)
|
||||
|
||||
@@ -30,7 +30,13 @@ internal static class AppDbServiceCollectionExtension
|
||||
public static ValueTask<List<TEntity>> ListAsync<TEntity>(this IAppDbService<TEntity> service, Expression<Func<TEntity, bool>> predicate, CancellationToken token = default)
|
||||
where TEntity : class
|
||||
{
|
||||
return service.QueryAsync((query, token) => query.Where(predicate).ToListAsync(token), token);
|
||||
return service.ListAsync(query => query.Where(predicate), token);
|
||||
}
|
||||
|
||||
public static ValueTask<List<TResult>> ListAsync<TEntity, TResult>(this IAppDbService<TEntity> service, Func<IQueryable<TEntity>, IQueryable<TResult>> query, CancellationToken token = default)
|
||||
where TEntity : class
|
||||
{
|
||||
return service.QueryAsync((query1, token) => query(query1).ToListAsync(token), token);
|
||||
}
|
||||
|
||||
public static ObservableCollection<TEntity> ObservableCollection<TEntity>(this IAppDbService<TEntity> service)
|
||||
|
||||
@@ -126,6 +126,18 @@ internal static class AppDbServiceExtension
|
||||
return service.QueryAsync((query, token) => query.SingleAsync(predicate, token), token);
|
||||
}
|
||||
|
||||
public static TEntity? SingleOrDefault<TEntity>(this IAppDbService<TEntity> service, Expression<Func<TEntity, bool>> predicate)
|
||||
where TEntity : class
|
||||
{
|
||||
return service.Query(query => query.SingleOrDefault(predicate));
|
||||
}
|
||||
|
||||
public static ValueTask<TEntity?> SingleOrDefaultAsync<TEntity>(this IAppDbService<TEntity> service, Expression<Func<TEntity, bool>> predicate, CancellationToken token = default)
|
||||
where TEntity : class
|
||||
{
|
||||
return service.QueryAsync((query, token) => query.SingleOrDefaultAsync(predicate, token), token);
|
||||
}
|
||||
|
||||
public static int Update<TEntity>(this IAppDbService<TEntity> service, TEntity entity)
|
||||
where TEntity : class
|
||||
{
|
||||
@@ -144,9 +156,21 @@ internal static class AppDbServiceExtension
|
||||
return service.Execute(dbset => dbset.RemoveAndSave(entity));
|
||||
}
|
||||
|
||||
public static int Delete<TEntity>(this IAppDbService<TEntity> service, Expression<Func<TEntity, bool>> predicate)
|
||||
where TEntity : class
|
||||
{
|
||||
return service.Execute(dbset => dbset.Where(predicate).ExecuteDelete());
|
||||
}
|
||||
|
||||
public static ValueTask<int> DeleteAsync<TEntity>(this IAppDbService<TEntity> service, TEntity entity, CancellationToken token = default)
|
||||
where TEntity : class
|
||||
{
|
||||
return service.ExecuteAsync((dbset, token) => dbset.RemoveAndSaveAsync(entity, token), token);
|
||||
}
|
||||
|
||||
public static ValueTask<int> DeleteAsync<TEntity>(this IAppDbService<TEntity> service, Expression<Func<TEntity, bool>> predicate, CancellationToken token = default)
|
||||
where TEntity : class
|
||||
{
|
||||
return service.ExecuteAsync((dbset, token) => dbset.Where(predicate).ExecuteDeleteAsync(token), token);
|
||||
}
|
||||
}
|
||||
@@ -46,13 +46,12 @@ internal sealed partial class AchievementDbService : IAchievementDbService
|
||||
[SuppressMessage("", "CA1305")]
|
||||
public ValueTask<List<EntityAchievement>> GetLatestFinishedAchievementListByArchiveIdAsync(Guid archiveId, int take, CancellationToken token = default)
|
||||
{
|
||||
return this.QueryAsync<EntityAchievement, List<EntityAchievement>>(
|
||||
(query, token) => query
|
||||
return this.ListAsync<EntityAchievement, EntityAchievement>(
|
||||
query => query
|
||||
.Where(a => a.ArchiveId == archiveId)
|
||||
.Where(a => a.Status >= Model.Intrinsic.AchievementStatus.STATUS_FINISHED)
|
||||
.OrderByDescending(a => a.Time.ToString())
|
||||
.Take(take)
|
||||
.ToListAsync(token),
|
||||
.Take(take),
|
||||
token);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,5 @@ namespace Snap.Hutao.Service.Announcement;
|
||||
[HighQuality]
|
||||
internal interface IAnnouncementService
|
||||
{
|
||||
/// <summary>
|
||||
/// 异步获取游戏公告与活动,通常会进行缓存
|
||||
/// </summary>
|
||||
/// <param name="languageCode">语言代码</param>
|
||||
/// <param name="region">服务器</param>
|
||||
/// <param name="cancellationToken">取消令牌</param>
|
||||
/// <returns>公告包装器</returns>
|
||||
ValueTask<AnnouncementWrapper> GetAnnouncementWrapperAsync(string languageCode, Region region, CancellationToken cancellationToken = default);
|
||||
ValueTask<AnnouncementWrapper> GetAnnouncementWrapperAsync(string languageCode, Region region, CancellationToken token = default);
|
||||
}
|
||||
@@ -29,11 +29,11 @@ internal sealed partial class AvatarInfoDbService : IAvatarInfoDbService
|
||||
|
||||
public void RemoveAvatarInfoRangeByUid(string uid)
|
||||
{
|
||||
this.Execute(dbset => dbset.Where(i => i.Uid == uid).ExecuteDelete());
|
||||
this.Delete(i => i.Uid == uid);
|
||||
}
|
||||
|
||||
public async ValueTask RemoveAvatarInfoRangeByUidAsync(string uid, CancellationToken token = default)
|
||||
{
|
||||
await this.ExecuteAsync((dbset, token) => dbset.Where(i => i.Uid == uid).ExecuteDeleteAsync(token), token).ConfigureAwait(false);
|
||||
await this.DeleteAsync(i => i.Uid == uid, token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -25,11 +25,11 @@ internal sealed partial class AvatarInfoService : IAvatarInfoService
|
||||
private readonly IMetadataService metadataService;
|
||||
private readonly ISummaryFactory summaryFactory;
|
||||
|
||||
public async ValueTask<ValueResult<RefreshResult, Summary?>> GetSummaryAsync(UserAndUid userAndUid, RefreshOption refreshOption, CancellationToken token = default)
|
||||
public async ValueTask<ValueResult<RefreshResultKind, Summary?>> GetSummaryAsync(UserAndUid userAndUid, RefreshOption refreshOption, CancellationToken token = default)
|
||||
{
|
||||
if (!await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||
{
|
||||
return new(RefreshResult.MetadataNotInitialized, null);
|
||||
return new(RefreshResultKind.MetadataNotInitialized, null);
|
||||
}
|
||||
|
||||
switch (refreshOption)
|
||||
@@ -40,43 +40,43 @@ internal sealed partial class AvatarInfoService : IAvatarInfoService
|
||||
|
||||
if (resp is null)
|
||||
{
|
||||
return new(RefreshResult.APIUnavailable, default);
|
||||
return new(RefreshResultKind.APIUnavailable, default);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(resp.Message))
|
||||
{
|
||||
return new(RefreshResult.StatusCodeNotSucceed, new Summary { Message = resp.Message });
|
||||
return new(RefreshResultKind.StatusCodeNotSucceed, new Summary { Message = resp.Message });
|
||||
}
|
||||
|
||||
if (!resp.IsValid)
|
||||
{
|
||||
return new(RefreshResult.ShowcaseNotOpen, default);
|
||||
return new(RefreshResultKind.ShowcaseNotOpen, default);
|
||||
}
|
||||
|
||||
List<EntityAvatarInfo> list = await avatarInfoDbBulkOperation.UpdateDbAvatarInfosByShowcaseAsync(userAndUid.Uid.Value, resp.AvatarInfoList, token).ConfigureAwait(false);
|
||||
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
||||
return new(RefreshResult.Ok, summary);
|
||||
return new(RefreshResultKind.Ok, summary);
|
||||
}
|
||||
|
||||
case RefreshOption.RequestFromHoyolabGameRecord:
|
||||
{
|
||||
List<EntityAvatarInfo> list = await avatarInfoDbBulkOperation.UpdateDbAvatarInfosByGameRecordCharacterAsync(userAndUid, token).ConfigureAwait(false);
|
||||
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
||||
return new(RefreshResult.Ok, summary);
|
||||
return new(RefreshResultKind.Ok, summary);
|
||||
}
|
||||
|
||||
case RefreshOption.RequestFromHoyolabCalculate:
|
||||
{
|
||||
List<EntityAvatarInfo> list = await avatarInfoDbBulkOperation.UpdateDbAvatarInfosByCalculateAvatarDetailAsync(userAndUid, token).ConfigureAwait(false);
|
||||
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
||||
return new(RefreshResult.Ok, summary);
|
||||
return new(RefreshResultKind.Ok, summary);
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
List<EntityAvatarInfo> list = await avatarInfoDbService.GetAvatarInfoListByUidAsync(userAndUid.Uid.Value, token).ConfigureAwait(false);
|
||||
Summary summary = await GetSummaryCoreAsync(list, token).ConfigureAwait(false);
|
||||
return new(RefreshResult.Ok, summary.Avatars.Count == 0 ? null : summary);
|
||||
return new(RefreshResultKind.Ok, summary.Avatars.Count == 0 ? null : summary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,5 +19,5 @@ internal interface IAvatarInfoService
|
||||
/// <param name="refreshOption">刷新选项</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>总览数据</returns>
|
||||
ValueTask<ValueResult<RefreshResult, Summary?>> GetSummaryAsync(UserAndUid userAndUid, RefreshOption refreshOption, CancellationToken token = default);
|
||||
ValueTask<ValueResult<RefreshResultKind, Summary?>> GetSummaryAsync(UserAndUid userAndUid, RefreshOption refreshOption, CancellationToken token = default);
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Snap.Hutao.Service.AvatarInfo;
|
||||
/// 刷新结果
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal enum RefreshResult
|
||||
internal enum RefreshResultKind
|
||||
{
|
||||
/// <summary>
|
||||
/// 正常
|
||||
@@ -26,11 +26,11 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
||||
private readonly ITaskContext taskContext;
|
||||
private readonly AppOptions appOptions;
|
||||
|
||||
private HashSet<string> currentBackgroundPathSet;
|
||||
private HashSet<string>? currentBackgroundPathSet;
|
||||
|
||||
public async ValueTask<ValueResult<bool, BackgroundImage?>> GetNextBackgroundImageAsync(BackgroundImage? previous)
|
||||
public async ValueTask<ValueResult<bool, BackgroundImage?>> GetNextBackgroundImageAsync(BackgroundImage? previous, CancellationToken token = default)
|
||||
{
|
||||
HashSet<string> backgroundSet = await SkipOrInitBackgroundAsync().ConfigureAwait(false);
|
||||
HashSet<string> backgroundSet = await SkipOrInitBackgroundAsync(token).ConfigureAwait(false);
|
||||
|
||||
if (backgroundSet.Count <= 0)
|
||||
{
|
||||
@@ -79,7 +79,7 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask<HashSet<string>> SkipOrInitBackgroundAsync()
|
||||
private async ValueTask<HashSet<string>> SkipOrInitBackgroundAsync(CancellationToken token = default)
|
||||
{
|
||||
switch (appOptions.BackgroundImageType)
|
||||
{
|
||||
@@ -90,7 +90,7 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
||||
string backgroundFolder = runtimeOptions.GetDataFolderBackgroundFolder();
|
||||
|
||||
currentBackgroundPathSet = Directory
|
||||
.GetFiles(backgroundFolder, "*.*", SearchOption.AllDirectories)
|
||||
.EnumerateFiles(backgroundFolder, "*", SearchOption.AllDirectories)
|
||||
.Where(path => AllowedFormats.Contains(Path.GetExtension(path)))
|
||||
.ToHashSet();
|
||||
}
|
||||
@@ -100,13 +100,13 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
||||
}
|
||||
|
||||
case BackgroundImageType.HutaoBing:
|
||||
await SetCurrentBackgroundPathSetAsync(client => client.GetBingWallpaperAsync()).ConfigureAwait(false);
|
||||
await SetCurrentBackgroundPathSetAsync((client, token) => client.GetBingWallpaperAsync(token), token).ConfigureAwait(false);
|
||||
break;
|
||||
case BackgroundImageType.HutaoDaily:
|
||||
await SetCurrentBackgroundPathSetAsync(client => client.GetTodayWallpaperAsync()).ConfigureAwait(false);
|
||||
await SetCurrentBackgroundPathSetAsync((client, token) => client.GetTodayWallpaperAsync(token), token).ConfigureAwait(false);
|
||||
break;
|
||||
case BackgroundImageType.HutaoOfficialLauncher:
|
||||
await SetCurrentBackgroundPathSetAsync(client => client.GetLauncherWallpaperAsync()).ConfigureAwait(false);
|
||||
await SetCurrentBackgroundPathSetAsync((client, token) => client.GetLauncherWallpaperAsync(token), token).ConfigureAwait(false);
|
||||
break;
|
||||
default:
|
||||
currentBackgroundPathSet = [];
|
||||
@@ -116,10 +116,10 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
||||
currentBackgroundPathSet ??= [];
|
||||
return currentBackgroundPathSet;
|
||||
|
||||
async Task SetCurrentBackgroundPathSetAsync(Func<HutaoWallpaperClient, ValueTask<Response<Wallpaper>>> responseFactory)
|
||||
async Task SetCurrentBackgroundPathSetAsync(Func<HutaoWallpaperClient, CancellationToken, ValueTask<Response<Wallpaper>>> responseFactory, CancellationToken token = default)
|
||||
{
|
||||
HutaoWallpaperClient wallpaperClient = serviceProvider.GetRequiredService<HutaoWallpaperClient>();
|
||||
Response<Wallpaper> response = await responseFactory(wallpaperClient).ConfigureAwait(false);
|
||||
Response<Wallpaper> response = await responseFactory(wallpaperClient, token).ConfigureAwait(false);
|
||||
if (response is { Data: Wallpaper wallpaper })
|
||||
{
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
|
||||
@@ -5,5 +5,5 @@ namespace Snap.Hutao.Service.BackgroundImage;
|
||||
|
||||
internal interface IBackgroundImageService
|
||||
{
|
||||
ValueTask<ValueResult<bool, BackgroundImage?>> GetNextBackgroundImageAsync(BackgroundImage? previous);
|
||||
ValueTask<ValueResult<bool, BackgroundImage?>> GetNextBackgroundImageAsync(BackgroundImage? previous, CancellationToken token = default);
|
||||
}
|
||||
@@ -2,9 +2,8 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Snap.Hutao.Service.Cultivation;
|
||||
@@ -15,182 +14,90 @@ internal sealed partial class CultivationDbService : ICultivationDbService
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
|
||||
public IServiceProvider ServiceProvider { get => serviceProvider; }
|
||||
|
||||
public List<InventoryItem> GetInventoryItemListByProjectId(Guid projectId)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
IQueryable<InventoryItem> result = appDbContext.InventoryItems.AsNoTracking().Where(a => a.ProjectId == projectId);
|
||||
return [.. result];
|
||||
}
|
||||
return this.List<InventoryItem>(i => i.ProjectId == projectId);
|
||||
}
|
||||
|
||||
public async ValueTask<List<InventoryItem>> GetInventoryItemListByProjectIdAsync(Guid projectId)
|
||||
public ValueTask<List<InventoryItem>> GetInventoryItemListByProjectIdAsync(Guid projectId, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
return await appDbContext.InventoryItems
|
||||
.AsNoTracking()
|
||||
.Where(a => a.ProjectId == projectId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
return this.ListAsync<InventoryItem>(i => i.ProjectId == projectId, token);
|
||||
}
|
||||
|
||||
public async ValueTask<List<CultivateEntry>> GetCultivateEntryListByProjectIdAsync(Guid projectId)
|
||||
public ValueTask<List<CultivateEntry>> GetCultivateEntryListByProjectIdAsync(Guid projectId, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
return await appDbContext.CultivateEntries
|
||||
.AsNoTracking()
|
||||
.Where(e => e.ProjectId == projectId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
return this.ListAsync<CultivateEntry>(e => e.ProjectId == projectId, token);
|
||||
}
|
||||
|
||||
public async ValueTask<List<CultivateEntry>> GetCultivateEntryIncludeLevelInformationListByProjectIdAsync(Guid projectId)
|
||||
public ValueTask<List<CultivateEntry>> GetCultivateEntryListIncludingLevelInformationByProjectIdAsync(Guid projectId, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
return await appDbContext.CultivateEntries
|
||||
.AsNoTracking()
|
||||
.Where(e => e.ProjectId == projectId)
|
||||
.Include(e => e.LevelInformation)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
return this.ListAsync<CultivateEntry, CultivateEntry>(query => query.Where(e => e.ProjectId == projectId).Include(e => e.LevelInformation), token);
|
||||
}
|
||||
|
||||
public async ValueTask<List<CultivateItem>> GetCultivateItemListByEntryIdAsync(Guid entryId)
|
||||
public ValueTask<List<CultivateItem>> GetCultivateItemListByEntryIdAsync(Guid entryId, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
return await appDbContext.CultivateItems
|
||||
.Where(i => i.EntryId == entryId)
|
||||
.OrderBy(i => i.ItemId)
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
return this.ListAsync<CultivateItem, CultivateItem>(query => query.Where(i => i.EntryId == entryId).OrderBy(i => i.ItemId), token);
|
||||
}
|
||||
|
||||
public async ValueTask RemoveCultivateEntryByIdAsync(Guid entryId)
|
||||
public async ValueTask RemoveCultivateEntryByIdAsync(Guid entryId, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.CultivateEntries
|
||||
.ExecuteDeleteWhereAsync(i => i.InnerId == entryId)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await this.DeleteByInnerIdAsync<CultivateEntry>(entryId, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public void UpdateCultivateItem(CultivateItem item)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
appDbContext.CultivateItems.UpdateAndSave(item);
|
||||
}
|
||||
this.Update(item);
|
||||
}
|
||||
|
||||
public async ValueTask UpdateCultivateItemAsync(CultivateItem item)
|
||||
public async ValueTask UpdateCultivateItemAsync(CultivateItem item, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.CultivateItems.UpdateAndSaveAsync(item).ConfigureAwait(false);
|
||||
}
|
||||
await this.UpdateAsync(item, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async ValueTask<CultivateEntry?> GetCultivateEntryByProjectIdAndItemIdAsync(Guid projectId, uint itemId)
|
||||
public async ValueTask<CultivateEntry?> GetCultivateEntryByProjectIdAndItemIdAsync(Guid projectId, uint itemId, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
return await appDbContext.CultivateEntries
|
||||
.SingleOrDefaultAsync(e => e.ProjectId == projectId && e.Id == itemId)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
return await this.SingleOrDefaultAsync<CultivateEntry>(e => e.ProjectId == projectId && e.Id == itemId, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async ValueTask AddCultivateEntryAsync(CultivateEntry entry)
|
||||
public async ValueTask AddCultivateEntryAsync(CultivateEntry entry, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.CultivateEntries.AddAndSaveAsync(entry).ConfigureAwait(false);
|
||||
}
|
||||
await this.AddAsync(entry, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async ValueTask RemoveCultivateItemRangeByEntryIdAsync(Guid entryId)
|
||||
public async ValueTask RemoveCultivateItemRangeByEntryIdAsync(Guid entryId, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.CultivateItems
|
||||
.ExecuteDeleteWhereAsync(i => i.EntryId == entryId)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await this.DeleteAsync<CultivateItem>(i => i.EntryId == entryId, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async ValueTask AddCultivateItemRangeAsync(IEnumerable<CultivateItem> toAdd)
|
||||
public async ValueTask AddCultivateItemRangeAsync(IEnumerable<CultivateItem> toAdd, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.CultivateItems.AddRangeAndSaveAsync(toAdd).ConfigureAwait(false);
|
||||
}
|
||||
await this.AddRangeAsync(toAdd, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async ValueTask AddCultivateProjectAsync(CultivateProject project)
|
||||
public async ValueTask AddCultivateProjectAsync(CultivateProject project, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.CultivateProjects.AddAndSaveAsync(project).ConfigureAwait(false);
|
||||
}
|
||||
await this.AddAsync(project, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async ValueTask RemoveCultivateProjectByIdAsync(Guid projectId)
|
||||
public async ValueTask RemoveCultivateProjectByIdAsync(Guid projectId, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.CultivateProjects
|
||||
.ExecuteDeleteWhereAsync(p => p.InnerId == projectId)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await this.DeleteByInnerIdAsync<CultivateProject>(projectId, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public ObservableCollection<CultivateProject> GetCultivateProjectCollection()
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
return appDbContext.CultivateProjects.AsNoTracking().ToObservableCollection();
|
||||
}
|
||||
return this.ObservableCollection<CultivateProject>();
|
||||
}
|
||||
|
||||
public async ValueTask RemoveLevelInformationByEntryIdAsync(Guid entryId)
|
||||
public async ValueTask RemoveLevelInformationByEntryIdAsync(Guid entryId, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.LevelInformations.ExecuteDeleteWhereAsync(l => l.EntryId == entryId).ConfigureAwait(false);
|
||||
}
|
||||
await this.DeleteAsync<CultivateEntryLevelInformation>(l => l.EntryId == entryId, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async ValueTask AddLevelInformationAsync(CultivateEntryLevelInformation levelInformation)
|
||||
public async ValueTask AddLevelInformationAsync(CultivateEntryLevelInformation levelInformation, CancellationToken token = default)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.LevelInformations.AddAndSaveAsync(levelInformation).ConfigureAwait(false);
|
||||
}
|
||||
await this.AddAsync(levelInformation, token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
// 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.Cultivation;
|
||||
|
||||
/// <summary>
|
||||
/// 集合部分
|
||||
/// </summary>
|
||||
internal sealed partial class CultivationService
|
||||
{
|
||||
private ObservableCollection<CultivateProject>? projects;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CultivateProject? Current
|
||||
{
|
||||
get => dbCurrent.Current;
|
||||
set => dbCurrent.Current = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ObservableCollection<CultivateProject> ProjectCollection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (projects is null)
|
||||
{
|
||||
projects = cultivationDbService.GetCultivateProjectCollection();
|
||||
Current ??= projects.SelectedOrDefault();
|
||||
}
|
||||
|
||||
return projects;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask<ProjectAddResult> TryAddProjectAsync(CultivateProject project)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(project.Name))
|
||||
{
|
||||
return ProjectAddResult.InvalidName;
|
||||
}
|
||||
|
||||
ArgumentNullException.ThrowIfNull(projects);
|
||||
|
||||
if (projects.Any(a => a.Name == project.Name))
|
||||
{
|
||||
return ProjectAddResult.AlreadyExists;
|
||||
}
|
||||
|
||||
// Sync cache
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
projects.Add(project);
|
||||
|
||||
// Sync database
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
await cultivationDbService.AddCultivateProjectAsync(project).ConfigureAwait(false);
|
||||
|
||||
return ProjectAddResult.Added;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask RemoveProjectAsync(CultivateProject project)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(projects);
|
||||
|
||||
// Sync cache
|
||||
// Keep this on main thread.
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
projects.Remove(project);
|
||||
|
||||
// Sync database
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
await cultivationDbService.RemoveCultivateProjectByIdAsync(project.InnerId).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,13 @@
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using Snap.Hutao.Model.Entity.Primitive;
|
||||
using Snap.Hutao.Model.Metadata.Item;
|
||||
using Snap.Hutao.Service.Inventory;
|
||||
using Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
using Snap.Hutao.ViewModel.Cultivation;
|
||||
using System.Collections.ObjectModel;
|
||||
using CalculateItem = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.Item;
|
||||
|
||||
namespace Snap.Hutao.Service.Cultivation;
|
||||
|
||||
@@ -25,28 +25,46 @@ internal sealed partial class CultivationService : ICultivationService
|
||||
private readonly ScopedDbCurrent<CultivateProject, Message.CultivateProjectChangedMessage> dbCurrent;
|
||||
private readonly ICultivationDbService cultivationDbService;
|
||||
private readonly IInventoryDbService inventoryDbService;
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly ITaskContext taskContext;
|
||||
|
||||
private ObservableCollection<CultivateProject>? projects;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CultivateProject? Current
|
||||
{
|
||||
get => dbCurrent.Current;
|
||||
set => dbCurrent.Current = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ObservableCollection<CultivateProject> ProjectCollection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (projects is null)
|
||||
{
|
||||
projects = cultivationDbService.GetCultivateProjectCollection();
|
||||
Current ??= projects.SelectedOrDefault();
|
||||
}
|
||||
|
||||
return projects;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public List<InventoryItemView> GetInventoryItemViews(CultivateProject cultivateProject, ICultivationMetadataContext context, ICommand saveCommand)
|
||||
{
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
Guid projectId = cultivateProject.InnerId;
|
||||
List<InventoryItem> entities = cultivationDbService.GetInventoryItemListByProjectId(projectId);
|
||||
|
||||
List<InventoryItemView> results = [];
|
||||
foreach (Material meta in context.EnumerateInventoryMaterial())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
|
||||
Guid projectId = cultivateProject.InnerId;
|
||||
List<InventoryItem> entities = cultivationDbService.GetInventoryItemListByProjectId(projectId);
|
||||
|
||||
List<InventoryItemView> results = [];
|
||||
foreach (Material meta in context.EnumerateInventoryMaterial())
|
||||
{
|
||||
InventoryItem entity = entities.SingleOrDefault(e => e.ItemId == meta.Id) ?? InventoryItem.From(projectId, meta.Id);
|
||||
results.Add(new(entity, meta, saveCommand));
|
||||
}
|
||||
|
||||
return results;
|
||||
InventoryItem entity = entities.SingleOrDefault(e => e.ItemId == meta.Id) ?? InventoryItem.From(projectId, meta.Id);
|
||||
results.Add(new(entity, meta, saveCommand));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -54,13 +72,15 @@ internal sealed partial class CultivationService : ICultivationService
|
||||
{
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
List<CultivateEntry> entries = await cultivationDbService
|
||||
.GetCultivateEntryIncludeLevelInformationListByProjectIdAsync(cultivateProject.InnerId)
|
||||
.GetCultivateEntryListIncludingLevelInformationByProjectIdAsync(cultivateProject.InnerId)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
List<CultivateEntryView> resultEntries = new(entries.Count);
|
||||
foreach (CultivateEntry entry in entries)
|
||||
{
|
||||
List<CultivateItemView> entryItems = [];
|
||||
|
||||
// Async operation here, thus we can't use the Span trick.
|
||||
foreach (CultivateItem cultivateItem in await cultivationDbService.GetCultivateItemListByEntryIdAsync(entry.InnerId).ConfigureAwait(false))
|
||||
{
|
||||
entryItems.Add(new(cultivateItem, context.GetMaterial(cultivateItem.ItemId)));
|
||||
@@ -78,9 +98,7 @@ internal sealed partial class CultivationService : ICultivationService
|
||||
resultEntries.Add(new(entry, item, entryItems));
|
||||
}
|
||||
|
||||
return resultEntries
|
||||
.OrderByDescending(e => e.IsToday)
|
||||
.ToObservableCollection();
|
||||
return resultEntries.SortByDescending(e => e.IsToday).ToObservableCollection();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -92,11 +110,9 @@ internal sealed partial class CultivationService : ICultivationService
|
||||
|
||||
Guid projectId = cultivateProject.InnerId;
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
foreach (CultivateEntry entry in await cultivationDbService.GetCultivateEntryListByProjectIdAsync(projectId).ConfigureAwait(false))
|
||||
foreach (CultivateEntry entry in await cultivationDbService.GetCultivateEntryListByProjectIdAsync(projectId, token).ConfigureAwait(false))
|
||||
{
|
||||
foreach (CultivateItem item in await cultivationDbService.GetCultivateItemListByEntryIdAsync(entry.InnerId).ConfigureAwait(false))
|
||||
foreach (CultivateItem item in await cultivationDbService.GetCultivateItemListByEntryIdAsync(entry.InnerId, token).ConfigureAwait(false))
|
||||
{
|
||||
if (item.IsFinished)
|
||||
{
|
||||
@@ -114,9 +130,7 @@ internal sealed partial class CultivationService : ICultivationService
|
||||
}
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
foreach (InventoryItem inventoryItem in await cultivationDbService.GetInventoryItemListByProjectIdAsync(projectId).ConfigureAwait(false))
|
||||
foreach (InventoryItem inventoryItem in await cultivationDbService.GetInventoryItemListByProjectIdAsync(projectId, token).ConfigureAwait(false))
|
||||
{
|
||||
if (resultItems.SingleOrDefault(i => i.Inner.Id == inventoryItem.ItemId) is { } existedItem)
|
||||
{
|
||||
@@ -124,15 +138,12 @@ internal sealed partial class CultivationService : ICultivationService
|
||||
}
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
return resultItems.SortBy(item => item.Inner.Id, MaterialIdComparer.Shared).ToObservableCollection();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask RemoveCultivateEntryAsync(Guid entryId)
|
||||
{
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
await cultivationDbService.RemoveCultivateEntryByIdAsync(entryId).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -149,7 +160,7 @@ internal sealed partial class CultivationService : ICultivationService
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask<bool> SaveConsumptionAsync(CultivateType type, uint itemId, List<Web.Hoyolab.Takumi.Event.Calculate.Item> items, LevelInformation levelInformation)
|
||||
public async ValueTask<bool> SaveConsumptionAsync(CultivateType type, uint itemId, List<CalculateItem> items, LevelInformation levelInformation)
|
||||
{
|
||||
if (items.Count == 0)
|
||||
{
|
||||
@@ -190,4 +201,45 @@ internal sealed partial class CultivationService : ICultivationService
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask<ProjectAddResultKind> TryAddProjectAsync(CultivateProject project)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(project.Name))
|
||||
{
|
||||
return ProjectAddResultKind.InvalidName;
|
||||
}
|
||||
|
||||
ArgumentNullException.ThrowIfNull(projects);
|
||||
|
||||
if (projects.Any(a => a.Name == project.Name))
|
||||
{
|
||||
return ProjectAddResultKind.AlreadyExists;
|
||||
}
|
||||
|
||||
// Sync cache
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
projects.Add(project);
|
||||
|
||||
// Sync database
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
await cultivationDbService.AddCultivateProjectAsync(project).ConfigureAwait(false);
|
||||
|
||||
return ProjectAddResultKind.Added;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask RemoveProjectAsync(CultivateProject project)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(projects);
|
||||
|
||||
// Sync cache
|
||||
// Keep this on main thread.
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
projects.Remove(project);
|
||||
|
||||
// Sync database
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
await cultivationDbService.RemoveCultivateProjectByIdAsync(project.InnerId).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -2,43 +2,48 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Snap.Hutao.Service.Cultivation;
|
||||
|
||||
internal interface ICultivationDbService
|
||||
internal interface ICultivationDbService : IAppDbService<InventoryItem>,
|
||||
IAppDbService<CultivateEntryLevelInformation>,
|
||||
IAppDbService<CultivateProject>,
|
||||
IAppDbService<CultivateEntry>,
|
||||
IAppDbService<CultivateItem>
|
||||
{
|
||||
ValueTask AddCultivateProjectAsync(CultivateProject project);
|
||||
ValueTask AddCultivateProjectAsync(CultivateProject project, CancellationToken token = default);
|
||||
|
||||
ValueTask RemoveCultivateEntryByIdAsync(Guid entryId);
|
||||
ValueTask RemoveCultivateEntryByIdAsync(Guid entryId, CancellationToken token = default);
|
||||
|
||||
ValueTask RemoveCultivateItemRangeByEntryIdAsync(Guid entryId);
|
||||
ValueTask RemoveCultivateItemRangeByEntryIdAsync(Guid entryId, CancellationToken token = default);
|
||||
|
||||
ValueTask RemoveCultivateProjectByIdAsync(Guid projectId);
|
||||
ValueTask RemoveCultivateProjectByIdAsync(Guid projectId, CancellationToken token = default);
|
||||
|
||||
ValueTask<CultivateEntry?> GetCultivateEntryByProjectIdAndItemIdAsync(Guid projectId, uint itemId);
|
||||
ValueTask<CultivateEntry?> GetCultivateEntryByProjectIdAndItemIdAsync(Guid projectId, uint itemId, CancellationToken token = default);
|
||||
|
||||
ValueTask<List<CultivateEntry>> GetCultivateEntryListByProjectIdAsync(Guid projectId);
|
||||
ValueTask<List<CultivateEntry>> GetCultivateEntryListByProjectIdAsync(Guid projectId, CancellationToken token = default);
|
||||
|
||||
ValueTask<List<CultivateItem>> GetCultivateItemListByEntryIdAsync(Guid entryId);
|
||||
ValueTask<List<CultivateItem>> GetCultivateItemListByEntryIdAsync(Guid entryId, CancellationToken token = default);
|
||||
|
||||
ObservableCollection<CultivateProject> GetCultivateProjectCollection();
|
||||
|
||||
List<InventoryItem> GetInventoryItemListByProjectId(Guid projectId);
|
||||
|
||||
ValueTask<List<InventoryItem>> GetInventoryItemListByProjectIdAsync(Guid projectId);
|
||||
ValueTask<List<InventoryItem>> GetInventoryItemListByProjectIdAsync(Guid projectId, CancellationToken token = default);
|
||||
|
||||
ValueTask AddCultivateEntryAsync(CultivateEntry entry);
|
||||
ValueTask AddCultivateEntryAsync(CultivateEntry entry, CancellationToken token = default);
|
||||
|
||||
ValueTask AddCultivateItemRangeAsync(IEnumerable<CultivateItem> toAdd);
|
||||
ValueTask AddCultivateItemRangeAsync(IEnumerable<CultivateItem> toAdd, CancellationToken token = default);
|
||||
|
||||
void UpdateCultivateItem(CultivateItem item);
|
||||
|
||||
ValueTask UpdateCultivateItemAsync(CultivateItem item);
|
||||
ValueTask UpdateCultivateItemAsync(CultivateItem item, CancellationToken token = default);
|
||||
|
||||
ValueTask RemoveLevelInformationByEntryIdAsync(Guid entryId);
|
||||
ValueTask RemoveLevelInformationByEntryIdAsync(Guid entryId, CancellationToken token = default);
|
||||
|
||||
ValueTask AddLevelInformationAsync(CultivateEntryLevelInformation levelInformation);
|
||||
ValueTask AddLevelInformationAsync(CultivateEntryLevelInformation levelInformation, CancellationToken token = default);
|
||||
|
||||
ValueTask<List<CultivateEntry>> GetCultivateEntryIncludeLevelInformationListByProjectIdAsync(Guid projectId);
|
||||
ValueTask<List<CultivateEntry>> GetCultivateEntryListIncludingLevelInformationByProjectIdAsync(Guid projectId, CancellationToken token = default);
|
||||
}
|
||||
@@ -65,5 +65,5 @@ internal interface ICultivationService
|
||||
/// </summary>
|
||||
/// <param name="project">项目</param>
|
||||
/// <returns>添加操作的结果</returns>
|
||||
ValueTask<ProjectAddResult> TryAddProjectAsync(CultivateProject project);
|
||||
ValueTask<ProjectAddResultKind> TryAddProjectAsync(CultivateProject project);
|
||||
}
|
||||
@@ -8,9 +8,10 @@ namespace Snap.Hutao.Service.Cultivation;
|
||||
|
||||
internal sealed class MaterialIdComparer : IComparer<MaterialId>
|
||||
{
|
||||
private static readonly Lazy<MaterialIdComparer> LazyShared = new(() => new());
|
||||
private static MaterialIdComparer? shared;
|
||||
private static object? syncRoot;
|
||||
|
||||
public static MaterialIdComparer Shared { get => LazyShared.Value; }
|
||||
public static MaterialIdComparer Shared { get => LazyInitializer.EnsureInitialized(ref shared, ref syncRoot, () => new()); }
|
||||
|
||||
public int Compare(MaterialId x, MaterialId y)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Snap.Hutao.Service.Cultivation;
|
||||
/// 项目添加结果
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal enum ProjectAddResult
|
||||
internal enum ProjectAddResultKind
|
||||
{
|
||||
/// <summary>
|
||||
/// 添加成功
|
||||
@@ -25,7 +25,7 @@ internal sealed partial class DailyNoteNotificationOperation
|
||||
|
||||
private readonly ITaskContext taskContext;
|
||||
private readonly IGameServiceFacade gameService;
|
||||
private readonly BindingClient bindingClient;
|
||||
private readonly IServiceScopeFactory serviceScopeFactory;
|
||||
private readonly DailyNoteOptions options;
|
||||
private readonly RuntimeOptions runtimeOptions;
|
||||
|
||||
@@ -58,14 +58,19 @@ internal sealed partial class DailyNoteNotificationOperation
|
||||
}
|
||||
else
|
||||
{
|
||||
Response<ListWrapper<UserGameRole>> rolesResponse = await bindingClient
|
||||
.GetUserGameRolesOverseaAwareAsync(entry.User)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (rolesResponse.IsOk())
|
||||
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||
{
|
||||
List<UserGameRole> roles = rolesResponse.Data.List;
|
||||
attribution = roles.SingleOrDefault(r => r.GameUid == entry.Uid)?.ToString() ?? ToastAttributionUnknown;
|
||||
BindingClient bindingClient = scope.ServiceProvider.GetRequiredService<BindingClient>();
|
||||
|
||||
Response<ListWrapper<UserGameRole>> rolesResponse = await bindingClient
|
||||
.GetUserGameRolesOverseaAwareAsync(entry.User)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (rolesResponse.IsOk())
|
||||
{
|
||||
List<UserGameRole> roles = rolesResponse.Data.List;
|
||||
attribution = roles.SingleOrDefault(r => r.GameUid == entry.Uid)?.ToString() ?? ToastAttributionUnknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
||||
{
|
||||
try
|
||||
{
|
||||
ValueResult<RefreshResult, Summary?> summaryResult;
|
||||
ValueResult<RefreshResultKind, Summary?> summaryResult;
|
||||
using (await EnterCriticalExecutionAsync().ConfigureAwait(false))
|
||||
{
|
||||
ContentDialog dialog = await contentDialogFactory
|
||||
@@ -135,8 +135,8 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
||||
}
|
||||
}
|
||||
|
||||
(RefreshResult result, Summary? summary) = summaryResult;
|
||||
if (result == RefreshResult.Ok)
|
||||
(RefreshResultKind result, Summary? summary) = summaryResult;
|
||||
if (result == RefreshResultKind.Ok)
|
||||
{
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
Summary = summary;
|
||||
@@ -146,16 +146,16 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case RefreshResult.APIUnavailable:
|
||||
case RefreshResultKind.APIUnavailable:
|
||||
infoBarService.Warning(SH.ViewModelAvatarPropertyEnkaApiUnavailable);
|
||||
break;
|
||||
|
||||
case RefreshResult.StatusCodeNotSucceed:
|
||||
case RefreshResultKind.StatusCodeNotSucceed:
|
||||
ArgumentNullException.ThrowIfNull(summary);
|
||||
infoBarService.Warning(summary.Message);
|
||||
break;
|
||||
|
||||
case RefreshResult.ShowcaseNotOpen:
|
||||
case RefreshResultKind.ShowcaseNotOpen:
|
||||
infoBarService.Warning(SH.ViewModelAvatarPropertyShowcaseNotOpen);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -86,15 +86,15 @@ internal sealed partial class CultivationViewModel : Abstraction.ViewModel
|
||||
|
||||
switch (await cultivationService.TryAddProjectAsync(project).ConfigureAwait(false))
|
||||
{
|
||||
case ProjectAddResult.Added:
|
||||
case ProjectAddResultKind.Added:
|
||||
infoBarService.Success(SH.ViewModelCultivationProjectAdded);
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
SelectedProject = project;
|
||||
break;
|
||||
case ProjectAddResult.InvalidName:
|
||||
case ProjectAddResultKind.InvalidName:
|
||||
infoBarService.Information(SH.ViewModelCultivationProjectInvalidName);
|
||||
break;
|
||||
case ProjectAddResult.AlreadyExists:
|
||||
case ProjectAddResultKind.AlreadyExists:
|
||||
infoBarService.Information(SH.ViewModelCultivationProjectAlreadyExists);
|
||||
break;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user