This commit is contained in:
DismissedLight
2022-10-06 11:29:07 +08:00
parent 009feced08
commit b545c0d09b
15 changed files with 85 additions and 47 deletions

View File

@@ -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]
#### 命名样式 ####

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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()

View File

@@ -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));
}
}
}

View File

@@ -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;

View File

@@ -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>

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -13,6 +13,11 @@ public enum RefreshResult
/// </summary>
Ok,
/// <summary>
/// 元数据加载失败
/// </summary>
MetadataUninitialized,
/// <summary>
/// API 不可用
/// </summary>

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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;

View File

@@ -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

View File

@@ -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