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 object Key { get; set; }
|
||||
}
|
||||
""";
|
||||
context.AddSource("Snap.Hutao.Core.DependencyInjection.Annotation.Attributes.g.cs", coreDependencyInjectionAnnotations);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Snap.Hutao.SourceGeneration.Primitive;
|
||||
using System.Collections.Generic;
|
||||
@@ -68,7 +69,7 @@ internal sealed class DependencyPropertyGenerator : IIncrementalGenerator
|
||||
|
||||
string propertyName = (string)arguments[0].Value!;
|
||||
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 code;
|
||||
@@ -125,25 +126,4 @@ internal sealed class DependencyPropertyGenerator : IIncrementalGenerator
|
||||
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;
|
||||
|
||||
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<");
|
||||
break;
|
||||
case InjectAsTransientName:
|
||||
case (InjectAsSingletonName, true):
|
||||
lineBuilder.Append(" services.AddKeyedSingleton<");
|
||||
break;
|
||||
case (InjectAsTransientName, false):
|
||||
lineBuilder.Append(" services.AddTransient<");
|
||||
break;
|
||||
case InjectAsScopedName:
|
||||
case (InjectAsTransientName, true):
|
||||
lineBuilder.Append(" services.AddKeyedTransient<");
|
||||
break;
|
||||
case (InjectAsScopedName, false):
|
||||
lineBuilder.Append(" services.AddScoped<");
|
||||
break;
|
||||
case (InjectAsScopedName, true):
|
||||
lineBuilder.Append(" services.AddKeyedScoped<");
|
||||
break;
|
||||
default:
|
||||
production.ReportDiagnostic(Diagnostic.Create(invalidInjectionDescriptor, context.Context.Node.GetLocation(), injectAsName));
|
||||
break;
|
||||
@@ -113,7 +125,14 @@ internal sealed class InjectionGenerator : IIncrementalGenerator
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using Microsoft.CodeAnalysis;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
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!));
|
||||
}
|
||||
|
||||
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>
|
||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -7,6 +7,10 @@ namespace Snap.Hutao.Test;
|
||||
[TestClass]
|
||||
public class JsonSerializeTest
|
||||
{
|
||||
private TestContext? testContext;
|
||||
|
||||
public TestContext? TestContext { get => testContext; set => testContext = value; }
|
||||
|
||||
private readonly JsonSerializerOptions AlowStringNumberOptions = new()
|
||||
{
|
||||
NumberHandling = JsonNumberHandling.AllowReadingFromString,
|
||||
@@ -53,6 +57,27 @@ public class JsonSerializeTest
|
||||
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
|
||||
{
|
||||
public int A { get => B; set => B = value; }
|
||||
@@ -64,4 +89,9 @@ public class JsonSerializeTest
|
||||
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
|
||||
public int A { get; set; }
|
||||
}
|
||||
|
||||
private sealed class ByteArraySample
|
||||
{
|
||||
public byte[]? Array { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,12 @@ public sealed class ForEachRuntimeBehaviorTest
|
||||
[TestMethod]
|
||||
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;
|
||||
foreach (ReadOnlySpan<char> chars in strings)
|
||||
{
|
||||
|
||||
@@ -8,8 +8,13 @@ public sealed class RangeRuntimeBehaviorTest
|
||||
[TestMethod]
|
||||
public void RangeTrimLastOne()
|
||||
{
|
||||
#if NET8_0_OR_GREATER
|
||||
int[] array = [1, 2, 3, 4];
|
||||
int[] test = [1, 2, 3];
|
||||
#else
|
||||
int[] array = { 1, 2, 3, 4 };
|
||||
int[] test = { 1, 2, 3 };
|
||||
#endif
|
||||
int[] result = array[..^1];
|
||||
Assert.AreEqual(3, result.Length);
|
||||
Assert.IsTrue(MemoryExtensions.SequenceEqual<int>(test, result));
|
||||
|
||||
@@ -6,7 +6,12 @@ public sealed class UnsafeRuntimeBehaviorTest
|
||||
[TestMethod]
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
@@ -35,7 +35,6 @@ internal static class DependencyInjection
|
||||
|
||||
// Discrete services
|
||||
.AddSingleton<IMessenger, WeakReferenceMessenger>()
|
||||
|
||||
.BuildServiceProvider(true);
|
||||
|
||||
Ioc.Default.ConfigureServices(serviceProvider);
|
||||
|
||||
@@ -48,7 +48,7 @@ internal sealed partial class GameChannelOptionsService : IGameChannelOptionsSer
|
||||
{
|
||||
using (FileStream readStream = File.OpenRead(configPath))
|
||||
{
|
||||
elements = IniSerializer.Deserialize(readStream).ToList();
|
||||
elements = [.. IniSerializer.Deserialize(readStream)];
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
|
||||
@@ -165,11 +165,11 @@ internal sealed class LaunchOptions : DbStoreOptions
|
||||
set => SetOption(ref isMonitorEnabled, SettingEntry.LaunchIsMonitorEnabled, value);
|
||||
}
|
||||
|
||||
public List<AspectRatio> AspectRatios { get; } = new()
|
||||
{
|
||||
public List<AspectRatio> AspectRatios { get; } =
|
||||
[
|
||||
new(2560, 1440),
|
||||
new(1920, 1080),
|
||||
};
|
||||
];
|
||||
|
||||
public AspectRatio? SelectedAspectRatio
|
||||
{
|
||||
|
||||
@@ -178,11 +178,11 @@ internal sealed partial class PackageConverter
|
||||
|
||||
private async ValueTask<Dictionary<string, VersionItem>> GetVersionItemsAsync(Stream stream)
|
||||
{
|
||||
Dictionary<string, VersionItem> results = new();
|
||||
Dictionary<string, VersionItem> results = [];
|
||||
using (StreamReader reader = new(stream))
|
||||
{
|
||||
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);
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
|
||||
@@ -30,8 +30,8 @@ internal sealed partial class GameProcessService : IGameProcessService
|
||||
return false;
|
||||
}
|
||||
|
||||
return System.Diagnostics.Process.GetProcessesByName(YuanShenProcessName).Any()
|
||||
|| System.Diagnostics.Process.GetProcessesByName(GenshinImpactProcessName).Any();
|
||||
return System.Diagnostics.Process.GetProcessesByName(YuanShenProcessName).Length > 0
|
||||
|| System.Diagnostics.Process.GetProcessesByName(GenshinImpactProcessName).Length > 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
#pragma warning disable CA1859
|
||||
IGameFpsUnlocker unlocker = serviceProvider.CreateInstance<GameFpsUnlocker>(game);
|
||||
#pragma warning restore CA1859
|
||||
UnlockTimingOptions options = new(100, 20000, 3000);
|
||||
Progress<UnlockerStatus> lockerProgress = new(unlockStatus => progress.Report(LaunchStatus.FromUnlockStatus(unlockStatus)));
|
||||
return unlocker.UnlockAsync(options, lockerProgress, token);
|
||||
|
||||
@@ -28,8 +28,9 @@ internal static class KnownLaunchSchemes
|
||||
/// <returns>已知的启动方案</returns>
|
||||
public static List<LaunchScheme> Get()
|
||||
{
|
||||
return new List<LaunchScheme>()
|
||||
{
|
||||
return
|
||||
[
|
||||
|
||||
// 官服
|
||||
ServerChineseChannelDefaultSubChannelDefaultCompat,
|
||||
ServerChineseChannelOfficialSubChannelDefault,
|
||||
@@ -47,6 +48,6 @@ internal static class KnownLaunchSchemes
|
||||
ServerGlobalChannelOfficialSubChannelOfficial,
|
||||
ServerGlobalChannelOfficialSubChannelEpic,
|
||||
ServerGlobalChannelOfficialSubChannelGoogle,
|
||||
};
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -135,8 +135,8 @@ internal sealed class GameFpsUnlocker : IGameFpsUnlocker
|
||||
{
|
||||
// E8 ?? ?? ?? ?? 85 C0 7E 07 E8 ?? ?? ?? ?? EB 05
|
||||
int second = 0;
|
||||
ReadOnlySpan<byte> secondPart = stackalloc byte[] { 0x85, 0xC0, 0x7E, 0x07, 0xE8, };
|
||||
ReadOnlySpan<byte> thirdPart = stackalloc byte[] { 0xEB, 0x05, };
|
||||
ReadOnlySpan<byte> secondPart = [0x85, 0xC0, 0x7E, 0x07, 0xE8,];
|
||||
ReadOnlySpan<byte> thirdPart = [0xEB, 0x05,];
|
||||
|
||||
while (second >= 0 && second < memory.Length)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ internal sealed partial class HutaoAsAService : IHutaoAsAService
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (NavigationView is null || pageType is null)
|
||||
@@ -191,23 +208,6 @@ internal sealed class NavigationService : INavigationService, INavigationInitial
|
||||
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)
|
||||
{
|
||||
selected = NavigationView?.SelectedItem as NavigationViewItem;
|
||||
|
||||
@@ -31,7 +31,7 @@ internal sealed class InfoBarService : IInfoBarService
|
||||
/// <inheritdoc/>
|
||||
public ObservableCollection<InfoBar> Collection
|
||||
{
|
||||
get => collection ??= new();
|
||||
get => collection ??= [];
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -121,7 +121,7 @@ internal sealed class InfoBarService : IInfoBarService
|
||||
Title = title,
|
||||
Message = message,
|
||||
IsOpen = true,
|
||||
Transitions = new() { new AddDeleteThemeTransition() },
|
||||
Transitions = [new AddDeleteThemeTransition()],
|
||||
};
|
||||
|
||||
infoBar.Closed += infobarClosedEventHandler;
|
||||
|
||||
@@ -24,7 +24,7 @@ internal sealed partial class UserInitializationService : IUserInitializationSer
|
||||
if (!await InitializeUserAsync(user, token).ConfigureAwait(false))
|
||||
{
|
||||
user.UserInfo = new() { Nickname = SH.ModelBindingUserInitializationFailed };
|
||||
user.UserGameRoles = new();
|
||||
user.UserGameRoles = [];
|
||||
}
|
||||
|
||||
return user;
|
||||
@@ -176,7 +176,7 @@ internal sealed partial class UserInitializationService : IUserInitializationSer
|
||||
if (userGameRolesResponse.IsOk())
|
||||
{
|
||||
user.UserGameRoles = userGameRolesResponse.Data.List;
|
||||
return user.UserGameRoles.Any();
|
||||
return user.UserGameRoles.Count > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -271,22 +271,22 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.230907" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.230907" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.13" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.13">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.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.WindowsAppSDK" Version="1.4.231008000" />
|
||||
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.507">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</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" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -252,7 +252,6 @@ internal sealed partial class AchievementViewModel : Abstraction.ViewModel, INav
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("", "SA1010")]
|
||||
[Command("ExportAsUIAFToFileCommand")]
|
||||
private async Task ExportAsUIAFToFileAsync()
|
||||
{
|
||||
|
||||
@@ -23,8 +23,7 @@ internal sealed class Team : List<AvatarView>
|
||||
public Team(ItemRate<string, int> team, Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||
: base(4)
|
||||
{
|
||||
// TODO use Collection Literials
|
||||
foreach (StringSegment item in new StringTokenizer(team.Item, new char[] { ',' }))
|
||||
foreach (StringSegment item in new StringTokenizer(team.Item, [',']))
|
||||
{
|
||||
uint id = uint.Parse(item.AsSpan(), CultureInfo.InvariantCulture);
|
||||
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();
|
||||
DailyNoteEntries = entryList;
|
||||
|
||||
@@ -231,7 +231,6 @@ internal sealed partial class GachaLogViewModel : Abstraction.ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("", "SA1010")]
|
||||
[Command("ExportToUIGFJsonCommand")]
|
||||
private async Task ExportToUIGFJsonAsync()
|
||||
{
|
||||
|
||||
@@ -109,7 +109,7 @@ internal static class StaticResource
|
||||
|
||||
public static HashSet<string> GetUnfulfilledCategorySet()
|
||||
{
|
||||
HashSet<string> result = new();
|
||||
HashSet<string> result = [];
|
||||
ApplicationDataCompositeValue map = LocalSetting.Get(ContractMap, DefaultResourceVersionMap);
|
||||
foreach ((string key, object value) in LatestResourceVersionMap)
|
||||
{
|
||||
|
||||
@@ -230,15 +230,15 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
}
|
||||
|
||||
[Command("OpenCacheFolderCommand")]
|
||||
private Task OpenCacheFolderAsync()
|
||||
private async Task OpenCacheFolderAsync()
|
||||
{
|
||||
return Launcher.LaunchFolderPathAsync(runtimeOptions.LocalCache).AsTask();
|
||||
await Launcher.LaunchFolderPathAsync(runtimeOptions.LocalCache);
|
||||
}
|
||||
|
||||
[Command("OpenDataFolderCommand")]
|
||||
private Task OpenDataFolderAsync()
|
||||
private async Task OpenDataFolderAsync()
|
||||
{
|
||||
return Launcher.LaunchFolderPathAsync(runtimeOptions.DataFolder).AsTask();
|
||||
await Launcher.LaunchFolderPathAsync(runtimeOptions.DataFolder);
|
||||
}
|
||||
|
||||
[Command("DeleteUsersCommand")]
|
||||
|
||||
@@ -16,11 +16,7 @@ internal sealed class LevelView : IMappingFrom<LevelView, TowerLevel, SpiralAbys
|
||||
{
|
||||
Index = SH.ModelBindingHutaoComplexRankLevel.Format(towerLevel.Index);
|
||||
IndexValue = towerLevel.Index;
|
||||
Battles = new()
|
||||
{
|
||||
BattleView.From(towerLevel, 1, context),
|
||||
BattleView.From(towerLevel, 2, context),
|
||||
};
|
||||
Battles = [BattleView.From(towerLevel, 1, context), BattleView.From(towerLevel, 2, context)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -24,10 +24,8 @@ internal static class AvatarFilter
|
||||
|
||||
private static bool DoFilter(string input, Avatar avatar)
|
||||
{
|
||||
List<bool> matches = new();
|
||||
|
||||
// TODO: use Collection Literals
|
||||
foreach (StringSegment segment in new StringTokenizer(input, new char[] { ' ' }))
|
||||
List<bool> matches = [];
|
||||
foreach (StringSegment segment in new StringTokenizer(input, [' ']))
|
||||
{
|
||||
string value = segment.ToString();
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ internal static class WeaponFilter
|
||||
return (object o) => o is Weapon weapon && DoFilter(input, weapon);
|
||||
}
|
||||
|
||||
[SuppressMessage("", "SA1010")]
|
||||
private static bool DoFilter(string input, Weapon weapon)
|
||||
{
|
||||
List<bool> matches = [];
|
||||
|
||||
@@ -92,15 +92,15 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
|
||||
|
||||
Dictionary<MaterialId, Material> idMaterialMap = await metadataService.GetIdToMaterialMapAsync().ConfigureAwait(false);
|
||||
List<Avatar> avatars = await metadataService.GetAvatarsAsync().ConfigureAwait(false);
|
||||
List<Avatar> sorted = avatars
|
||||
IOrderedEnumerable<Avatar> sorted = avatars
|
||||
.OrderByDescending(avatar => avatar.BeginTime)
|
||||
.ThenByDescending(avatar => avatar.Sort)
|
||||
.ToList();
|
||||
.ThenByDescending(avatar => avatar.Sort);
|
||||
List<Avatar> list = [.. sorted];
|
||||
|
||||
await CombineComplexDataAsync(sorted, idMaterialMap).ConfigureAwait(false);
|
||||
await CombineComplexDataAsync(list, idMaterialMap).ConfigureAwait(false);
|
||||
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
Avatars = new AdvancedCollectionView(sorted, true);
|
||||
Avatars = new AdvancedCollectionView(list, true);
|
||||
Selected = Avatars.Cast<Avatar>().FirstOrDefault();
|
||||
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);
|
||||
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_ATTACK, avatarGrowCurve, avatar.BaseValue),
|
||||
new(FightProperty.FIGHT_PROP_BASE_DEFENSE, avatarGrowCurve, avatar.BaseValue),
|
||||
new(promoteProperty, avatarGrowCurve, avatar.BaseValue),
|
||||
};
|
||||
];
|
||||
|
||||
ArgumentNullException.ThrowIfNull(levelAvatarCurveMap);
|
||||
BaseValueInfo = new(avatar.MaxLevel, propertyCurveValues, levelAvatarCurveMap, avatarPromoteMap);
|
||||
|
||||
@@ -461,7 +461,7 @@ internal class MiHoYoJSBridge
|
||||
}
|
||||
|
||||
[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);
|
||||
return default;
|
||||
@@ -490,7 +490,7 @@ internal class MiHoYoJSBridge
|
||||
"pushPage" => await PushPageAsync(param).ConfigureAwait(false),
|
||||
"share" => Share(param),
|
||||
"showLoading" => null,
|
||||
_ => LogUnhandledMessage("Unhandled Message Type: {method}", param.Method),
|
||||
_ => LogUnhandledMessage("Unhandled Message Type: {Method}", param.Method),
|
||||
};
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
|
||||
@@ -18,7 +18,7 @@ internal sealed partial class Cookie
|
||||
/// 构造一个空白的Cookie
|
||||
/// </summary>
|
||||
public Cookie()
|
||||
: this(new())
|
||||
: this([])
|
||||
{
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ internal sealed partial class Cookie
|
||||
/// <returns>新的Cookie对象</returns>
|
||||
public static Cookie Parse(string cookieString)
|
||||
{
|
||||
SortedDictionary<string, string> cookieMap = new();
|
||||
SortedDictionary<string, string> cookieMap = [];
|
||||
cookieString = cookieString.Replace(" ", string.Empty, StringComparison.Ordinal);
|
||||
string[] values = cookieString.Split(';', StringSplitOptions.RemoveEmptyEntries);
|
||||
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)
|
||||
{
|
||||
SortedDictionary<string, string> cookieMap = new();
|
||||
SortedDictionary<string, string> cookieMap = [];
|
||||
|
||||
foreach (CoreWebView2Cookie cookie in webView2Cookies)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,6 @@ namespace Snap.Hutao.Web.Hoyolab;
|
||||
|
||||
internal static class PlayerUidExtension
|
||||
{
|
||||
[SuppressMessage("", "SA1010")]
|
||||
public static string ToQueryString(this in PlayerUid playerUid)
|
||||
{
|
||||
NameValueCollection collection = [];
|
||||
|
||||
@@ -53,12 +53,12 @@ internal sealed class AvatarPromotionDelta
|
||||
return new()
|
||||
{
|
||||
AvatarLevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarLevelTarget, 90U),
|
||||
SkillList = new()
|
||||
{
|
||||
SkillList =
|
||||
[
|
||||
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillATarget, 10U), },
|
||||
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillETarget, 10U), },
|
||||
new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationAvatarSkillQTarget, 10U), },
|
||||
},
|
||||
],
|
||||
Weapon = new() { LevelTarget = LocalSetting.Get(SettingKeys.CultivationWeapon90LevelTarget, 90U), },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ internal sealed partial class CalculateClient
|
||||
int currentPage = 1;
|
||||
SyncAvatarFilter filter = new() { Uid = userAndUid.Uid.Value, Region = userAndUid.Uid.Region };
|
||||
|
||||
List<Avatar> avatars = new();
|
||||
List<Avatar> avatars = [];
|
||||
Response<ListWrapper<Avatar>>? resp;
|
||||
|
||||
do
|
||||
@@ -166,10 +166,10 @@ internal sealed partial class CalculateClient
|
||||
private class SyncAvatarFilter
|
||||
{
|
||||
[JsonPropertyName("element_attr_ids")]
|
||||
public List<int>? ElementAttrIds { get; set; } = new();
|
||||
public List<int>? ElementAttrIds { get; set; } = [];
|
||||
|
||||
[JsonPropertyName("weapon_cat_ids")]
|
||||
public List<int>? WeaponCatIds { get; set; } = new();
|
||||
public List<int>? WeaponCatIds { get; set; } = [];
|
||||
|
||||
[JsonPropertyName("page")]
|
||||
public int Page { get; set; }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
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 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>()
|
||||
{
|
||||
Bennett, Chongyun, Fischl, Keqing, Sara,
|
||||
}.ToImmutableList();
|
||||
private static readonly FrozenSet<string> ShortExpeditionTimeAvatars = FrozenSet.ToFrozenSet([Bennett, Chongyun, Fischl, Keqing, Sara]);
|
||||
|
||||
/// <summary>
|
||||
/// 图标
|
||||
|
||||
@@ -53,7 +53,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
{
|
||||
// Replace message
|
||||
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)
|
||||
{
|
||||
@@ -99,7 +99,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
{
|
||||
// Replace message
|
||||
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)
|
||||
{
|
||||
@@ -146,7 +146,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
{
|
||||
// Replace message
|
||||
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)
|
||||
{
|
||||
@@ -156,9 +156,9 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
.SetXrpcChallenge(challenge)
|
||||
.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)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
@@ -216,7 +216,7 @@ internal sealed partial class GameRecordClient : IGameRecordClient
|
||||
{
|
||||
// Replace message
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
[ConstructorGenerated]
|
||||
[Injection(InjectAs.Transient)]
|
||||
[Injection(InjectAs.Transient, Key = GeetestCardVerifierType.Custom)]
|
||||
internal sealed partial class HomaGeetestCardVerifier : IGeetestCardVerifier
|
||||
{
|
||||
private readonly CardClient cardClient;
|
||||
|
||||
@@ -14,7 +14,6 @@ internal sealed class ReliquarySetsConverter : JsonConverter<ReliquarySets>
|
||||
private const char Separator = ',';
|
||||
|
||||
/// <inheritdoc/>
|
||||
[SuppressMessage("", "SA1010")]
|
||||
public override ReliquarySets? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.GetString() is { } source)
|
||||
|
||||
@@ -62,7 +62,7 @@ internal class JsonHttpContentSerializer : HttpContentSerializer
|
||||
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);
|
||||
ByteArrayContent httpContent = new(bytes);
|
||||
@@ -75,7 +75,7 @@ internal class JsonHttpContentSerializer : HttpContentSerializer
|
||||
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);
|
||||
return new StringContent(str, encoding, MediaType.ApplicationJson);
|
||||
|
||||
Reference in New Issue
Block a user