mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
fix #88
This commit is contained in:
@@ -159,6 +159,7 @@ dotnet_diagnostic.CA1805.severity = suggestion
|
||||
|
||||
# VSTHRD111: Use ConfigureAwait(bool)
|
||||
dotnet_diagnostic.VSTHRD111.severity = suggestion
|
||||
csharp_style_prefer_top_level_statements = true:silent
|
||||
|
||||
[*.vb]
|
||||
#### 命名样式 ####
|
||||
|
||||
@@ -139,7 +139,7 @@ public abstract class CacheBase<T>
|
||||
|
||||
IStorageItem? item = await folder.TryGetItemAsync(fileName).AsTask().ConfigureAwait(false);
|
||||
|
||||
if (item == null)
|
||||
if (item == null || (await item.GetBasicPropertiesAsync()).Size == 0)
|
||||
{
|
||||
StorageFile baseFile = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting).AsTask().ConfigureAwait(false);
|
||||
await DownloadFileAsync(uri, baseFile).ConfigureAwait(false);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using System.IO;
|
||||
|
||||
namespace Snap.Hutao.Core.Exception;
|
||||
|
||||
@@ -24,24 +25,33 @@ internal class ExceptionRecorder
|
||||
|
||||
application.UnhandledException += OnAppUnhandledException;
|
||||
application.DebugSettings.BindingFailed += OnXamlBindingFailed;
|
||||
AppDomain.CurrentDomain.UnhandledException += OnCurrentDomainUnhandledException;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当应用程序未经处理的异常引发时调用
|
||||
/// </summary>
|
||||
/// <param name="sender">实例</param>
|
||||
/// <param name="e">事件参数</param>
|
||||
public void OnAppUnhandledException(object? sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
|
||||
private void OnCurrentDomainUnhandledException(object sender, System.UnhandledExceptionEventArgs e)
|
||||
{
|
||||
logger.LogError(EventIds.UnhandledException, e.Exception, "未经处理的异常: [HResult:{code}]", e.Exception.HResult);
|
||||
logger.LogError(EventIds.UnhandledException, e.ExceptionObject as System.Exception, "未经处理的异常");
|
||||
|
||||
foreach (ILoggerProvider provider in Ioc.Default.GetRequiredService<IEnumerable<ILoggerProvider>>())
|
||||
{
|
||||
provider.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Xaml 绑定失败时触发
|
||||
/// </summary>
|
||||
/// <param name="sender">实例</param>
|
||||
/// <param name="e">事件参数</param>
|
||||
public void OnXamlBindingFailed(object? sender, BindingFailedEventArgs e)
|
||||
private void OnAppUnhandledException(object? sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
|
||||
{
|
||||
logger.LogError(EventIds.UnhandledException, e.Exception, "未经处理的异常");
|
||||
|
||||
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
File.WriteAllText(Path.Combine(path, "Excpetion.txt"), e.Exception?.ToString());
|
||||
|
||||
foreach (ILoggerProvider provider in Ioc.Default.GetRequiredService<IEnumerable<ILoggerProvider>>())
|
||||
{
|
||||
provider.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnXamlBindingFailed(object? sender, BindingFailedEventArgs e)
|
||||
{
|
||||
logger.LogCritical(EventIds.XamlBindingError, "XAML绑定失败: {message}", e.Message);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ public sealed class LogEntryQueue : IDisposable
|
||||
private readonly TaskCompletionSource writeDbCompletionSource = new();
|
||||
private readonly LogDbContext logDbContext;
|
||||
|
||||
private bool disposed;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的日志队列
|
||||
/// </summary>
|
||||
@@ -27,7 +29,7 @@ public sealed class LogEntryQueue : IDisposable
|
||||
{
|
||||
logDbContext = InitializeDbContext();
|
||||
|
||||
Task.Run(async () => await WritePendingLogsAsync(disposeTokenSource.Token)).SafeForget();
|
||||
Task.Run(() => WritePendingLogsAsync(disposeTokenSource.Token)).SafeForget();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -43,6 +45,11 @@ public sealed class LogEntryQueue : IDisposable
|
||||
[SuppressMessage("", "VSTHRD002")]
|
||||
public void Dispose()
|
||||
{
|
||||
if (disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// notify the write task to complete.
|
||||
disposeTokenSource.Cancel();
|
||||
|
||||
@@ -50,6 +57,7 @@ public sealed class LogEntryQueue : IDisposable
|
||||
writeDbCompletionSource.Task.GetAwaiter().GetResult();
|
||||
|
||||
logDbContext.Dispose();
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
private static LogDbContext InitializeDbContext()
|
||||
|
||||
@@ -93,7 +93,7 @@ internal class AsyncRelayCommandFactory : IAsyncRelayCommandFactory
|
||||
if (asyncRelayCommand.ExecutionTask?.Exception is AggregateException exception)
|
||||
{
|
||||
Exception baseException = exception.GetBaseException();
|
||||
logger.LogError(EventIds.AsyncCommandException, baseException, "{name} Exception", nameof(asyncRelayCommand));
|
||||
logger.LogError(EventIds.AsyncCommandException, baseException, "{name} Exception", nameof(AsyncRelayCommand));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,11 @@ public class SkillDepot
|
||||
{
|
||||
foreach (ProudableSkill skill in Skills)
|
||||
{
|
||||
yield return skill;
|
||||
// skip skills like Mona's & Ayaka's shift
|
||||
if (skill.Proud.Parameters.Count > 1)
|
||||
{
|
||||
yield return skill;
|
||||
}
|
||||
}
|
||||
|
||||
yield return EnergySkill;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Identity
|
||||
Name="7f0db578-026f-4e0b-a75b-d5d06bb0a74d"
|
||||
Publisher="CN=DGP Studio"
|
||||
Version="1.1.5.0" />
|
||||
Version="1.1.6.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>胡桃</DisplayName>
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Snap.Hutao;
|
||||
/// <summary>
|
||||
/// Program class
|
||||
/// </summary>
|
||||
public static class Program
|
||||
public static partial class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// 主线程队列
|
||||
@@ -62,8 +62,8 @@ public static class Program
|
||||
|
||||
// Microsoft extension
|
||||
.AddLogging(builder => builder
|
||||
.AddDatabase()
|
||||
.AddDebug())
|
||||
.AddDebug()
|
||||
.AddDatabase())
|
||||
.AddMemoryCache()
|
||||
|
||||
// Hutao extensions
|
||||
|
||||
@@ -5,6 +5,7 @@ using Snap.Hutao.Context.Database;
|
||||
using Snap.Hutao.Core.Threading;
|
||||
using Snap.Hutao.Model.Binding.AvatarProperty;
|
||||
using Snap.Hutao.Service.AvatarInfo.Factory;
|
||||
using Snap.Hutao.Service.Metadata;
|
||||
using Snap.Hutao.Web.Enka;
|
||||
using Snap.Hutao.Web.Enka.Model;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
@@ -20,6 +21,7 @@ internal class AvatarInfoService : IAvatarInfoService
|
||||
private readonly AppDbContext appDbContext;
|
||||
private readonly ISummaryFactory summaryFactory;
|
||||
private readonly EnkaClient enkaClient;
|
||||
private readonly IMetadataService metadataService;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的角色信息服务
|
||||
@@ -27,9 +29,10 @@ internal class AvatarInfoService : IAvatarInfoService
|
||||
/// <param name="appDbContext">数据库上下文</param>
|
||||
/// <param name="summaryFactory">简述工厂</param>
|
||||
/// <param name="enkaClient">Enka客户端</param>
|
||||
public AvatarInfoService(AppDbContext appDbContext, ISummaryFactory summaryFactory, EnkaClient enkaClient)
|
||||
public AvatarInfoService(AppDbContext appDbContext, IMetadataService metadataService, ISummaryFactory summaryFactory, EnkaClient enkaClient)
|
||||
{
|
||||
this.appDbContext = appDbContext;
|
||||
this.metadataService = metadataService;
|
||||
this.summaryFactory = summaryFactory;
|
||||
this.enkaClient = enkaClient;
|
||||
}
|
||||
@@ -37,34 +40,41 @@ internal class AvatarInfoService : IAvatarInfoService
|
||||
/// <inheritdoc/>
|
||||
public async Task<ValueResult<RefreshResult, Summary?>> GetSummaryAsync(PlayerUid uid, RefreshOption refreshOption, CancellationToken token = default)
|
||||
{
|
||||
if (HasOption(refreshOption, RefreshOption.RequestFromAPI))
|
||||
if (await metadataService.InitializeAsync(token).ConfigureAwait(false))
|
||||
{
|
||||
EnkaResponse? resp = await GetEnkaResponseAsync(uid, token).ConfigureAwait(false);
|
||||
if (resp == null)
|
||||
if (HasOption(refreshOption, RefreshOption.RequestFromAPI))
|
||||
{
|
||||
return new(RefreshResult.APIUnavailable, null);
|
||||
}
|
||||
EnkaResponse? resp = await GetEnkaResponseAsync(uid, token).ConfigureAwait(false);
|
||||
if (resp == null)
|
||||
{
|
||||
return new(RefreshResult.APIUnavailable, null);
|
||||
}
|
||||
|
||||
if (resp.IsValid)
|
||||
{
|
||||
IList<Web.Enka.Model.AvatarInfo> list = HasOption(refreshOption, RefreshOption.StoreInDatabase)
|
||||
? UpdateDbAvatarInfo(uid.Value, resp.AvatarInfoList)
|
||||
: resp.AvatarInfoList;
|
||||
if (resp.IsValid)
|
||||
{
|
||||
IList<Web.Enka.Model.AvatarInfo> list = HasOption(refreshOption, RefreshOption.StoreInDatabase)
|
||||
? UpdateDbAvatarInfo(uid.Value, resp.AvatarInfoList)
|
||||
: resp.AvatarInfoList;
|
||||
|
||||
Summary summary = await summaryFactory.CreateAsync(resp.PlayerInfo, list).ConfigureAwait(false);
|
||||
return new(RefreshResult.Ok, summary);
|
||||
Summary summary = await summaryFactory.CreateAsync(resp.PlayerInfo, list).ConfigureAwait(false);
|
||||
return new(RefreshResult.Ok, summary);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new(RefreshResult.ShowcaseNotOpen, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new(RefreshResult.ShowcaseNotOpen, null);
|
||||
PlayerInfo info = PlayerInfo.CreateEmpty(uid.Value);
|
||||
|
||||
Summary summary = await summaryFactory.CreateAsync(info, GetDbAvatarInfos(uid.Value)).ConfigureAwait(false);
|
||||
return new(RefreshResult.Ok, summary);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayerInfo info = PlayerInfo.CreateEmpty(uid.Value);
|
||||
|
||||
Summary summary = await summaryFactory.CreateAsync(info, GetDbAvatarInfos(uid.Value)).ConfigureAwait(false);
|
||||
return new(RefreshResult.Ok, summary);
|
||||
return new(RefreshResult.MetadataUninitialized, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,11 @@ public enum RefreshResult
|
||||
/// </summary>
|
||||
Ok,
|
||||
|
||||
/// <summary>
|
||||
/// 元数据加载失败
|
||||
/// </summary>
|
||||
MetadataUninitialized,
|
||||
|
||||
/// <summary>
|
||||
/// API 不可用
|
||||
/// </summary>
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.UI.Behaviors" Version="7.1.2" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls" Version="7.1.2" />
|
||||
<!-- Prevent NewtownSoft.Json -->
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.9" />
|
||||
<!-- The PrivateAssets & IncludeAssets of Microsoft.EntityFrameworkCore.Tools should be remove to prevent multiple deps files-->
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.9" />
|
||||
|
||||
@@ -242,7 +242,7 @@
|
||||
<Border
|
||||
CornerRadius="{StaticResource CompatCornerRadius}"
|
||||
Background="#FFB29880"
|
||||
Padding="4,0"
|
||||
Padding="2,0"
|
||||
Width="40"
|
||||
Grid.Column="1"
|
||||
Margin="6,0,0,0"
|
||||
@@ -317,8 +317,8 @@
|
||||
Description="{Binding AffixDescription}">
|
||||
<shct:DescriptionTextBlock.Resources>
|
||||
<Style
|
||||
TargetType="TextBlock"
|
||||
BasedOn="{StaticResource BodyTextBlockStyle}">
|
||||
TargetType="TextBlock"
|
||||
BasedOn="{StaticResource BodyTextBlockStyle}">
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
</Style>
|
||||
</shct:DescriptionTextBlock.Resources>
|
||||
|
||||
@@ -16,11 +16,8 @@ using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.Service.GachaLog;
|
||||
using Snap.Hutao.View.Dialog;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
using Windows.Storage.Pickers.Provider;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ internal static class ApiEndpoints
|
||||
public const string UserGameRoles = $"{ApiTaKumiBindingApi}/getUserGameRolesByCookie?game_biz=hk4e_cn";
|
||||
|
||||
/// <summary>
|
||||
/// 用户游戏角色
|
||||
/// AuthKey
|
||||
/// </summary>
|
||||
public const string GenAuthKey = $"{ApiTaKumiBindingApi}/genAuthKey";
|
||||
#endregion
|
||||
|
||||
@@ -174,7 +174,9 @@ public partial class Cookie
|
||||
|
||||
if (uidCounter.Count > 0)
|
||||
{
|
||||
uid = uidCounter.MaxBy(kvp => kvp.Value).Key;
|
||||
// fix #88 自带页面登录米游社,提示登录失败
|
||||
string key = uidCounter.MaxBy(kvp => kvp.Value).Key;
|
||||
uid = inner[key];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user