mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
bulk refactor
This commit is contained in:
@@ -140,6 +140,8 @@ internal sealed class AttributeGenerator : IIncrementalGenerator
|
|||||||
public InjectionAttribute(InjectAs injectAs, Type interfaceType)
|
public InjectionAttribute(InjectAs injectAs, Type interfaceType)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object Key { get; set; }
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
context.AddSource("Snap.Hutao.Core.DependencyInjection.Annotation.Attributes.g.cs", coreDependencyInjectionAnnotations);
|
context.AddSource("Snap.Hutao.Core.DependencyInjection.Annotation.Attributes.g.cs", coreDependencyInjectionAnnotations);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
using Snap.Hutao.SourceGeneration.Primitive;
|
using Snap.Hutao.SourceGeneration.Primitive;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -68,7 +69,7 @@ internal sealed class DependencyPropertyGenerator : IIncrementalGenerator
|
|||||||
|
|
||||||
string propertyName = (string)arguments[0].Value!;
|
string propertyName = (string)arguments[0].Value!;
|
||||||
string propertyType = arguments[1].Value!.ToString();
|
string propertyType = arguments[1].Value!.ToString();
|
||||||
string defaultValue = GetLiteralString(arguments.ElementAtOrDefault(2)) ?? "default";
|
string defaultValue = arguments.ElementAtOrDefault(2).ToCSharpString() ?? "default";
|
||||||
string propertyChangedCallback = arguments.ElementAtOrDefault(3) is { IsNull: false } arg3 ? $", {arg3.Value}" : string.Empty;
|
string propertyChangedCallback = arguments.ElementAtOrDefault(3) is { IsNull: false } arg3 ? $", {arg3.Value}" : string.Empty;
|
||||||
|
|
||||||
string code;
|
string code;
|
||||||
@@ -125,25 +126,4 @@ internal sealed class DependencyPropertyGenerator : IIncrementalGenerator
|
|||||||
production.AddSource($"{normalizedClassName}.{propertyName}.g.cs", code);
|
production.AddSource($"{normalizedClassName}.{propertyName}.g.cs", code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string? GetLiteralString(TypedConstant typedConstant)
|
|
||||||
{
|
|
||||||
if (typedConstant.IsNull)
|
|
||||||
{
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typedConstant.Value is bool boolValue)
|
|
||||||
{
|
|
||||||
return boolValue ? "true" : "false";
|
|
||||||
}
|
|
||||||
|
|
||||||
string result = typedConstant.Value!.ToString();
|
|
||||||
if (string.IsNullOrEmpty(result))
|
|
||||||
{
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -92,17 +92,29 @@ internal sealed class InjectionGenerator : IIncrementalGenerator
|
|||||||
ImmutableArray<TypedConstant> arguments = injectionInfo.ConstructorArguments;
|
ImmutableArray<TypedConstant> arguments = injectionInfo.ConstructorArguments;
|
||||||
|
|
||||||
string injectAsName = arguments[0].ToCSharpString();
|
string injectAsName = arguments[0].ToCSharpString();
|
||||||
switch (injectAsName)
|
|
||||||
|
bool hasKey = injectionInfo.TryGetNamedArgumentValue("Key", out TypedConstant key);
|
||||||
|
|
||||||
|
switch (injectAsName, hasKey)
|
||||||
{
|
{
|
||||||
case InjectAsSingletonName:
|
case (InjectAsSingletonName, false):
|
||||||
lineBuilder.Append(" services.AddSingleton<");
|
lineBuilder.Append(" services.AddSingleton<");
|
||||||
break;
|
break;
|
||||||
case InjectAsTransientName:
|
case (InjectAsSingletonName, true):
|
||||||
|
lineBuilder.Append(" services.AddKeyedSingleton<");
|
||||||
|
break;
|
||||||
|
case (InjectAsTransientName, false):
|
||||||
lineBuilder.Append(" services.AddTransient<");
|
lineBuilder.Append(" services.AddTransient<");
|
||||||
break;
|
break;
|
||||||
case InjectAsScopedName:
|
case (InjectAsTransientName, true):
|
||||||
|
lineBuilder.Append(" services.AddKeyedTransient<");
|
||||||
|
break;
|
||||||
|
case (InjectAsScopedName, false):
|
||||||
lineBuilder.Append(" services.AddScoped<");
|
lineBuilder.Append(" services.AddScoped<");
|
||||||
break;
|
break;
|
||||||
|
case (InjectAsScopedName, true):
|
||||||
|
lineBuilder.Append(" services.AddKeyedScoped<");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
production.ReportDiagnostic(Diagnostic.Create(invalidInjectionDescriptor, context.Context.Node.GetLocation(), injectAsName));
|
production.ReportDiagnostic(Diagnostic.Create(invalidInjectionDescriptor, context.Context.Node.GetLocation(), injectAsName));
|
||||||
break;
|
break;
|
||||||
@@ -113,7 +125,14 @@ internal sealed class InjectionGenerator : IIncrementalGenerator
|
|||||||
lineBuilder.Append($"{arguments[1].Value}, ");
|
lineBuilder.Append($"{arguments[1].Value}, ");
|
||||||
}
|
}
|
||||||
|
|
||||||
lineBuilder.Append($"{context.Symbol.ToDisplayString()}>();");
|
if (hasKey)
|
||||||
|
{
|
||||||
|
lineBuilder.Append($"{context.Symbol.ToDisplayString()}>({key.ToCSharpString()});");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lineBuilder.Append($"{context.Symbol.ToDisplayString()}>();");
|
||||||
|
}
|
||||||
|
|
||||||
lines.Add(lineBuilder.ToString());
|
lines.Add(lineBuilder.ToString());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Snap.Hutao.SourceGeneration.Primitive;
|
namespace Snap.Hutao.SourceGeneration.Primitive;
|
||||||
@@ -13,4 +14,19 @@ internal static class AttributeDataExtension
|
|||||||
{
|
{
|
||||||
return data.NamedArguments.Any(a => a.Key == key && predicate((TValue)a.Value.Value!));
|
return data.NamedArguments.Any(a => a.Key == key && predicate((TValue)a.Value.Value!));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool TryGetNamedArgumentValue(this AttributeData data, string key, out TypedConstant value)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string, TypedConstant> pair in data.NamedArguments)
|
||||||
|
{
|
||||||
|
if (pair.Key == key)
|
||||||
|
{
|
||||||
|
value = pair.Value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
<Platforms>x64</Platforms>
|
<Platforms>x64</Platforms>
|
||||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ namespace Snap.Hutao.Test;
|
|||||||
[TestClass]
|
[TestClass]
|
||||||
public class JsonSerializeTest
|
public class JsonSerializeTest
|
||||||
{
|
{
|
||||||
|
private TestContext? testContext;
|
||||||
|
|
||||||
|
public TestContext? TestContext { get => testContext; set => testContext = value; }
|
||||||
|
|
||||||
private readonly JsonSerializerOptions AlowStringNumberOptions = new()
|
private readonly JsonSerializerOptions AlowStringNumberOptions = new()
|
||||||
{
|
{
|
||||||
NumberHandling = JsonNumberHandling.AllowReadingFromString,
|
NumberHandling = JsonNumberHandling.AllowReadingFromString,
|
||||||
@@ -53,6 +57,27 @@ public class JsonSerializeTest
|
|||||||
Assert.AreEqual(sample[111], "12");
|
Assert.AreEqual(sample[111], "12");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ByteArraySerializeAsBase64()
|
||||||
|
{
|
||||||
|
byte[] array =
|
||||||
|
#if NET8_0_OR_GREATER
|
||||||
|
[1, 2, 3, 4, 5];
|
||||||
|
#else
|
||||||
|
{ 1, 2, 3, 4, 5 };
|
||||||
|
#endif
|
||||||
|
ByteArraySample sample = new()
|
||||||
|
{
|
||||||
|
Array = array,
|
||||||
|
};
|
||||||
|
|
||||||
|
string result = JsonSerializer.Serialize(sample);
|
||||||
|
TestContext!.WriteLine($"ByteArray Serialize Result: {result}");
|
||||||
|
Assert.AreEqual(result, """
|
||||||
|
{"Array":"AQIDBAU="}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
private sealed class Sample
|
private sealed class Sample
|
||||||
{
|
{
|
||||||
public int A { get => B; set => B = value; }
|
public int A { get => B; set => B = value; }
|
||||||
@@ -64,4 +89,9 @@ public class JsonSerializeTest
|
|||||||
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
|
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
|
||||||
public int A { get; set; }
|
public int A { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed class ByteArraySample
|
||||||
|
{
|
||||||
|
public byte[]? Array { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,8 +9,12 @@ public sealed class ForEachRuntimeBehaviorTest
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void ListOfStringCanEnumerateAsReadOnlySpanOfChar()
|
public void ListOfStringCanEnumerateAsReadOnlySpanOfChar()
|
||||||
{
|
{
|
||||||
List<string> strings = ["a", "b", "c"];
|
List<string> strings =
|
||||||
|
#if NET8_0_OR_GREATER
|
||||||
|
["a", "b", "c"];
|
||||||
|
#else
|
||||||
|
new() { "a", "b", "c" };
|
||||||
|
#endif
|
||||||
int count = 0;
|
int count = 0;
|
||||||
foreach (ReadOnlySpan<char> chars in strings)
|
foreach (ReadOnlySpan<char> chars in strings)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,8 +8,13 @@ public sealed class RangeRuntimeBehaviorTest
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void RangeTrimLastOne()
|
public void RangeTrimLastOne()
|
||||||
{
|
{
|
||||||
|
#if NET8_0_OR_GREATER
|
||||||
int[] array = [1, 2, 3, 4];
|
int[] array = [1, 2, 3, 4];
|
||||||
int[] test = [1, 2, 3];
|
int[] test = [1, 2, 3];
|
||||||
|
#else
|
||||||
|
int[] array = { 1, 2, 3, 4 };
|
||||||
|
int[] test = { 1, 2, 3 };
|
||||||
|
#endif
|
||||||
int[] result = array[..^1];
|
int[] result = array[..^1];
|
||||||
Assert.AreEqual(3, result.Length);
|
Assert.AreEqual(3, result.Length);
|
||||||
Assert.IsTrue(MemoryExtensions.SequenceEqual<int>(test, result));
|
Assert.IsTrue(MemoryExtensions.SequenceEqual<int>(test, result));
|
||||||
|
|||||||
@@ -6,7 +6,12 @@ public sealed class UnsafeRuntimeBehaviorTest
|
|||||||
[TestMethod]
|
[TestMethod]
|
||||||
public unsafe void UInt32AllSetIs()
|
public unsafe void UInt32AllSetIs()
|
||||||
{
|
{
|
||||||
byte[] bytes = [0xFF, 0xFF, 0xFF, 0xFF,];
|
byte[] bytes =
|
||||||
|
#if NET8_0_OR_GREATER
|
||||||
|
[0xFF, 0xFF, 0xFF, 0xFF];
|
||||||
|
#else
|
||||||
|
{ 0xFF, 0xFF, 0xFF, 0xFF, };
|
||||||
|
#endif
|
||||||
|
|
||||||
fixed (byte* pBytes = bytes)
|
fixed (byte* pBytes = bytes)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||||
<ImplicitUsings>disable</ImplicitUsings>
|
<ImplicitUsings>disable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ internal static class DependencyInjection
|
|||||||
|
|
||||||
// Discrete services
|
// Discrete services
|
||||||
.AddSingleton<IMessenger, WeakReferenceMessenger>()
|
.AddSingleton<IMessenger, WeakReferenceMessenger>()
|
||||||
|
|
||||||
.BuildServiceProvider(true);
|
.BuildServiceProvider(true);
|
||||||
|
|
||||||
Ioc.Default.ConfigureServices(serviceProvider);
|
Ioc.Default.ConfigureServices(serviceProvider);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ internal sealed partial class GameChannelOptionsService : IGameChannelOptionsSer
|
|||||||
{
|
{
|
||||||
using (FileStream readStream = File.OpenRead(configPath))
|
using (FileStream readStream = File.OpenRead(configPath))
|
||||||
{
|
{
|
||||||
elements = IniSerializer.Deserialize(readStream).ToList();
|
elements = [.. IniSerializer.Deserialize(readStream)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException ex)
|
catch (FileNotFoundException ex)
|
||||||
|
|||||||
@@ -165,11 +165,11 @@ internal sealed class LaunchOptions : DbStoreOptions
|
|||||||
set => SetOption(ref isMonitorEnabled, SettingEntry.LaunchIsMonitorEnabled, value);
|
set => SetOption(ref isMonitorEnabled, SettingEntry.LaunchIsMonitorEnabled, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AspectRatio> AspectRatios { get; } = new()
|
public List<AspectRatio> AspectRatios { get; } =
|
||||||
{
|
[
|
||||||
new(2560, 1440),
|
new(2560, 1440),
|
||||||
new(1920, 1080),
|
new(1920, 1080),
|
||||||
};
|
];
|
||||||
|
|
||||||
public AspectRatio? SelectedAspectRatio
|
public AspectRatio? SelectedAspectRatio
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -178,11 +178,11 @@ internal sealed partial class PackageConverter
|
|||||||
|
|
||||||
private async ValueTask<Dictionary<string, VersionItem>> GetVersionItemsAsync(Stream stream)
|
private async ValueTask<Dictionary<string, VersionItem>> GetVersionItemsAsync(Stream stream)
|
||||||
{
|
{
|
||||||
Dictionary<string, VersionItem> results = new();
|
Dictionary<string, VersionItem> results = [];
|
||||||
using (StreamReader reader = new(stream))
|
using (StreamReader reader = new(stream))
|
||||||
{
|
{
|
||||||
Regex dataFolderRegex = DataFolderRegex();
|
Regex dataFolderRegex = DataFolderRegex();
|
||||||
while (await reader.ReadLineAsync().ConfigureAwait(false) is { } row && !string.IsNullOrEmpty(row))
|
while (await reader.ReadLineAsync().ConfigureAwait(false) is { Length: > 0 } row)
|
||||||
{
|
{
|
||||||
VersionItem? item = JsonSerializer.Deserialize<VersionItem>(row, options);
|
VersionItem? item = JsonSerializer.Deserialize<VersionItem>(row, options);
|
||||||
ArgumentNullException.ThrowIfNull(item);
|
ArgumentNullException.ThrowIfNull(item);
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ internal sealed partial class GameProcessService : IGameProcessService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return System.Diagnostics.Process.GetProcessesByName(YuanShenProcessName).Any()
|
return System.Diagnostics.Process.GetProcessesByName(YuanShenProcessName).Length > 0
|
||||||
|| System.Diagnostics.Process.GetProcessesByName(GenshinImpactProcessName).Any();
|
|| System.Diagnostics.Process.GetProcessesByName(GenshinImpactProcessName).Length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask LaunchAsync(IProgress<LaunchStatus> progress)
|
public async ValueTask LaunchAsync(IProgress<LaunchStatus> progress)
|
||||||
@@ -126,7 +126,9 @@ internal sealed partial class GameProcessService : IGameProcessService
|
|||||||
|
|
||||||
private ValueTask UnlockFpsAsync(System.Diagnostics.Process game, IProgress<LaunchStatus> progress, CancellationToken token = default)
|
private ValueTask UnlockFpsAsync(System.Diagnostics.Process game, IProgress<LaunchStatus> progress, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
|
#pragma warning disable CA1859
|
||||||
IGameFpsUnlocker unlocker = serviceProvider.CreateInstance<GameFpsUnlocker>(game);
|
IGameFpsUnlocker unlocker = serviceProvider.CreateInstance<GameFpsUnlocker>(game);
|
||||||
|
#pragma warning restore CA1859
|
||||||
UnlockTimingOptions options = new(100, 20000, 3000);
|
UnlockTimingOptions options = new(100, 20000, 3000);
|
||||||
Progress<UnlockerStatus> lockerProgress = new(unlockStatus => progress.Report(LaunchStatus.FromUnlockStatus(unlockStatus)));
|
Progress<UnlockerStatus> lockerProgress = new(unlockStatus => progress.Report(LaunchStatus.FromUnlockStatus(unlockStatus)));
|
||||||
return unlocker.UnlockAsync(options, lockerProgress, token);
|
return unlocker.UnlockAsync(options, lockerProgress, token);
|
||||||
|
|||||||
@@ -28,8 +28,9 @@ internal static class KnownLaunchSchemes
|
|||||||
/// <returns>已知的启动方案</returns>
|
/// <returns>已知的启动方案</returns>
|
||||||
public static List<LaunchScheme> Get()
|
public static List<LaunchScheme> Get()
|
||||||
{
|
{
|
||||||
return new List<LaunchScheme>()
|
return
|
||||||
{
|
[
|
||||||
|
|
||||||
// 官服
|
// 官服
|
||||||
ServerChineseChannelDefaultSubChannelDefaultCompat,
|
ServerChineseChannelDefaultSubChannelDefaultCompat,
|
||||||
ServerChineseChannelOfficialSubChannelDefault,
|
ServerChineseChannelOfficialSubChannelDefault,
|
||||||
@@ -47,6 +48,6 @@ internal static class KnownLaunchSchemes
|
|||||||
ServerGlobalChannelOfficialSubChannelOfficial,
|
ServerGlobalChannelOfficialSubChannelOfficial,
|
||||||
ServerGlobalChannelOfficialSubChannelEpic,
|
ServerGlobalChannelOfficialSubChannelEpic,
|
||||||
ServerGlobalChannelOfficialSubChannelGoogle,
|
ServerGlobalChannelOfficialSubChannelGoogle,
|
||||||
};
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,8 +135,8 @@ internal sealed class GameFpsUnlocker : IGameFpsUnlocker
|
|||||||
{
|
{
|
||||||
// E8 ?? ?? ?? ?? 85 C0 7E 07 E8 ?? ?? ?? ?? EB 05
|
// E8 ?? ?? ?? ?? 85 C0 7E 07 E8 ?? ?? ?? ?? EB 05
|
||||||
int second = 0;
|
int second = 0;
|
||||||
ReadOnlySpan<byte> secondPart = stackalloc byte[] { 0x85, 0xC0, 0x7E, 0x07, 0xE8, };
|
ReadOnlySpan<byte> secondPart = [0x85, 0xC0, 0x7E, 0x07, 0xE8,];
|
||||||
ReadOnlySpan<byte> thirdPart = stackalloc byte[] { 0xEB, 0x05, };
|
ReadOnlySpan<byte> thirdPart = [0xEB, 0x05,];
|
||||||
|
|
||||||
while (second >= 0 && second < memory.Length)
|
while (second >= 0 && second < memory.Length)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ internal sealed partial class HutaoAsAService : IHutaoAsAService
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new();
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,6 +168,23 @@ internal sealed class NavigationService : INavigationService, INavigationInitial
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<NavigationViewItem> EnumerateMenuItems(IList<object> items)
|
||||||
|
{
|
||||||
|
foreach (NavigationViewItem item in items.OfType<NavigationViewItem>())
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
|
||||||
|
// Suppress recursion method call if possible
|
||||||
|
if (item.MenuItems.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (NavigationViewItem subItem in EnumerateMenuItems(item.MenuItems))
|
||||||
|
{
|
||||||
|
yield return subItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool SyncSelectedNavigationViewItemWith(Type? pageType)
|
private bool SyncSelectedNavigationViewItemWith(Type? pageType)
|
||||||
{
|
{
|
||||||
if (NavigationView is null || pageType is null)
|
if (NavigationView is null || pageType is null)
|
||||||
@@ -191,23 +208,6 @@ internal sealed class NavigationService : INavigationService, INavigationInitial
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<NavigationViewItem> EnumerateMenuItems(IList<object> items)
|
|
||||||
{
|
|
||||||
foreach (NavigationViewItem item in items.OfType<NavigationViewItem>())
|
|
||||||
{
|
|
||||||
yield return item;
|
|
||||||
|
|
||||||
// Suppress recursion method call if possible
|
|
||||||
if (item.MenuItems.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (NavigationViewItem subItem in EnumerateMenuItems(item.MenuItems))
|
|
||||||
{
|
|
||||||
yield return subItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
|
private void OnItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
|
||||||
{
|
{
|
||||||
selected = NavigationView?.SelectedItem as NavigationViewItem;
|
selected = NavigationView?.SelectedItem as NavigationViewItem;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ internal sealed class InfoBarService : IInfoBarService
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ObservableCollection<InfoBar> Collection
|
public ObservableCollection<InfoBar> Collection
|
||||||
{
|
{
|
||||||
get => collection ??= new();
|
get => collection ??= [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -121,7 +121,7 @@ internal sealed class InfoBarService : IInfoBarService
|
|||||||
Title = title,
|
Title = title,
|
||||||
Message = message,
|
Message = message,
|
||||||
IsOpen = true,
|
IsOpen = true,
|
||||||
Transitions = new() { new AddDeleteThemeTransition() },
|
Transitions = [new AddDeleteThemeTransition()],
|
||||||
};
|
};
|
||||||
|
|
||||||
infoBar.Closed += infobarClosedEventHandler;
|
infoBar.Closed += infobarClosedEventHandler;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ internal sealed partial class UserInitializationService : IUserInitializationSer
|
|||||||
if (!await InitializeUserAsync(user, token).ConfigureAwait(false))
|
if (!await InitializeUserAsync(user, token).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
user.UserInfo = new() { Nickname = SH.ModelBindingUserInitializationFailed };
|
user.UserInfo = new() { Nickname = SH.ModelBindingUserInitializationFailed };
|
||||||
user.UserGameRoles = new();
|
user.UserGameRoles = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
@@ -176,7 +176,7 @@ internal sealed partial class UserInitializationService : IUserInitializationSer
|
|||||||
if (userGameRolesResponse.IsOk())
|
if (userGameRolesResponse.IsOk())
|
||||||
{
|
{
|
||||||
user.UserGameRoles = userGameRolesResponse.Data.List;
|
user.UserGameRoles = userGameRolesResponse.Data.List;
|
||||||
return user.UserGameRoles.Any();
|
return user.UserGameRoles.Count > 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -271,22 +271,22 @@
|
|||||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.230907" />
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.230907" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.230907" />
|
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.230907" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.13" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.13">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.1.0" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.6.11" />
|
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.8.8" />
|
||||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
||||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.231008000" />
|
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.231008000" />
|
||||||
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.507">
|
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.507">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="System.IO.Hashing" Version="7.0.0" />
|
<PackageReference Include="System.IO.Hashing" Version="8.0.0" />
|
||||||
<PackageReference Include="TaskScheduler" Version="2.10.1" />
|
<PackageReference Include="TaskScheduler" Version="2.10.1" />
|
||||||
<Manifest Include="$(ApplicationManifest)" />
|
<Manifest Include="$(ApplicationManifest)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -252,7 +252,6 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[SuppressMessage("", "SA1010")]
|
|
||||||
[Command("ExportAsUIAFToFileCommand")]
|
[Command("ExportAsUIAFToFileCommand")]
|
||||||
private async Task ExportAsUIAFToFileAsync()
|
private async Task ExportAsUIAFToFileAsync()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,8 +23,7 @@ internal sealed class Team : List<AvatarView>
|
|||||||
public Team(ItemRate<string, int> team, Dictionary<AvatarId, Avatar> idAvatarMap)
|
public Team(ItemRate<string, int> team, Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||||
: base(4)
|
: base(4)
|
||||||
{
|
{
|
||||||
// TODO use Collection Literials
|
foreach (StringSegment item in new StringTokenizer(team.Item, [',']))
|
||||||
foreach (StringSegment item in new StringTokenizer(team.Item, new char[] { ',' }))
|
|
||||||
{
|
{
|
||||||
uint id = uint.Parse(item.AsSpan(), CultureInfo.InvariantCulture);
|
uint id = uint.Parse(item.AsSpan(), CultureInfo.InvariantCulture);
|
||||||
Add(new(idAvatarMap[id]));
|
Add(new(idAvatarMap[id]));
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ internal sealed partial class DailyNoteViewModelSlim : Abstraction.ViewModelSlim
|
|||||||
|
|
||||||
// 此处使用浅拷贝的列表以避免当导航到实时便笺页面后
|
// 此处使用浅拷贝的列表以避免当导航到实时便笺页面后
|
||||||
// 由于主页尚未卸载,添加或删除便笺可能会崩溃的问题
|
// 由于主页尚未卸载,添加或删除便笺可能会崩溃的问题
|
||||||
List<DailyNoteEntry> entryList = entries.ToList();
|
List<DailyNoteEntry> entryList = [.. entries];
|
||||||
|
|
||||||
await taskContext.SwitchToMainThreadAsync();
|
await taskContext.SwitchToMainThreadAsync();
|
||||||
DailyNoteEntries = entryList;
|
DailyNoteEntries = entryList;
|
||||||
|
|||||||
@@ -231,7 +231,6 @@ internal sealed partial class GachaLogViewModel : Abstraction.ViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[SuppressMessage("", "SA1010")]
|
|
||||||
[Command("ExportToUIGFJsonCommand")]
|
[Command("ExportToUIGFJsonCommand")]
|
||||||
private async Task ExportToUIGFJsonAsync()
|
private async Task ExportToUIGFJsonAsync()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ internal static class StaticResource
|
|||||||
|
|
||||||
public static HashSet<string> GetUnfulfilledCategorySet()
|
public static HashSet<string> GetUnfulfilledCategorySet()
|
||||||
{
|
{
|
||||||
HashSet<string> result = new();
|
HashSet<string> result = [];
|
||||||
ApplicationDataCompositeValue map = LocalSetting.Get(ContractMap, DefaultResourceVersionMap);
|
ApplicationDataCompositeValue map = LocalSetting.Get(ContractMap, DefaultResourceVersionMap);
|
||||||
foreach ((string key, object value) in LatestResourceVersionMap)
|
foreach ((string key, object value) in LatestResourceVersionMap)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -230,15 +230,15 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Command("OpenCacheFolderCommand")]
|
[Command("OpenCacheFolderCommand")]
|
||||||
private Task OpenCacheFolderAsync()
|
private async Task OpenCacheFolderAsync()
|
||||||
{
|
{
|
||||||
return Launcher.LaunchFolderPathAsync(runtimeOptions.LocalCache).AsTask();
|
await Launcher.LaunchFolderPathAsync(runtimeOptions.LocalCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("OpenDataFolderCommand")]
|
[Command("OpenDataFolderCommand")]
|
||||||
private Task OpenDataFolderAsync()
|
private async Task OpenDataFolderAsync()
|
||||||
{
|
{
|
||||||
return Launcher.LaunchFolderPathAsync(runtimeOptions.DataFolder).AsTask();
|
await Launcher.LaunchFolderPathAsync(runtimeOptions.DataFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("DeleteUsersCommand")]
|
[Command("DeleteUsersCommand")]
|
||||||
|
|||||||
@@ -16,11 +16,7 @@ internal sealed class LevelView : IMappingFrom<LevelView, TowerLevel, SpiralAbys
|
|||||||
{
|
{
|
||||||
Index = SH.ModelBindingHutaoComplexRankLevel.Format(towerLevel.Index);
|
Index = SH.ModelBindingHutaoComplexRankLevel.Format(towerLevel.Index);
|
||||||
IndexValue = towerLevel.Index;
|
IndexValue = towerLevel.Index;
|
||||||
Battles = new()
|
Battles = [BattleView.From(towerLevel, 1, context), BattleView.From(towerLevel, 2, context)];
|
||||||
{
|
|
||||||
BattleView.From(towerLevel, 1, context),
|
|
||||||
BattleView.From(towerLevel, 2, context),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -24,10 +24,8 @@ internal static class AvatarFilter
|
|||||||
|
|
||||||
private static bool DoFilter(string input, Avatar avatar)
|
private static bool DoFilter(string input, Avatar avatar)
|
||||||
{
|
{
|
||||||
List<bool> matches = new();
|
List<bool> matches = [];
|
||||||
|
foreach (StringSegment segment in new StringTokenizer(input, [' ']))
|
||||||
// TODO: use Collection Literals
|
|
||||||
foreach (StringSegment segment in new StringTokenizer(input, new char[] { ' ' }))
|
|
||||||
{
|
{
|
||||||
string value = segment.ToString();
|
string value = segment.ToString();
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ internal static class WeaponFilter
|
|||||||
return (object o) => o is Weapon weapon && DoFilter(input, weapon);
|
return (object o) => o is Weapon weapon && DoFilter(input, weapon);
|
||||||
}
|
}
|
||||||
|
|
||||||
[SuppressMessage("", "SA1010")]
|
|
||||||
private static bool DoFilter(string input, Weapon weapon)
|
private static bool DoFilter(string input, Weapon weapon)
|
||||||
{
|
{
|
||||||
List<bool> matches = [];
|
List<bool> matches = [];
|
||||||
|
|||||||
@@ -92,15 +92,15 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
|
|||||||
|
|
||||||
Dictionary<MaterialId, Material> idMaterialMap = await metadataService.GetIdToMaterialMapAsync().ConfigureAwait(false);
|
Dictionary<MaterialId, Material> idMaterialMap = await metadataService.GetIdToMaterialMapAsync().ConfigureAwait(false);
|
||||||
List<Avatar> avatars = await metadataService.GetAvatarsAsync().ConfigureAwait(false);
|
List<Avatar> avatars = await metadataService.GetAvatarsAsync().ConfigureAwait(false);
|
||||||
List<Avatar> sorted = avatars
|
IOrderedEnumerable<Avatar> sorted = avatars
|
||||||
.OrderByDescending(avatar => avatar.BeginTime)
|
.OrderByDescending(avatar => avatar.BeginTime)
|
||||||
.ThenByDescending(avatar => avatar.Sort)
|
.ThenByDescending(avatar => avatar.Sort);
|
||||||
.ToList();
|
List<Avatar> list = [.. sorted];
|
||||||
|
|
||||||
await CombineComplexDataAsync(sorted, idMaterialMap).ConfigureAwait(false);
|
await CombineComplexDataAsync(list, idMaterialMap).ConfigureAwait(false);
|
||||||
|
|
||||||
await taskContext.SwitchToMainThreadAsync();
|
await taskContext.SwitchToMainThreadAsync();
|
||||||
Avatars = new AdvancedCollectionView(sorted, true);
|
Avatars = new AdvancedCollectionView(list, true);
|
||||||
Selected = Avatars.Cast<Avatar>().FirstOrDefault();
|
Selected = Avatars.Cast<Avatar>().FirstOrDefault();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -192,13 +192,13 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
|
|||||||
Dictionary<FightProperty, GrowCurveType> avatarGrowCurve = avatar.GrowCurves.ToDictionary(g => g.Type, g => g.Value);
|
Dictionary<FightProperty, GrowCurveType> avatarGrowCurve = avatar.GrowCurves.ToDictionary(g => g.Type, g => g.Value);
|
||||||
FightProperty promoteProperty = avatarPromoteMap[0].AddProperties.Last().Type;
|
FightProperty promoteProperty = avatarPromoteMap[0].AddProperties.Last().Type;
|
||||||
|
|
||||||
List<PropertyCurveValue> propertyCurveValues = new()
|
List<PropertyCurveValue> propertyCurveValues =
|
||||||
{
|
[
|
||||||
new(FightProperty.FIGHT_PROP_BASE_HP, avatarGrowCurve, avatar.BaseValue),
|
new(FightProperty.FIGHT_PROP_BASE_HP, avatarGrowCurve, avatar.BaseValue),
|
||||||
new(FightProperty.FIGHT_PROP_BASE_ATTACK, avatarGrowCurve, avatar.BaseValue),
|
new(FightProperty.FIGHT_PROP_BASE_ATTACK, avatarGrowCurve, avatar.BaseValue),
|
||||||
new(FightProperty.FIGHT_PROP_BASE_DEFENSE, avatarGrowCurve, avatar.BaseValue),
|
new(FightProperty.FIGHT_PROP_BASE_DEFENSE, avatarGrowCurve, avatar.BaseValue),
|
||||||
new(promoteProperty, avatarGrowCurve, avatar.BaseValue),
|
new(promoteProperty, avatarGrowCurve, avatar.BaseValue),
|
||||||
};
|
];
|
||||||
|
|
||||||
ArgumentNullException.ThrowIfNull(levelAvatarCurveMap);
|
ArgumentNullException.ThrowIfNull(levelAvatarCurveMap);
|
||||||
BaseValueInfo = new(avatar.MaxLevel, propertyCurveValues, levelAvatarCurveMap, avatarPromoteMap);
|
BaseValueInfo = new(avatar.MaxLevel, propertyCurveValues, levelAvatarCurveMap, avatarPromoteMap);
|
||||||
|
|||||||
@@ -461,7 +461,7 @@ internal class MiHoYoJSBridge
|
|||||||
}
|
}
|
||||||
|
|
||||||
[SuppressMessage("", "CA2254")]
|
[SuppressMessage("", "CA2254")]
|
||||||
private IJsResult? LogUnhandledMessage([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string message, params object?[] param)
|
private IJsResult? LogUnhandledMessage(string message, params object?[] param)
|
||||||
{
|
{
|
||||||
logger.LogWarning(message, param);
|
logger.LogWarning(message, param);
|
||||||
return default;
|
return default;
|
||||||
@@ -490,7 +490,7 @@ internal class MiHoYoJSBridge
|
|||||||
"pushPage" => await PushPageAsync(param).ConfigureAwait(false),
|
"pushPage" => await PushPageAsync(param).ConfigureAwait(false),
|
||||||
"share" => Share(param),
|
"share" => Share(param),
|
||||||
"showLoading" => null,
|
"showLoading" => null,
|
||||||
_ => LogUnhandledMessage("Unhandled Message Type: {method}", param.Method),
|
_ => LogUnhandledMessage("Unhandled Message Type: {Method}", param.Method),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
catch (ObjectDisposedException)
|
catch (ObjectDisposedException)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ internal sealed partial class Cookie
|
|||||||
/// 构造一个空白的Cookie
|
/// 构造一个空白的Cookie
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Cookie()
|
public Cookie()
|
||||||
: this(new())
|
: this([])
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ internal sealed partial class Cookie
|
|||||||
/// <returns>新的Cookie对象</returns>
|
/// <returns>新的Cookie对象</returns>
|
||||||
public static Cookie Parse(string cookieString)
|
public static Cookie Parse(string cookieString)
|
||||||
{
|
{
|
||||||
SortedDictionary<string, string> cookieMap = new();
|
SortedDictionary<string, string> cookieMap = [];
|
||||||
cookieString = cookieString.Replace(" ", string.Empty, StringComparison.Ordinal);
|
cookieString = cookieString.Replace(" ", string.Empty, StringComparison.Ordinal);
|
||||||
string[] values = cookieString.Split(';', StringSplitOptions.RemoveEmptyEntries);
|
string[] values = cookieString.Split(';', StringSplitOptions.RemoveEmptyEntries);
|
||||||
foreach (string[] parts in values.Select(c => c.Split('=', 2)))
|
foreach (string[] parts in values.Select(c => c.Split('=', 2)))
|
||||||
@@ -59,7 +59,7 @@ internal sealed partial class Cookie
|
|||||||
|
|
||||||
public static Cookie FromCoreWebView2Cookies(IReadOnlyList<CoreWebView2Cookie> webView2Cookies)
|
public static Cookie FromCoreWebView2Cookies(IReadOnlyList<CoreWebView2Cookie> webView2Cookies)
|
||||||
{
|
{
|
||||||
SortedDictionary<string, string> cookieMap = new();
|
SortedDictionary<string, string> cookieMap = [];
|
||||||
|
|
||||||
foreach (CoreWebView2Cookie cookie in webView2Cookies)
|
foreach (CoreWebView2Cookie cookie in webView2Cookies)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ namespace Snap.Hutao.Web.Hoyolab;
|
|||||||
|
|
||||||
internal static class PlayerUidExtension
|
internal static class PlayerUidExtension
|
||||||
{
|
{
|
||||||
[SuppressMessage("", "SA1010")]
|
|
||||||
public static string ToQueryString(this in PlayerUid playerUid)
|
public static string ToQueryString(this in PlayerUid playerUid)
|
||||||
{
|
{
|
||||||
NameValueCollection collection = [];
|
NameValueCollection collection = [];
|
||||||
|
|||||||
@@ -53,12 +53,12 @@ internal sealed class AvatarPromotionDelta
|
|||||||
return new()
|
return new()
|
||||||
{
|
{
|
||||||
AvatarLevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarLevelTarget, 90U),
|
AvatarLevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarLevelTarget, 90U),
|
||||||
SkillList = new()
|
SkillList =
|
||||||
{
|
[
|
||||||
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillATarget, 10U), },
|
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillATarget, 10U), },
|
||||||
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillETarget, 10U), },
|
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillETarget, 10U), },
|
||||||
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillQTarget, 10U), },
|
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillQTarget, 10U), },
|
||||||
},
|
],
|
||||||
Weapon = new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationWeapon90LevelTarget, 90U), },
|
Weapon = new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationWeapon90LevelTarget, 90U), },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ internal sealed partial class CalculateClient
|
|||||||
int currentPage = 1;
|
int currentPage = 1;
|
||||||
SyncAvatarFilter filter = new() { Uid = userAndUid.Uid.Value, Region = userAndUid.Uid.Region };
|
SyncAvatarFilter filter = new() { Uid = userAndUid.Uid.Value, Region = userAndUid.Uid.Region };
|
||||||
|
|
||||||
List<Avatar> avatars = new();
|
List<Avatar> avatars = [];
|
||||||
Response<ListWrapper<Avatar>>? resp;
|
Response<ListWrapper<Avatar>>? resp;
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -166,10 +166,10 @@ internal sealed partial class CalculateClient
|
|||||||
private class SyncAvatarFilter
|
private class SyncAvatarFilter
|
||||||
{
|
{
|
||||||
[JsonPropertyName("element_attr_ids")]
|
[JsonPropertyName("element_attr_ids")]
|
||||||
public List<int>? ElementAttrIds { get; set; } = new();
|
public List<int>? ElementAttrIds { get; set; } = [];
|
||||||
|
|
||||||
[JsonPropertyName("weapon_cat_ids")]
|
[JsonPropertyName("weapon_cat_ids")]
|
||||||
public List<int>? WeaponCatIds { get; set; } = new();
|
public List<int>? WeaponCatIds { get; set; } = [];
|
||||||
|
|
||||||
[JsonPropertyName("page")]
|
[JsonPropertyName("page")]
|
||||||
public int Page { get; set; }
|
public int Page { get; set; }
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using System.Collections.Frozen;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
|
||||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.DailyNote;
|
namespace Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.DailyNote;
|
||||||
@@ -17,10 +18,7 @@ internal sealed class Expedition
|
|||||||
private const string Keqing = "https://upload-bbs.mihoyo.com/game_record/genshin/character_side_icon/UI_AvatarIcon_Side_Keqing.png";
|
private const string Keqing = "https://upload-bbs.mihoyo.com/game_record/genshin/character_side_icon/UI_AvatarIcon_Side_Keqing.png";
|
||||||
private const string Sara = "https://upload-bbs.mihoyo.com/game_record/genshin/character_side_icon/UI_AvatarIcon_Side_Sara.png";
|
private const string Sara = "https://upload-bbs.mihoyo.com/game_record/genshin/character_side_icon/UI_AvatarIcon_Side_Sara.png";
|
||||||
|
|
||||||
private static readonly ImmutableList<string> ShortExpeditionTimeAvatars = new List<string>()
|
private static readonly FrozenSet<string> ShortExpeditionTimeAvatars = FrozenSet.ToFrozenSet([Bennett, Chongyun, Fischl, Keqing, Sara]);
|
||||||
{
|
|
||||||
Bennett, Chongyun, Fischl, Keqing, Sara,
|
|
||||||
}.ToImmutableList();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 图标
|
/// 图标
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
|||||||
{
|
{
|
||||||
// Replace message
|
// Replace message
|
||||||
resp.Message = SH.WebDailyNoteVerificationFailed;
|
resp.Message = SH.WebDailyNoteVerificationFailed;
|
||||||
IGeetestCardVerifier verifier = serviceProvider.GetRequiredService<HomaGeetestCardVerifier>();
|
IGeetestCardVerifier verifier = serviceProvider.GetRequiredKeyedService<IGeetestCardVerifier>(GeetestCardVerifierType.Custom);
|
||||||
|
|
||||||
if (await verifier.TryValidateXrpcChallengeAsync(userAndUid.User, token).ConfigureAwait(false) is { } challenge)
|
if (await verifier.TryValidateXrpcChallengeAsync(userAndUid.User, token).ConfigureAwait(false) is { } challenge)
|
||||||
{
|
{
|
||||||
@@ -99,7 +99,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
|||||||
{
|
{
|
||||||
// Replace message
|
// Replace message
|
||||||
resp.Message = SH.WebIndexOrSpiralAbyssVerificationFailed;
|
resp.Message = SH.WebIndexOrSpiralAbyssVerificationFailed;
|
||||||
IGeetestCardVerifier verifier = serviceProvider.GetRequiredService<HomaGeetestCardVerifier>();
|
IGeetestCardVerifier verifier = serviceProvider.GetRequiredKeyedService<IGeetestCardVerifier>(GeetestCardVerifierType.Custom);
|
||||||
|
|
||||||
if (await verifier.TryValidateXrpcChallengeAsync(userAndUid.User, token).ConfigureAwait(false) is { } challenge)
|
if (await verifier.TryValidateXrpcChallengeAsync(userAndUid.User, token).ConfigureAwait(false) is { } challenge)
|
||||||
{
|
{
|
||||||
@@ -146,7 +146,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
|||||||
{
|
{
|
||||||
// Replace message
|
// Replace message
|
||||||
resp.Message = SH.WebIndexOrSpiralAbyssVerificationFailed;
|
resp.Message = SH.WebIndexOrSpiralAbyssVerificationFailed;
|
||||||
IGeetestCardVerifier verifier = serviceProvider.GetRequiredService<HomaGeetestCardVerifier>();
|
IGeetestCardVerifier verifier = serviceProvider.GetRequiredKeyedService<IGeetestCardVerifier>(GeetestCardVerifierType.Custom);
|
||||||
|
|
||||||
if (await verifier.TryValidateXrpcChallengeAsync(userAndUid.User, token).ConfigureAwait(false) is { } challenge)
|
if (await verifier.TryValidateXrpcChallengeAsync(userAndUid.User, token).ConfigureAwait(false) is { } challenge)
|
||||||
{
|
{
|
||||||
@@ -156,9 +156,9 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
|||||||
.SetXrpcChallenge(challenge)
|
.SetXrpcChallenge(challenge)
|
||||||
.Get();
|
.Get();
|
||||||
|
|
||||||
await builder.SetDynamicSecretAsync(DynamicSecretVersion.Gen2, SaltType.X4, false).ConfigureAwait(false);
|
await verifiedbuilder.SetDynamicSecretAsync(DynamicSecretVersion.Gen2, SaltType.X4, false).ConfigureAwait(false);
|
||||||
|
|
||||||
resp = await builder
|
resp = await verifiedbuilder
|
||||||
.TryCatchSendAsync<Response<SpiralAbyss.SpiralAbyss>>(httpClient, logger, token)
|
.TryCatchSendAsync<Response<SpiralAbyss.SpiralAbyss>>(httpClient, logger, token)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
|||||||
{
|
{
|
||||||
// Replace message
|
// Replace message
|
||||||
resp.Message = SH.WebIndexOrSpiralAbyssVerificationFailed;
|
resp.Message = SH.WebIndexOrSpiralAbyssVerificationFailed;
|
||||||
IGeetestCardVerifier verifier = serviceProvider.GetRequiredService<HomaGeetestCardVerifier>();
|
IGeetestCardVerifier verifier = serviceProvider.GetRequiredKeyedService<IGeetestCardVerifier>(GeetestCardVerifierType.Custom);
|
||||||
|
|
||||||
if (await verifier.TryValidateXrpcChallengeAsync(userAndUid.User, token).ConfigureAwait(false) is { } challenge)
|
if (await verifier.TryValidateXrpcChallengeAsync(userAndUid.User, token).ConfigureAwait(false) is { } challenge)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.Verification;
|
||||||
|
|
||||||
|
internal enum GeetestCardVerifierType
|
||||||
|
{
|
||||||
|
Custom,
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ using Snap.Hutao.Web.Hutao.Geetest;
|
|||||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.Verification;
|
namespace Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.Verification;
|
||||||
|
|
||||||
[ConstructorGenerated]
|
[ConstructorGenerated]
|
||||||
[Injection(InjectAs.Transient)]
|
[Injection(InjectAs.Transient, Key = GeetestCardVerifierType.Custom)]
|
||||||
internal sealed partial class HomaGeetestCardVerifier : IGeetestCardVerifier
|
internal sealed partial class HomaGeetestCardVerifier : IGeetestCardVerifier
|
||||||
{
|
{
|
||||||
private readonly CardClient cardClient;
|
private readonly CardClient cardClient;
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ internal sealed class ReliquarySetsConverter : JsonConverter<ReliquarySets>
|
|||||||
private const char Separator = ',';
|
private const char Separator = ',';
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
[SuppressMessage("", "SA1010")]
|
|
||||||
public override ReliquarySets? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
public override ReliquarySets? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
{
|
{
|
||||||
if (reader.GetString() is { } source)
|
if (reader.GetString() is { } source)
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ internal class JsonHttpContentSerializer : HttpContentSerializer
|
|||||||
return JsonSerializer.Deserialize(json, contentType, JsonSerializerOptions);
|
return JsonSerializer.Deserialize(json, contentType, JsonSerializerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpContent? SerializeUtf8(object? content, Type contentType)
|
private ByteArrayContent? SerializeUtf8(object? content, Type contentType)
|
||||||
{
|
{
|
||||||
byte[] bytes = JsonSerializer.SerializeToUtf8Bytes(content, contentType, JsonSerializerOptions);
|
byte[] bytes = JsonSerializer.SerializeToUtf8Bytes(content, contentType, JsonSerializerOptions);
|
||||||
ByteArrayContent httpContent = new(bytes);
|
ByteArrayContent httpContent = new(bytes);
|
||||||
@@ -75,7 +75,7 @@ internal class JsonHttpContentSerializer : HttpContentSerializer
|
|||||||
return httpContent;
|
return httpContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpContent? SerializeOtherEncoding(object? content, Type contentType, Encoding encoding)
|
private StringContent? SerializeOtherEncoding(object? content, Type contentType, Encoding encoding)
|
||||||
{
|
{
|
||||||
string str = JsonSerializer.Serialize(content, contentType, JsonSerializerOptions);
|
string str = JsonSerializer.Serialize(content, contentType, JsonSerializerOptions);
|
||||||
return new StringContent(str, encoding, MediaType.ApplicationJson);
|
return new StringContent(str, encoding, MediaType.ApplicationJson);
|
||||||
|
|||||||
Reference in New Issue
Block a user