mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
code style
This commit is contained in:
@@ -7,7 +7,6 @@ using Microsoft.Windows.AppLifecycle;
|
||||
using Snap.Hutao.Core;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Core.LifeCycle;
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using System.Diagnostics;
|
||||
using Windows.Storage;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ internal static class ContentDialogExtension
|
||||
contentDialog.ShowAsync().AsTask().SafeForget();
|
||||
|
||||
// E_ASYNC_OPERATION_NOT_STARTED 0x80000019
|
||||
// Only a single ContentDialog can be open at any time.
|
||||
return new ContentDialogHider(contentDialog);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Snap.Hutao.Control.Image;
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Snap.Hutao.Core.Annotation;
|
||||
namespace Snap.Hutao.Core.Annotation;
|
||||
|
||||
/// <summary>
|
||||
/// 本地化键
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using System.IO;
|
||||
|
||||
namespace Snap.Hutao.Core.IO;
|
||||
@@ -16,7 +17,14 @@ internal sealed class TempFile : IDisposable
|
||||
/// <param name="delete">是否在创建时删除文件</param>
|
||||
public TempFile(bool delete = false)
|
||||
{
|
||||
Path = System.IO.Path.GetTempFileName();
|
||||
try
|
||||
{
|
||||
Path = System.IO.Path.GetTempFileName();
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
throw ThrowHelper.RuntimeEnvironment(SH.CoreIOTempFileCreateFail, ex);
|
||||
}
|
||||
|
||||
if (delete)
|
||||
{
|
||||
|
||||
@@ -109,7 +109,7 @@ internal static class Activation
|
||||
|
||||
private static async Task HandleActivationCoreAsync(AppActivationArguments args, bool isRedirected)
|
||||
{
|
||||
if (args.Kind == ExtendedActivationKind.Protocol)
|
||||
if (args.Kind == ExtendedActivationKind.Protocol)
|
||||
{
|
||||
if (args.TryGetProtocolActivatedUri(out Uri? uri))
|
||||
{
|
||||
|
||||
@@ -10,7 +10,6 @@ using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Message;
|
||||
using Snap.Hutao.Win32;
|
||||
using System.IO;
|
||||
using Windows.ApplicationModel;
|
||||
using Windows.Graphics;
|
||||
using Windows.UI;
|
||||
using Windows.Win32.Foundation;
|
||||
|
||||
@@ -29,7 +29,7 @@ public class SpiralAbyssEntry : ObservableObject
|
||||
/// 计划名称
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
public string Schedule { get => $"第 {ScheduleId} 期"; }
|
||||
public string Schedule { get => string.Format(SH.ModelEntitySpiralAbyssScheduleFormat, ScheduleId); }
|
||||
|
||||
/// <summary>
|
||||
/// Uid
|
||||
|
||||
@@ -195,6 +195,15 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 权限不足,创建临时文件失败 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string CoreIOTempFileCreateFail {
|
||||
get {
|
||||
return ResourceManager.GetString("CoreIOTempFileCreateFail", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 启动游戏 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -339,6 +348,15 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 第 {0} 期 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ModelEntitySpiralAbyssScheduleFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("ModelEntitySpiralAbyssScheduleFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 必须先选择一个用户与角色 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -357,6 +375,24 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 保存养成计划状态失败 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ServiceCultivationProjectCurrentUserdataCourrpted {
|
||||
get {
|
||||
return ResourceManager.GetString("ServiceCultivationProjectCurrentUserdataCourrpted", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 存在多个选中的养成计划 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ServiceCultivationProjectCurrentUserdataCourrpted2 {
|
||||
get {
|
||||
return ResourceManager.GetString("ServiceCultivationProjectCurrentUserdataCourrpted2", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 开始游戏 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -1437,6 +1473,15 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 养成计划添加失败 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewModelCultivationAddWarning {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewModelCultivationAddWarning", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 已成功添加至当前养成计划 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -162,6 +162,9 @@
|
||||
<data name="CoreIOPickerExtensionPickerExceptionInfoBarTitle" xml:space="preserve">
|
||||
<value>无法打开文件选择器</value>
|
||||
</data>
|
||||
<data name="CoreIOTempFileCreateFail" xml:space="preserve">
|
||||
<value>权限不足,创建临时文件失败</value>
|
||||
</data>
|
||||
<data name="CoreJumpListHelperLaunchGameItemDisplayName" xml:space="preserve">
|
||||
<value>启动游戏</value>
|
||||
</data>
|
||||
@@ -210,12 +213,21 @@
|
||||
<data name="ModelBingGachaWishBaseTotalCountFormat" xml:space="preserve">
|
||||
<value>{0} 抽</value>
|
||||
</data>
|
||||
<data name="ModelEntitySpiralAbyssScheduleFormat" xml:space="preserve">
|
||||
<value>第 {0} 期</value>
|
||||
</data>
|
||||
<data name="MustSelectUserAndUid" xml:space="preserve">
|
||||
<value>必须先选择一个用户与角色</value>
|
||||
</data>
|
||||
<data name="ServiceAchievementUserdataCorruptedInnerIdNotUnique" xml:space="preserve">
|
||||
<value>单个成就存档内发现多个相同的成就 Id</value>
|
||||
</data>
|
||||
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
|
||||
<value>保存养成计划状态失败</value>
|
||||
</data>
|
||||
<data name="ServiceCultivationProjectCurrentUserdataCourrpted2" xml:space="preserve">
|
||||
<value>存在多个选中的养成计划</value>
|
||||
</data>
|
||||
<data name="ServiceDailyNoteNotifierActionLaunchGameButton" xml:space="preserve">
|
||||
<value>开始游戏</value>
|
||||
</data>
|
||||
@@ -576,6 +588,9 @@
|
||||
<data name="ViewModelAvatarPropertyShowcaseNotOpen" xml:space="preserve">
|
||||
<value>角色展柜尚未开启,请前往游戏操作后重试</value>
|
||||
</data>
|
||||
<data name="ViewModelCultivationAddWarning" xml:space="preserve">
|
||||
<value>养成计划添加失败</value>
|
||||
</data>
|
||||
<data name="ViewModelCultivationEntryAddSuccess" xml:space="preserve">
|
||||
<value>已成功添加至当前养成计划</value>
|
||||
</data>
|
||||
|
||||
@@ -6,7 +6,6 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Core.Diagnostics;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using Snap.Hutao.Model.InterChange.Achievement;
|
||||
|
||||
@@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
@@ -55,10 +56,21 @@ internal class CultivationService : ICultivationService
|
||||
using (IServiceScope scope = scopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
projects = new(appDbContext.CultivateProjects.AsNoTracking().ToList());
|
||||
projects = appDbContext.CultivateProjects.AsNoTracking().ToObservableCollection();
|
||||
}
|
||||
|
||||
Current ??= projects.SingleOrDefault(proj => proj.IsSelected);
|
||||
try
|
||||
{
|
||||
Current ??= projects.SingleOrDefault(proj => proj.IsSelected);
|
||||
}
|
||||
catch (DbUpdateConcurrencyException ex)
|
||||
{
|
||||
ThrowHelper.UserdataCorrupted(SH.ServiceCultivationProjectCurrentUserdataCourrpted, ex);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
ThrowHelper.UserdataCorrupted(SH.ServiceCultivationProjectCurrentUserdataCourrpted2, ex);
|
||||
}
|
||||
}
|
||||
|
||||
return projects;
|
||||
@@ -277,7 +289,15 @@ internal class CultivationService : ICultivationService
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
|
||||
Current ??= appDbContext.CultivateProjects.AsNoTracking().SingleOrDefault(proj => proj.IsSelected);
|
||||
try
|
||||
{
|
||||
Current ??= appDbContext.CultivateProjects.AsNoTracking().SingleOrDefault(proj => proj.IsSelected);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
ThrowHelper.UserdataCorrupted(SH.ServiceCultivationProjectCurrentUserdataCourrpted2, ex);
|
||||
}
|
||||
|
||||
if (Current == null)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
using Snap.Hutao.Model.Binding.Cultivation;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Metadata;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using Snap.Hutao.Model.Metadata.Converter;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Auth;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.DailyNote;
|
||||
|
||||
@@ -16,7 +16,6 @@ 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.Abstraction;
|
||||
using Snap.Hutao.Service.GachaLog.Factory;
|
||||
using Snap.Hutao.Service.GachaLog.QueryProvider;
|
||||
using Snap.Hutao.Service.Metadata;
|
||||
@@ -122,7 +121,7 @@ internal class GachaLogService : IGachaLogService
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
try
|
||||
{
|
||||
archiveCollection ??= appDbContext.GachaArchives.AsNoTracking().ToObservableCollection();
|
||||
archiveCollection ??= appDbContext.GachaArchives.AsNoTracking().ToObservableCollection();
|
||||
}
|
||||
catch (SqliteException ex)
|
||||
{
|
||||
@@ -329,6 +328,8 @@ internal class GachaLogService : IGachaLogService
|
||||
GachaArchive created = GachaArchive.Create(uid);
|
||||
appDbContext.GachaArchives.AddAndSave(created);
|
||||
|
||||
// System.InvalidOperationException: Sequence contains no elements
|
||||
// ? how this happen here?
|
||||
archive = appDbContext.GachaArchives.Single(a => a.Uid == uid);
|
||||
GachaArchive temp = archive;
|
||||
ThreadHelper.InvokeOnMainThread(() => archiveCollection!.Add(temp));
|
||||
|
||||
@@ -48,7 +48,7 @@ internal class GachaLogQueryWebCacheProvider : IGachaLogQueryProvider
|
||||
{
|
||||
(bool isOk, string path) = await gameService.GetGamePathAsync().ConfigureAwait(false);
|
||||
|
||||
if (isOk)
|
||||
if (isOk && (!string.IsNullOrEmpty(path)))
|
||||
{
|
||||
string cacheFile = GetCacheFile(path);
|
||||
|
||||
|
||||
@@ -59,14 +59,13 @@ internal class GameService : IGameService
|
||||
{
|
||||
if (memoryCache.TryGetValue(GamePathKey, out object? value))
|
||||
{
|
||||
return new(true, Must.NotNull((value as string)!));
|
||||
return new(true, (value as string)!);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (IServiceScope scope = scopeFactory.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
|
||||
SettingEntry entry = await appDbContext.Settings.SingleOrAddAsync(SettingEntry.GamePath, string.Empty).ConfigureAwait(false);
|
||||
|
||||
// Cannot find in setting
|
||||
@@ -89,7 +88,7 @@ internal class GameService : IGameService
|
||||
{
|
||||
// Save result.
|
||||
entry.Value = result.Value;
|
||||
appDbContext.Settings.UpdateAndSave(entry);
|
||||
await appDbContext.Settings.UpdateAndSaveAsync(entry).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
|
||||
using Snap.Hutao.Core.IO;
|
||||
using Snap.Hutao.Model.Binding.LaunchGame;
|
||||
using Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net.Http;
|
||||
using static Snap.Hutao.Service.Game.GameConstants;
|
||||
|
||||
namespace Snap.Hutao.Service.Game.Package;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
|
||||
using Snap.Hutao.Core.Diagnostics;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Core.IO;
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using Snap.Hutao.Extension;
|
||||
@@ -11,7 +12,6 @@ using Snap.Hutao.Service.Abstraction;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Snap.Hutao.Service.Metadata;
|
||||
|
||||
@@ -180,10 +180,18 @@ internal partial class MetadataService : IMetadataService, IMetadataServiceIniti
|
||||
return Must.NotNull((T)value!);
|
||||
}
|
||||
|
||||
using (Stream fileStream = File.OpenRead(Path.Combine(metadataFolderPath, $"{fileName}.json")))
|
||||
string path = Path.Combine(metadataFolderPath, $"{fileName}.json");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
T? result = await JsonSerializer.DeserializeAsync<T>(fileStream, options, token).ConfigureAwait(false);
|
||||
return memoryCache.Set(cacheKey, Must.NotNull(result!));
|
||||
using (Stream fileStream = File.OpenRead(path))
|
||||
{
|
||||
T? result = await JsonSerializer.DeserializeAsync<T>(fileStream, options, token).ConfigureAwait(false);
|
||||
return memoryCache.Set(cacheKey, Must.NotNull(result!));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ThrowHelper.UserdataCorrupted(SH.ServiceMetadataNotInitialized, null!);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control;
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using Snap.Hutao.Core.Setting;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.View.Helper;
|
||||
|
||||
@@ -63,61 +63,38 @@ internal class SpiralAbyssRecordService : ISpiralAbyssRecordService
|
||||
/// <inheritdoc/>
|
||||
public async Task RefreshSpiralAbyssAsync(UserAndUid userAndUid)
|
||||
{
|
||||
Response<Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss> lastResponse = await gameRecordClient
|
||||
.GetSpiralAbyssAsync(userAndUid, SpiralAbyssSchedule.Last)
|
||||
await RefreshSpiralAbyssCoreAsync(userAndUid, SpiralAbyssSchedule.Last).ConfigureAwait(false);
|
||||
await RefreshSpiralAbyssCoreAsync(userAndUid, SpiralAbyssSchedule.Current).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task RefreshSpiralAbyssCoreAsync(UserAndUid userAndUid, SpiralAbyssSchedule schedule)
|
||||
{
|
||||
Response<Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss> response = await gameRecordClient
|
||||
.GetSpiralAbyssAsync(userAndUid, schedule)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (lastResponse.IsOk())
|
||||
if (response.IsOk())
|
||||
{
|
||||
Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss last = lastResponse.Data;
|
||||
Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss webSpiralAbyss = response.Data;
|
||||
|
||||
SpiralAbyssEntry? lastEntry = spiralAbysses!.SingleOrDefault(s => s.ScheduleId == last.ScheduleId);
|
||||
if (lastEntry != null)
|
||||
SpiralAbyssEntry? existEntry = spiralAbysses!.SingleOrDefault(s => s.ScheduleId == webSpiralAbyss.ScheduleId);
|
||||
if (existEntry != null)
|
||||
{
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
lastEntry.UpdateSpiralAbyss(last);
|
||||
existEntry.UpdateSpiralAbyss(webSpiralAbyss);
|
||||
|
||||
await ThreadHelper.SwitchToBackgroundAsync();
|
||||
await appDbContext.SpiralAbysses.UpdateAndSaveAsync(lastEntry).ConfigureAwait(false);
|
||||
await appDbContext.SpiralAbysses.UpdateAndSaveAsync(existEntry).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SpiralAbyssEntry entry = SpiralAbyssEntry.Create(userAndUid.Uid.Value, last);
|
||||
SpiralAbyssEntry newEntry = SpiralAbyssEntry.Create(userAndUid.Uid.Value, webSpiralAbyss);
|
||||
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
spiralAbysses!.Insert(0, entry);
|
||||
spiralAbysses!.Insert(0, newEntry);
|
||||
|
||||
await ThreadHelper.SwitchToBackgroundAsync();
|
||||
await appDbContext.SpiralAbysses.AddAndSaveAsync(entry).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
Response<Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss> currentResponse = await gameRecordClient
|
||||
.GetSpiralAbyssAsync(userAndUid, SpiralAbyssSchedule.Current)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (currentResponse.IsOk())
|
||||
{
|
||||
Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.SpiralAbyss current = currentResponse.Data;
|
||||
|
||||
SpiralAbyssEntry? currentEntry = spiralAbysses!.SingleOrDefault(s => s.ScheduleId == current.ScheduleId);
|
||||
if (currentEntry != null)
|
||||
{
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
currentEntry.UpdateSpiralAbyss(current);
|
||||
|
||||
await ThreadHelper.SwitchToBackgroundAsync();
|
||||
await appDbContext.SpiralAbysses.UpdateAndSaveAsync(currentEntry).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SpiralAbyssEntry entry = SpiralAbyssEntry.Create(userAndUid.Uid.Value, current);
|
||||
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
spiralAbysses!.Insert(0, entry);
|
||||
|
||||
await ThreadHelper.SwitchToBackgroundAsync();
|
||||
await appDbContext.SpiralAbysses.AddAndSaveAsync(entry).ConfigureAwait(false);
|
||||
await appDbContext.SpiralAbysses.AddAndSaveAsync(newEntry).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ internal class UserService : IUserService
|
||||
// Sync cache
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
userCollection!.Remove(user);
|
||||
roleCollection?.RemoveWhere(r => r.User.InnerId == user.Entity.InnerId);
|
||||
roleCollection?.RemoveWhere(r => r.User.Mid == user.Entity.Mid);
|
||||
|
||||
// Sync database
|
||||
await ThreadHelper.SwitchToBackgroundAsync();
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Snap.Hutao.Control;
|
||||
using Snap.Hutao.Control.Theme;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement;
|
||||
using Windows.System;
|
||||
|
||||
@@ -58,8 +56,8 @@ public sealed partial class AnnouncementContentViewer : Microsoft.UI.Xaml.Contro
|
||||
/// </summary>
|
||||
public Announcement Announcement
|
||||
{
|
||||
get { return (Announcement)GetValue(AnnouncementProperty); }
|
||||
set { SetValue(AnnouncementProperty, value); }
|
||||
get => (Announcement)GetValue(AnnouncementProperty);
|
||||
set => SetValue(AnnouncementProperty, value);
|
||||
}
|
||||
|
||||
private static string? GenerateHtml(Announcement? announcement, ElementTheme theme)
|
||||
|
||||
@@ -27,7 +27,7 @@ public sealed partial class StatisticsCard : UserControl
|
||||
/// </summary>
|
||||
public bool ShowUpPull
|
||||
{
|
||||
get { return (bool)GetValue(ShowUpPullProperty); }
|
||||
set { SetValue(ShowUpPullProperty, value); }
|
||||
get => (bool)GetValue(ShowUpPullProperty);
|
||||
set => SetValue(ShowUpPullProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Model.Binding.Gacha.Abstraction;
|
||||
using Snap.Hutao.Service.GachaLog;
|
||||
using Snap.Hutao.View.Control;
|
||||
using Snap.Hutao.Web.Hoyolab.Hk4e.Event.GachaInfo;
|
||||
|
||||
namespace Snap.Hutao.View.Dialog;
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ public sealed partial class LaunchGamePackageConvertDialog : ContentDialog
|
||||
/// </summary>
|
||||
public PackageReplaceStatus State
|
||||
{
|
||||
get { return (PackageReplaceStatus)GetValue(StateProperty); }
|
||||
set { SetValue(StateProperty, value); }
|
||||
get => (PackageReplaceStatus)GetValue(StateProperty);
|
||||
set => SetValue(StateProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,16 +29,23 @@ public sealed partial class LoginMihoyoUserPage : Microsoft.UI.Xaml.Controls.Pag
|
||||
[SuppressMessage("", "VSTHRD100")]
|
||||
private async void OnRootLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await WebView.EnsureCoreWebView2Async();
|
||||
|
||||
CoreWebView2CookieManager manager = WebView.CoreWebView2.CookieManager;
|
||||
IReadOnlyList<CoreWebView2Cookie> cookies = await manager.GetCookiesAsync("https://user.mihoyo.com");
|
||||
foreach (CoreWebView2Cookie item in cookies)
|
||||
try
|
||||
{
|
||||
manager.DeleteCookie(item);
|
||||
}
|
||||
await WebView.EnsureCoreWebView2Async();
|
||||
|
||||
WebView.CoreWebView2.Navigate("https://user.mihoyo.com/#/login/password");
|
||||
CoreWebView2CookieManager manager = WebView.CoreWebView2.CookieManager;
|
||||
IReadOnlyList<CoreWebView2Cookie> cookies = await manager.GetCookiesAsync("https://user.mihoyo.com");
|
||||
foreach (CoreWebView2Cookie item in cookies)
|
||||
{
|
||||
manager.DeleteCookie(item);
|
||||
}
|
||||
|
||||
WebView.CoreWebView2.Navigate("https://user.mihoyo.com/#/login/password");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Ioc.Default.GetRequiredService<IInfoBarService>().Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleCurrentCookieAsync(CancellationToken token)
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using Snap.Hutao.Control;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Snap.Hutao.ViewModel;
|
||||
|
||||
namespace Snap.Hutao.View.Page;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<shcb:InvokeCommandOnLoadedBehavior Command="{Binding OpenUICommand}"/>
|
||||
</mxi:Interaction.Behaviors>
|
||||
|
||||
<Grid>
|
||||
<Grid Visibility="{Binding IsInitialized, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<SplitView
|
||||
Grid.Row="1"
|
||||
DisplayMode="Inline"
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using Snap.Hutao.Control;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Snap.Hutao.ViewModel;
|
||||
|
||||
namespace Snap.Hutao.View.Page;
|
||||
|
||||
@@ -43,7 +43,7 @@ public abstract class ViewModel : ObservableObject, IViewModel
|
||||
/// 当页面被释放后抛出异常
|
||||
/// </summary>
|
||||
/// <exception cref="OperationCanceledException">操作被用户取消</exception>
|
||||
protected void ThrowIfViewDisposed()
|
||||
private void ThrowIfViewDisposed()
|
||||
{
|
||||
if (IsViewDisposed)
|
||||
{
|
||||
|
||||
@@ -5,10 +5,8 @@ using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.WinUI.UI;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Core.IO;
|
||||
using Snap.Hutao.Core.IO.DataTransfer;
|
||||
using Snap.Hutao.Core.LifeCycle;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Factory.Abstraction;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
@@ -18,7 +19,6 @@ using Snap.Hutao.Service.AvatarInfo;
|
||||
using Snap.Hutao.Service.Cultivation;
|
||||
using Snap.Hutao.Service.User;
|
||||
using Snap.Hutao.View.Dialog;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
||||
using Snap.Hutao.Web.Response;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Graphics.Imaging;
|
||||
@@ -39,30 +39,21 @@ namespace Snap.Hutao.ViewModel;
|
||||
[Injection(InjectAs.Scoped)]
|
||||
internal class AvatarPropertyViewModel : Abstraction.ViewModel
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly IUserService userService;
|
||||
private readonly IAvatarInfoService avatarInfoService;
|
||||
private readonly IInfoBarService infoBarService;
|
||||
private readonly IContentDialogFactory contentDialogFactory;
|
||||
private Summary? summary;
|
||||
private Avatar? selectedAvatar;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的角色属性视图模型
|
||||
/// </summary>
|
||||
/// <param name="userService">用户服务</param>
|
||||
/// <param name="avatarInfoService">角色信息服务</param>
|
||||
/// <param name="contentDialogFactory">对话框工厂</param>
|
||||
/// <param name="infoBarService">信息条服务</param>
|
||||
public AvatarPropertyViewModel(
|
||||
IUserService userService,
|
||||
IAvatarInfoService avatarInfoService,
|
||||
IContentDialogFactory contentDialogFactory,
|
||||
IInfoBarService infoBarService)
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
public AvatarPropertyViewModel(IServiceProvider serviceProvider)
|
||||
{
|
||||
this.userService = userService;
|
||||
this.avatarInfoService = avatarInfoService;
|
||||
this.infoBarService = infoBarService;
|
||||
this.contentDialogFactory = contentDialogFactory;
|
||||
userService = serviceProvider.GetRequiredService<IUserService>();
|
||||
infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
RefreshFromEnkaApiCommand = new AsyncRelayCommand(RefreshByEnkaApiAsync);
|
||||
@@ -159,14 +150,18 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel
|
||||
ValueResult<RefreshResult, Summary?> summaryResult;
|
||||
using (await EnterCriticalExecutionAsync().ConfigureAwait(false))
|
||||
{
|
||||
ContentDialog dialog = await contentDialogFactory
|
||||
ContentDialog dialog = await serviceProvider
|
||||
.GetRequiredService<IContentDialogFactory>()
|
||||
.CreateForIndeterminateProgressAsync(SH.ViewModelAvatarPropertyFetch)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
await using (await dialog.BlockAsync().ConfigureAwait(false))
|
||||
{
|
||||
summaryResult = await avatarInfoService.GetSummaryAsync(userAndUid, option, token).ConfigureAwait(false);
|
||||
summaryResult = await serviceProvider
|
||||
.GetRequiredService<IAvatarInfoService>()
|
||||
.GetSummaryAsync(userAndUid, option, token)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,9 +194,6 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel
|
||||
{
|
||||
if (avatar != null)
|
||||
{
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
IUserService userService = Ioc.Default.GetRequiredService<IUserService>();
|
||||
|
||||
if (userService.Current != null)
|
||||
{
|
||||
if (avatar.Weapon == null)
|
||||
@@ -218,14 +210,14 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel
|
||||
|
||||
if (isOk)
|
||||
{
|
||||
Response<CalcConsumption> consumptionResponse = await Ioc.Default
|
||||
Response<CalcConsumption> consumptionResponse = await serviceProvider
|
||||
.GetRequiredService<CalcClient>()
|
||||
.ComputeAsync(userService.Current.Entity, delta)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (consumptionResponse.IsOk())
|
||||
{
|
||||
ICultivationService cultivationService = Ioc.Default.GetRequiredService<ICultivationService>();
|
||||
ICultivationService cultivationService = serviceProvider.GetRequiredService<ICultivationService>();
|
||||
CalcConsumption consumption = consumptionResponse.Data;
|
||||
|
||||
List<CalcItem> items = CalcItemHelper.Merge(consumption.AvatarConsume, consumption.AvatarSkillConsume);
|
||||
@@ -233,18 +225,25 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel
|
||||
.SaveConsumptionAsync(CultivateType.AvatarAndSkill, avatar.Id, items)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// take a hot path if avatar is not saved.
|
||||
bool avatarAndWeaponSaved = avatarSaved && await cultivationService
|
||||
.SaveConsumptionAsync(CultivateType.Weapon, avatar.Weapon.Id, consumption.WeaponConsume.EmptyIfNull())
|
||||
.ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
// take a hot path if avatar is not saved.
|
||||
bool avatarAndWeaponSaved = avatarSaved && await cultivationService
|
||||
.SaveConsumptionAsync(CultivateType.Weapon, avatar.Weapon.Id, consumption.WeaponConsume.EmptyIfNull())
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (avatarAndWeaponSaved)
|
||||
{
|
||||
infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
|
||||
if (avatarAndWeaponSaved)
|
||||
{
|
||||
infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Core.ExceptionService.UserdataCorruptedException ex)
|
||||
{
|
||||
infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
|
||||
infoBarService.Error(ex, SH.ViewModelCultivationAddWarning);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,7 +266,7 @@ internal class AvatarPropertyViewModel : Abstraction.ViewModel
|
||||
bool clipboardOpened = false;
|
||||
using (SoftwareBitmap softwareBitmap = SoftwareBitmap.CreateCopyFromBuffer(buffer, BitmapPixelFormat.Bgra8, bitmap.PixelWidth, bitmap.PixelHeight))
|
||||
{
|
||||
Color tintColor = (Color)Ioc.Default.GetRequiredService<App>().Resources["CompatBackgroundColor"];
|
||||
Color tintColor = (Color)serviceProvider.GetRequiredService<App>().Resources["CompatBackgroundColor"];
|
||||
Bgra8 tint = Bgra8.FromColor(tintColor);
|
||||
softwareBitmap.NormalBlend(tint);
|
||||
using (InMemoryRandomAccessStream memory = new())
|
||||
|
||||
@@ -51,18 +51,11 @@ internal class DailyNoteViewModel : Abstraction.ViewModel
|
||||
/// 构造一个新的实时便笺视图模型
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
/// <param name="userService">用户服务</param>
|
||||
/// <param name="dailyNoteService">实时便笺服务</param>
|
||||
/// <param name="appDbContext">数据库上下文</param>
|
||||
public DailyNoteViewModel(
|
||||
IServiceProvider serviceProvider,
|
||||
IUserService userService,
|
||||
IDailyNoteService dailyNoteService,
|
||||
AppDbContext appDbContext)
|
||||
public DailyNoteViewModel(IServiceProvider serviceProvider)
|
||||
{
|
||||
this.userService = userService;
|
||||
this.dailyNoteService = dailyNoteService;
|
||||
this.appDbContext = appDbContext;
|
||||
userService = serviceProvider.GetRequiredService<IUserService>();
|
||||
dailyNoteService = serviceProvider.GetRequiredService<IDailyNoteService>();
|
||||
appDbContext = serviceProvider.GetRequiredService<AppDbContext>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
@@ -92,7 +85,7 @@ internal class DailyNoteViewModel : Abstraction.ViewModel
|
||||
{
|
||||
if (!ScheduleTaskHelper.RegisterForDailyNoteRefresh(value.Value))
|
||||
{
|
||||
Ioc.Default.GetRequiredService<IInfoBarService>().Warning(SH.ViewModelDailyNoteRegisterTaskFail);
|
||||
serviceProvider.GetRequiredService<IInfoBarService>().Warning(SH.ViewModelDailyNoteRegisterTaskFail);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -244,10 +237,13 @@ internal class DailyNoteViewModel : Abstraction.ViewModel
|
||||
{
|
||||
if (entry != null)
|
||||
{
|
||||
// ContentDialog must be created by main thread.
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
await new DailyNoteNotificationDialog(entry).ShowAsync();
|
||||
appDbContext.DailyNotes.UpdateAndSave(entry);
|
||||
using (await EnterCriticalExecutionAsync().ConfigureAwait(false))
|
||||
{
|
||||
// ContentDialog must be created by main thread.
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
await new DailyNoteNotificationDialog(entry).ShowAsync();
|
||||
appDbContext.DailyNotes.UpdateAndSave(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,16 @@ namespace Snap.Hutao.ViewModel;
|
||||
[Injection(InjectAs.Scoped)]
|
||||
internal class ExperimentalFeaturesViewModel : ObservableObject
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的实验性功能视图模型
|
||||
/// </summary>
|
||||
public ExperimentalFeaturesViewModel()
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
public ExperimentalFeaturesViewModel(IServiceProvider serviceProvider)
|
||||
{
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenCacheFolderCommand = new AsyncRelayCommand(OpenCacheFolderAsync);
|
||||
OpenDataFolderCommand = new AsyncRelayCommand(OpenDataFolderAsync);
|
||||
DeleteUsersCommand = new AsyncRelayCommand(DangerousDeleteUsersAsync);
|
||||
@@ -61,7 +66,7 @@ internal class ExperimentalFeaturesViewModel : ObservableObject
|
||||
|
||||
private async Task DangerousDeleteUsersAsync()
|
||||
{
|
||||
using (IServiceScope scope = Ioc.Default.CreateScope())
|
||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await appDbContext.Users.ExecuteDeleteAsync().ConfigureAwait(false);
|
||||
@@ -73,7 +78,7 @@ internal class ExperimentalFeaturesViewModel : ObservableObject
|
||||
|
||||
private void DangerousDeleteAllScheduleTasks()
|
||||
{
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
if (Core.ScheduleTaskHelper.UnregisterAllTasks())
|
||||
{
|
||||
infoBarService.Success(SH.ViewModelExperimentalDeleteTaskSuccess);
|
||||
|
||||
@@ -150,11 +150,8 @@ internal class GachaLogViewModel : Abstraction.ViewModel
|
||||
if (await gachaLogService.InitializeAsync(CancellationToken).ConfigureAwait(true))
|
||||
{
|
||||
ObservableCollection<GachaArchive> archives;
|
||||
|
||||
ThrowIfViewDisposed();
|
||||
using (await DisposeLock.EnterAsync().ConfigureAwait(false))
|
||||
using (await EnterCriticalExecutionAsync().ConfigureAwait(false))
|
||||
{
|
||||
ThrowIfViewDisposed();
|
||||
archives = await gachaLogService.GetArchiveCollectionAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -204,13 +201,13 @@ internal class GachaLogViewModel : Abstraction.ViewModel
|
||||
|
||||
try
|
||||
{
|
||||
using (await DisposeLock.EnterAsync().ConfigureAwait(false))
|
||||
using (await EnterCriticalExecutionAsync().ConfigureAwait(false))
|
||||
{
|
||||
try
|
||||
{
|
||||
authkeyValid = await gachaLogService.RefreshGachaLogAsync(query, strategy, progress, CancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (Core.ExceptionService.UserdataCorruptedException ex)
|
||||
catch (UserdataCorruptedException ex)
|
||||
{
|
||||
authkeyValid = false;
|
||||
infoBarService.Error(ex);
|
||||
@@ -304,11 +301,14 @@ internal class GachaLogViewModel : Abstraction.ViewModel
|
||||
|
||||
if (result == ContentDialogResult.Primary)
|
||||
{
|
||||
await gachaLogService.RemoveArchiveAsync(SelectedArchive).ConfigureAwait(false);
|
||||
using (await EnterCriticalExecutionAsync().ConfigureAwait(false))
|
||||
{
|
||||
await gachaLogService.RemoveArchiveAsync(SelectedArchive).ConfigureAwait(false);
|
||||
|
||||
// reselect first archive
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
SelectedArchive = Archives.FirstOrDefault();
|
||||
// reselect first archive
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
SelectedArchive = Archives.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -354,7 +354,7 @@ internal class GachaLogViewModel : Abstraction.ViewModel
|
||||
}
|
||||
catch (UserdataCorruptedException ex)
|
||||
{
|
||||
Ioc.Default.GetRequiredService<IInfoBarService>().Error(ex);
|
||||
infoBarService.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,15 +2,9 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.Service.Hutao;
|
||||
using Snap.Hutao.Web.Hutao.Model;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Graphics.Imaging;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Snap.Hutao.Control.Extension;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Core.LifeCycle;
|
||||
@@ -12,7 +13,6 @@ using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.Service.Game;
|
||||
using Snap.Hutao.Service.Game.Unlocker;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Snap.Hutao.Service.User;
|
||||
using Snap.Hutao.View.Dialog;
|
||||
@@ -36,6 +36,7 @@ internal class LaunchGameViewModel : Abstraction.ViewModel
|
||||
private static readonly string TrueString = true.ToString();
|
||||
private static readonly string FalseString = false.ToString();
|
||||
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly IGameService gameService;
|
||||
private readonly AppDbContext appDbContext;
|
||||
private readonly IMemoryCache memoryCache;
|
||||
@@ -56,17 +57,13 @@ internal class LaunchGameViewModel : Abstraction.ViewModel
|
||||
/// <summary>
|
||||
/// 构造一个新的启动游戏视图模型
|
||||
/// </summary>
|
||||
/// <param name="gameService">游戏服务</param>
|
||||
/// <param name="memoryCache">内存缓存</param>
|
||||
/// <param name="appDbContext">数据库上下文</param>
|
||||
public LaunchGameViewModel(
|
||||
IGameService gameService,
|
||||
IMemoryCache memoryCache,
|
||||
AppDbContext appDbContext)
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
public LaunchGameViewModel(IServiceProvider serviceProvider)
|
||||
{
|
||||
this.gameService = gameService;
|
||||
this.appDbContext = appDbContext;
|
||||
this.memoryCache = memoryCache;
|
||||
gameService = serviceProvider.GetRequiredService<IGameService>();
|
||||
appDbContext = serviceProvider.GetRequiredService<AppDbContext>();
|
||||
memoryCache = serviceProvider.GetRequiredService<IMemoryCache>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
LaunchCommand = new AsyncRelayCommand(LaunchAsync);
|
||||
@@ -210,11 +207,8 @@ internal class LaunchGameViewModel : Abstraction.ViewModel
|
||||
{
|
||||
try
|
||||
{
|
||||
ThrowIfViewDisposed();
|
||||
using (await DisposeLock.EnterAsync(CancellationToken).ConfigureAwait(true))
|
||||
using (await EnterCriticalExecutionAsync().ConfigureAwait(false))
|
||||
{
|
||||
ThrowIfViewDisposed();
|
||||
|
||||
MultiChannel multi = gameService.GetMultiChannel();
|
||||
if (string.IsNullOrEmpty(multi.ConfigFilePath))
|
||||
{
|
||||
@@ -222,7 +216,7 @@ internal class LaunchGameViewModel : Abstraction.ViewModel
|
||||
}
|
||||
else
|
||||
{
|
||||
Ioc.Default.GetRequiredService<IInfoBarService>().Warning(SH.ViewModelLaunchGameMultiChannelReadFail);
|
||||
serviceProvider.GetRequiredService<IInfoBarService>().Warning(SH.ViewModelLaunchGameMultiChannelReadFail);
|
||||
}
|
||||
|
||||
GameAccounts = await gameService.GetGameAccountCollectionAsync().ConfigureAwait(true);
|
||||
@@ -231,6 +225,7 @@ internal class LaunchGameViewModel : Abstraction.ViewModel
|
||||
if (memoryCache.TryGetValue(DesiredUid, out object? value) && value is string uid)
|
||||
{
|
||||
SelectedGameAccount = GameAccounts.FirstOrDefault(g => g.AttachUid == uid);
|
||||
memoryCache.Remove(DesiredUid);
|
||||
}
|
||||
|
||||
// Sync from Settings
|
||||
@@ -243,8 +238,8 @@ internal class LaunchGameViewModel : Abstraction.ViewModel
|
||||
}
|
||||
else
|
||||
{
|
||||
Ioc.Default.GetRequiredService<IInfoBarService>().Warning(SH.ViewModelLaunchGamePathInvalid);
|
||||
await Ioc.Default.GetRequiredService<INavigationService>()
|
||||
serviceProvider.GetRequiredService<IInfoBarService>().Warning(SH.ViewModelLaunchGamePathInvalid);
|
||||
await serviceProvider.GetRequiredService<INavigationService>()
|
||||
.NavigateAsync<View.Page.SettingPage>(INavigationAwaiter.Default, true)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
@@ -288,7 +283,7 @@ internal class LaunchGameViewModel : Abstraction.ViewModel
|
||||
|
||||
private async Task LaunchAsync()
|
||||
{
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
|
||||
if (gameService.IsGameRunning())
|
||||
{
|
||||
@@ -344,7 +339,7 @@ internal class LaunchGameViewModel : Abstraction.ViewModel
|
||||
}
|
||||
catch (Core.ExceptionService.UserdataCorruptedException ex)
|
||||
{
|
||||
Ioc.Default.GetRequiredService<IInfoBarService>().Error(ex);
|
||||
serviceProvider.GetRequiredService<IInfoBarService>().Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,8 +347,8 @@ internal class LaunchGameViewModel : Abstraction.ViewModel
|
||||
{
|
||||
if (gameAccount != null)
|
||||
{
|
||||
IUserService userService = Ioc.Default.GetRequiredService<IUserService>();
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
IUserService userService = serviceProvider.GetRequiredService<IUserService>();
|
||||
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
|
||||
if (userService.Current?.SelectedUserGameRole is UserGameRole role)
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Core.IO;
|
||||
using Snap.Hutao.Core.Setting;
|
||||
@@ -27,6 +28,7 @@ namespace Snap.Hutao.ViewModel;
|
||||
[Injection(InjectAs.Scoped)]
|
||||
internal class SettingViewModel : Abstraction.ViewModel
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly AppDbContext appDbContext;
|
||||
private readonly IGameService gameService;
|
||||
private readonly ILogger<SettingViewModel> logger;
|
||||
@@ -46,21 +48,14 @@ internal class SettingViewModel : Abstraction.ViewModel
|
||||
/// <summary>
|
||||
/// 构造一个新的设置视图模型
|
||||
/// </summary>
|
||||
/// <param name="appDbContext">数据库上下文</param>
|
||||
/// <param name="gameService">游戏服务</param>
|
||||
/// <param name="experimental">实验性功能</param>
|
||||
/// <param name="logger">日志器</param>
|
||||
public SettingViewModel(
|
||||
AppDbContext appDbContext,
|
||||
IGameService gameService,
|
||||
ExperimentalFeaturesViewModel experimental,
|
||||
ILogger<SettingViewModel> logger)
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
public SettingViewModel(IServiceProvider serviceProvider)
|
||||
{
|
||||
this.appDbContext = appDbContext;
|
||||
this.gameService = gameService;
|
||||
this.logger = logger;
|
||||
|
||||
Experimental = experimental;
|
||||
appDbContext = serviceProvider.GetRequiredService<AppDbContext>();
|
||||
gameService = serviceProvider.GetRequiredService<IGameService>();
|
||||
logger = serviceProvider.GetRequiredService<ILogger<SettingViewModel>>();
|
||||
Experimental = serviceProvider.GetRequiredService<ExperimentalFeaturesViewModel>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
isEmptyHistoryWishVisibleEntry = appDbContext.Settings.SingleOrAdd(SettingEntry.IsEmptyHistoryWishVisible, SettingEntryHelper.TrueString);
|
||||
IsEmptyHistoryWishVisible = bool.Parse(isEmptyHistoryWishVisibleEntry.Value!);
|
||||
@@ -152,7 +147,7 @@ internal class SettingViewModel : Abstraction.ViewModel
|
||||
{
|
||||
selectedBackdropTypeEntry.Value = value.Value.ToString();
|
||||
appDbContext.Settings.UpdateAndSave(selectedBackdropTypeEntry);
|
||||
Ioc.Default.GetRequiredService<IMessenger>().Send(new Message.BackdropTypeChangedMessage(value.Value));
|
||||
serviceProvider.GetRequiredService<IMessenger>().Send(new Message.BackdropTypeChangedMessage(value.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,7 +184,7 @@ internal class SettingViewModel : Abstraction.ViewModel
|
||||
|
||||
private async Task SetGamePathAsync()
|
||||
{
|
||||
IGameLocator locator = Ioc.Default.GetRequiredService<IEnumerable<IGameLocator>>()
|
||||
IGameLocator locator = serviceProvider.GetRequiredService<IEnumerable<IGameLocator>>()
|
||||
.Single(l => l.Name == nameof(ManualGameLocator));
|
||||
|
||||
(bool isOk, string path) = await locator.LocateGamePathAsync().ConfigureAwait(false);
|
||||
@@ -203,7 +198,7 @@ internal class SettingViewModel : Abstraction.ViewModel
|
||||
|
||||
private void DeleteGameWebCache()
|
||||
{
|
||||
IGameService gameService = Ioc.Default.GetRequiredService<IGameService>();
|
||||
IGameService gameService = serviceProvider.GetRequiredService<IGameService>();
|
||||
string gamePath = gameService.GetGamePathSkipLocator();
|
||||
|
||||
if (!string.IsNullOrEmpty(gamePath))
|
||||
@@ -211,7 +206,7 @@ internal class SettingViewModel : Abstraction.ViewModel
|
||||
string cacheFilePath = GachaLogQueryWebCacheProvider.GetCacheFile(gamePath);
|
||||
string cacheFolder = Path.GetDirectoryName(cacheFilePath)!;
|
||||
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
if (Directory.Exists(cacheFolder))
|
||||
{
|
||||
try
|
||||
@@ -243,7 +238,7 @@ internal class SettingViewModel : Abstraction.ViewModel
|
||||
private async Task CheckUpdateAsync()
|
||||
{
|
||||
#if DEBUG
|
||||
await Ioc.Default
|
||||
await serviceProvider
|
||||
.GetRequiredService<Service.Navigation.INavigationService>()
|
||||
.NavigateAsync<View.Page.TestPage>(Service.Navigation.INavigationAwaiter.Default)
|
||||
.ConfigureAwait(false);
|
||||
@@ -254,11 +249,11 @@ internal class SettingViewModel : Abstraction.ViewModel
|
||||
|
||||
private async Task SetDataFolderAsync()
|
||||
{
|
||||
IPickerFactory pickerFactory = Ioc.Default.GetRequiredService<IPickerFactory>();
|
||||
IPickerFactory pickerFactory = serviceProvider.GetRequiredService<IPickerFactory>();
|
||||
FolderPicker picker = pickerFactory.GetFolderPicker();
|
||||
(bool isOk, string folder) = await picker.TryPickSingleFolderAsync().ConfigureAwait(false);
|
||||
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
if (isOk)
|
||||
{
|
||||
LocalSetting.Set(SettingKeys.DataFolderPath, folder);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Snap.Hutao.Message;
|
||||
using Snap.Hutao.Model.Binding.SpiralAbyss;
|
||||
using Snap.Hutao.Model.Binding.User;
|
||||
@@ -25,6 +26,7 @@ namespace Snap.Hutao.ViewModel;
|
||||
[Injection(InjectAs.Scoped)]
|
||||
internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient<UserChangedMessage>
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly ISpiralAbyssRecordService spiralAbyssRecordService;
|
||||
private readonly IMetadataService metadataService;
|
||||
private readonly IUserService userService;
|
||||
@@ -37,25 +39,23 @@ internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient<Us
|
||||
/// <summary>
|
||||
/// 构造一个新的深渊记录视图模型
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
/// <param name="spiralAbyssRecordService">深渊记录服务</param>
|
||||
/// <param name="metadataService">元数据服务</param>
|
||||
/// <param name="userService">用户服务</param>
|
||||
/// <param name="messenger">消息器</param>
|
||||
public SpiralAbyssRecordViewModel(
|
||||
ISpiralAbyssRecordService spiralAbyssRecordService,
|
||||
IMetadataService metadataService,
|
||||
IUserService userService,
|
||||
IMessenger messenger)
|
||||
public SpiralAbyssRecordViewModel(IServiceProvider serviceProvider)
|
||||
{
|
||||
this.spiralAbyssRecordService = spiralAbyssRecordService;
|
||||
this.metadataService = metadataService;
|
||||
this.userService = userService;
|
||||
spiralAbyssRecordService = serviceProvider.GetRequiredService<ISpiralAbyssRecordService>();
|
||||
metadataService = serviceProvider.GetRequiredService<IMetadataService>();
|
||||
userService = serviceProvider.GetRequiredService<IUserService>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
RefreshCommand = new AsyncRelayCommand(RefreshAsync);
|
||||
UploadSpiralAbyssRecordCommand = new AsyncRelayCommand(UploadSpiralAbyssRecordAsync);
|
||||
|
||||
messenger.Register(this);
|
||||
serviceProvider.GetRequiredService<IMessenger>().Register(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -123,10 +123,12 @@ internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient<Us
|
||||
if (UserAndUid.TryFromUser(userService.Current, out UserAndUid? userAndUid))
|
||||
{
|
||||
await UpdateSpiralAbyssCollectionAsync(userAndUid).ConfigureAwait(false);
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
IsInitialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ioc.Default.GetRequiredService<IInfoBarService>().Warning(SH.MustSelectUserAndUid);
|
||||
serviceProvider.GetRequiredService<IInfoBarService>().Warning(SH.MustSelectUserAndUid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,10 +138,8 @@ internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient<Us
|
||||
ObservableCollection<SpiralAbyssEntry>? temp = null;
|
||||
try
|
||||
{
|
||||
ThrowIfViewDisposed();
|
||||
using (await DisposeLock.EnterAsync().ConfigureAwait(false))
|
||||
using (await EnterCriticalExecutionAsync().ConfigureAwait(false))
|
||||
{
|
||||
ThrowIfViewDisposed();
|
||||
temp = await spiralAbyssRecordService
|
||||
.GetSpiralAbyssCollectionAsync(userAndUid)
|
||||
.ConfigureAwait(false);
|
||||
@@ -156,16 +156,14 @@ internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient<Us
|
||||
|
||||
private async Task RefreshAsync()
|
||||
{
|
||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||
if (SpiralAbyssEntries != null)
|
||||
{
|
||||
if (UserAndUid.TryFromUser(userService.Current, out UserAndUid? userAndUid))
|
||||
{
|
||||
try
|
||||
{
|
||||
ThrowIfViewDisposed();
|
||||
using (await DisposeLock.EnterAsync().ConfigureAwait(false))
|
||||
using (await EnterCriticalExecutionAsync().ConfigureAwait(false))
|
||||
{
|
||||
ThrowIfViewDisposed();
|
||||
await spiralAbyssRecordService
|
||||
.RefreshSpiralAbyssAsync(userAndUid)
|
||||
.ConfigureAwait(false);
|
||||
@@ -176,15 +174,15 @@ internal class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecipient<Us
|
||||
}
|
||||
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
SelectedEntry = SpiralAbyssEntries?.FirstOrDefault();
|
||||
SelectedEntry = SpiralAbyssEntries.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UploadSpiralAbyssRecordAsync()
|
||||
{
|
||||
HomaClient homaClient = Ioc.Default.GetRequiredService<HomaClient>();
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
HomaClient homaClient = serviceProvider.GetRequiredService<HomaClient>();
|
||||
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
|
||||
if (UserAndUid.TryFromUser(userService.Current, out UserAndUid? userAndUid))
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Snap.Hutao.Core.IO;
|
||||
using Snap.Hutao.Core.IO.Bits;
|
||||
using Snap.Hutao.Service.User;
|
||||
@@ -18,11 +19,16 @@ namespace Snap.Hutao.ViewModel;
|
||||
[Injection(InjectAs.Scoped)]
|
||||
internal class TestViewModel : Abstraction.ViewModel
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的测试视图模型
|
||||
/// </summary>
|
||||
public TestViewModel()
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
public TestViewModel(IServiceProvider serviceProvider)
|
||||
{
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
ShowCommunityGameRecordDialogCommand = new AsyncRelayCommand(ShowCommunityGameRecordDialogAsync);
|
||||
ShowAdoptCalculatorDialogCommand = new AsyncRelayCommand(ShowAdoptCalculatorDialogAsync);
|
||||
DangerousLoginMihoyoBbsCommand = new AsyncRelayCommand(DangerousLoginMihoyoBbsAsync);
|
||||
@@ -71,7 +77,7 @@ internal class TestViewModel : Abstraction.ViewModel
|
||||
|
||||
if (isOk)
|
||||
{
|
||||
(Response<LoginResult>? resp, Aigis? aigis) = await Ioc.Default
|
||||
(Response<LoginResult>? resp, Aigis? aigis) = await serviceProvider
|
||||
.GetRequiredService<PassportClient2>()
|
||||
.LoginByPasswordAsync(data, CancellationToken.None)
|
||||
.ConfigureAwait(false);
|
||||
@@ -82,7 +88,7 @@ internal class TestViewModel : Abstraction.ViewModel
|
||||
{
|
||||
Cookie cookie = Cookie.FromLoginResult(resp.Data);
|
||||
|
||||
await Ioc.Default
|
||||
await serviceProvider
|
||||
.GetRequiredService<IUserService>()
|
||||
.ProcessInputCookieAsync(cookie)
|
||||
.ConfigureAwait(false);
|
||||
@@ -97,9 +103,9 @@ internal class TestViewModel : Abstraction.ViewModel
|
||||
|
||||
private async Task DownloadStaticFileAsync()
|
||||
{
|
||||
BitsManager bitsManager = Ioc.Default.GetRequiredService<BitsManager>();
|
||||
BitsManager bitsManager = serviceProvider.GetRequiredService<BitsManager>();
|
||||
Uri testUri = new(Web.HutaoEndpoints.StaticZip("AvatarIcon"));
|
||||
ILogger<TestViewModel> logger = Ioc.Default.GetRequiredService<ILogger<TestViewModel>>();
|
||||
ILogger<TestViewModel> logger = serviceProvider.GetRequiredService<ILogger<TestViewModel>>();
|
||||
Progress<ProgressUpdateStatus> progress = new(status => logger.LogInformation("{info}", status));
|
||||
(bool isOk, TempFile file) = await bitsManager.DownloadAsync(testUri, progress).ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Core.IO.DataTransfer;
|
||||
using Snap.Hutao.Extension;
|
||||
@@ -24,6 +25,7 @@ namespace Snap.Hutao.ViewModel;
|
||||
[Injection(InjectAs.Singleton)]
|
||||
internal class UserViewModel : ObservableObject
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly IUserService userService;
|
||||
private readonly IInfoBarService infoBarService;
|
||||
|
||||
@@ -33,12 +35,14 @@ internal class UserViewModel : ObservableObject
|
||||
/// <summary>
|
||||
/// 构造一个新的用户视图模型
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
/// <param name="userService">用户服务</param>
|
||||
/// <param name="infoBarService">信息条服务</param>
|
||||
public UserViewModel(IUserService userService, IInfoBarService infoBarService)
|
||||
public UserViewModel(IServiceProvider serviceProvider)
|
||||
{
|
||||
this.userService = userService;
|
||||
this.infoBarService = infoBarService;
|
||||
userService = serviceProvider.GetRequiredService<IUserService>();
|
||||
infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
AddUserCommand = new AsyncRelayCommand(AddUserAsync);
|
||||
@@ -155,7 +159,7 @@ internal class UserViewModel : ObservableObject
|
||||
{
|
||||
if (Core.WebView2Helper.IsSupported)
|
||||
{
|
||||
Ioc.Default.GetRequiredService<INavigationService>().Navigate<LoginMihoyoUserPage>(INavigationAwaiter.Default);
|
||||
serviceProvider.GetRequiredService<INavigationService>().Navigate<LoginMihoyoUserPage>(INavigationAwaiter.Default);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -207,15 +207,22 @@ internal class WelcomeViewModel : ObservableObject
|
||||
private void ExtractFiles(string file)
|
||||
{
|
||||
IImageCacheFilePathOperation imageCache = serviceProvider.GetRequiredService<IImageCache>().ImplictAs<IImageCacheFilePathOperation>()!;
|
||||
|
||||
using (ZipArchive archive = ZipFile.OpenRead(file))
|
||||
try
|
||||
{
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
using (ZipArchive archive = ZipFile.OpenRead(file))
|
||||
{
|
||||
string destPath = imageCache.GetFilePathFromCategoryAndFileName(fileName, entry.FullName);
|
||||
entry.ExtractToFile(destPath, true);
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
string destPath = imageCache.GetFilePathFromCategoryAndFileName(fileName, entry.FullName);
|
||||
entry.ExtractToFile(destPath, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidDataException)
|
||||
{
|
||||
// System.IO.InvalidDataException: End of Central Directory record could not be found.
|
||||
// Basically the file downloaded is corrupted, skip anyway.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.WinUI.UI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Model.Binding.Cultivation;
|
||||
@@ -34,6 +35,7 @@ namespace Snap.Hutao.ViewModel;
|
||||
[Injection(InjectAs.Scoped)]
|
||||
internal class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly IMetadataService metadataService;
|
||||
private readonly IHutaoCache hutaoCache;
|
||||
|
||||
@@ -44,12 +46,13 @@ internal class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
/// <summary>
|
||||
/// 构造一个新的角色资料视图模型
|
||||
/// </summary>
|
||||
/// <param name="metadataService">元数据服务</param>
|
||||
/// <param name="hutaoCache">胡桃缓存</param>
|
||||
public WikiAvatarViewModel(IMetadataService metadataService, IHutaoCache hutaoCache)
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
public WikiAvatarViewModel(IServiceProvider serviceProvider)
|
||||
{
|
||||
this.metadataService = metadataService;
|
||||
this.hutaoCache = hutaoCache;
|
||||
metadataService = serviceProvider.GetRequiredService<IMetadataService>();
|
||||
hutaoCache = serviceProvider.GetRequiredService<IHutaoCache>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
CultivateCommand = new AsyncRelayCommand<Avatar>(CultivateAsync);
|
||||
FilterCommand = new RelayCommand<string>(ApplyFilter);
|
||||
@@ -123,8 +126,8 @@ internal class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
{
|
||||
if (avatar != null)
|
||||
{
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
IUserService userService = Ioc.Default.GetRequiredService<IUserService>();
|
||||
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
IUserService userService = serviceProvider.GetRequiredService<IUserService>();
|
||||
|
||||
if (userService.Current != null)
|
||||
{
|
||||
@@ -136,7 +139,7 @@ internal class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
|
||||
if (isOk)
|
||||
{
|
||||
Response<CalcConsumption> consumptionResponse = await Ioc.Default
|
||||
Response<CalcConsumption> consumptionResponse = await serviceProvider
|
||||
.GetRequiredService<CalcClient>()
|
||||
.ComputeAsync(userService.Current.Entity, delta)
|
||||
.ConfigureAwait(false);
|
||||
@@ -146,18 +149,25 @@ internal class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
CalcConsumption consumption = consumptionResponse.Data;
|
||||
|
||||
List<CalcItem> items = CalcItemHelper.Merge(consumption.AvatarConsume, consumption.AvatarSkillConsume);
|
||||
bool saved = await Ioc.Default
|
||||
.GetRequiredService<ICultivationService>()
|
||||
.SaveConsumptionAsync(CultivateType.AvatarAndSkill, avatar.Id, items)
|
||||
.ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
bool saved = await serviceProvider
|
||||
.GetRequiredService<ICultivationService>()
|
||||
.SaveConsumptionAsync(CultivateType.AvatarAndSkill, avatar.Id, items)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (saved)
|
||||
{
|
||||
infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
|
||||
if (saved)
|
||||
{
|
||||
infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Core.ExceptionService.UserdataCorruptedException ex)
|
||||
{
|
||||
infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
|
||||
infoBarService.Error(ex, SH.ViewModelCultivationAddWarning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.WinUI.UI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Model.Binding.Cultivation;
|
||||
@@ -37,6 +38,7 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
11419, 11420, 11421, // 「一心传」名刀
|
||||
};
|
||||
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly IMetadataService metadataService;
|
||||
private readonly IHutaoCache hutaoCache;
|
||||
|
||||
@@ -47,12 +49,12 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
/// <summary>
|
||||
/// 构造一个新的武器资料视图模型
|
||||
/// </summary>
|
||||
/// <param name="metadataService">元数据服务</param>
|
||||
/// <param name="hutaoCache">胡桃缓存</param>
|
||||
public WikiWeaponViewModel(IMetadataService metadataService, IHutaoCache hutaoCache)
|
||||
/// <param name="serviceProvider">服务提供器</param>
|
||||
public WikiWeaponViewModel(IServiceProvider serviceProvider)
|
||||
{
|
||||
this.metadataService = metadataService;
|
||||
this.hutaoCache = hutaoCache;
|
||||
metadataService = serviceProvider.GetRequiredService<IMetadataService>();
|
||||
hutaoCache = serviceProvider.GetRequiredService<IHutaoCache>();
|
||||
this.serviceProvider = serviceProvider;
|
||||
|
||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
||||
CultivateCommand = new AsyncRelayCommand<Weapon>(CultivateAsync);
|
||||
@@ -122,8 +124,8 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
{
|
||||
if (weapon != null)
|
||||
{
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
IUserService userService = Ioc.Default.GetRequiredService<IUserService>();
|
||||
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
IUserService userService = serviceProvider.GetRequiredService<IUserService>();
|
||||
|
||||
if (userService.Current != null)
|
||||
{
|
||||
@@ -135,7 +137,7 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
|
||||
if (isOk)
|
||||
{
|
||||
Response<CalcConsumption> consumptionResponse = await Ioc.Default
|
||||
Response<CalcConsumption> consumptionResponse = await serviceProvider
|
||||
.GetRequiredService<CalcClient>()
|
||||
.ComputeAsync(userService.Current.Entity, delta)
|
||||
.ConfigureAwait(false);
|
||||
@@ -144,18 +146,25 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
||||
{
|
||||
CalcConsumption consumption = consumptionResponse.Data;
|
||||
|
||||
bool saved = await Ioc.Default
|
||||
.GetRequiredService<ICultivationService>()
|
||||
.SaveConsumptionAsync(CultivateType.Weapon, weapon.Id, consumption.WeaponConsume.EmptyIfNull())
|
||||
.ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
bool saved = await serviceProvider
|
||||
.GetRequiredService<ICultivationService>()
|
||||
.SaveConsumptionAsync(CultivateType.Weapon, weapon.Id, consumption.WeaponConsume.EmptyIfNull())
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (saved)
|
||||
{
|
||||
infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
|
||||
if (saved)
|
||||
{
|
||||
infoBarService.Success(SH.ViewModelCultivationEntryAddSuccess);
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Core.ExceptionService.UserdataCorruptedException ex)
|
||||
{
|
||||
infoBarService.Warning(SH.ViewModelCultivationEntryAddWarning);
|
||||
infoBarService.Error(ex, SH.ViewModelCultivationAddWarning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
using Snap.Hutao.Web.Request;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using Snap.Hutao.Extension;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
Reference in New Issue
Block a user