activation optimization

This commit is contained in:
Lightczx
2023-12-01 14:58:10 +08:00
parent 98a711da70
commit 2b851a5459
5 changed files with 169 additions and 53 deletions

View File

@@ -5,7 +5,7 @@ using System.Text.Json.Serialization;
namespace Snap.Hutao.Test.BaseClassLibrary;
[TestClass]
public class JsonSerializeTest
public sealed class JsonSerializeTest
{
public TestContext? TestContext { get; set; }

View File

@@ -0,0 +1,19 @@
using System;
namespace Snap.Hutao.Test.BaseClassLibrary;
[TestClass]
public sealed class TypeReflectionTest
{
[TestMethod]
public void TypeCodeOfEnumIsUserlyingTypeTypeCode()
{
Assert.AreEqual(Type.GetTypeCode(typeof(TestEnum)), TypeCode.Int32);
}
private enum TestEnum
{
A,
B,
}
}

View File

@@ -140,14 +140,19 @@ internal sealed partial class Activation : IActivation
private async ValueTask HandleNormalLaunchActionAsync()
{
// Increase launch times
LocalSetting.Set(SettingKeys.LaunchTimes, LocalSetting.Get(SettingKeys.LaunchTimes, 0) + 1);
LocalSetting.Update(SettingKeys.LaunchTimes, 0, x => x + 1);
if (StaticResource.IsAnyUnfulfilledCategoryPresent())
// If it's the first time launch, we show the guide window anyway.
// Otherwise, we check if there's any unfulfilled resource category present.
if (UnsafeLocalSetting.Get(SettingKeys.Major1Minor7Revision0GuideState, GuideState.Language) >= GuideState.StaticResourceBegin)
{
LocalSetting.Set(SettingKeys.Major1Minor7Revision0GuideState, (uint)GuideState.StaticResourceBegin);
if (StaticResource.IsAnyUnfulfilledCategoryPresent())
{
UnsafeLocalSetting.Set(SettingKeys.Major1Minor7Revision0GuideState, GuideState.StaticResourceBegin);
}
}
if (LocalSetting.Get(SettingKeys.Major1Minor7Revision0GuideState, (uint)GuideState.Language) < (uint)GuideState.Completed)
if (UnsafeLocalSetting.Get(SettingKeys.Major1Minor7Revision0GuideState, GuideState.Language) < GuideState.Completed)
{
await taskContext.SwitchToMainThreadAsync();
serviceProvider.GetRequiredService<GuideWindow>();
@@ -160,31 +165,33 @@ internal sealed partial class Activation : IActivation
private async ValueTask WaitMainWindowAsync()
{
if (currentWindowReference.Window is null)
if (currentWindowReference.Window is not null)
{
await taskContext.SwitchToMainThreadAsync();
serviceProvider.GetRequiredService<MainWindow>();
await taskContext.SwitchToBackgroundAsync();
serviceProvider
.GetRequiredService<IMetadataService>()
.As<IMetadataServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
serviceProvider
.GetRequiredService<IHutaoUserService>()
.As<IHutaoUserServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
serviceProvider
.GetRequiredService<IDiscordService>()
.SetNormalActivity()
.SafeForget();
return;
}
await taskContext.SwitchToMainThreadAsync();
serviceProvider.GetRequiredService<MainWindow>();
await taskContext.SwitchToBackgroundAsync();
serviceProvider
.GetRequiredService<IMetadataService>()
.As<IMetadataServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
serviceProvider
.GetRequiredService<IHutaoUserService>()
.As<IHutaoUserServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
serviceProvider
.GetRequiredService<IDiscordService>()
.SetNormalActivity()
.SafeForget();
}
private async ValueTask HandleUrlActivationAsync(Uri uri, bool isRedirected)
@@ -279,21 +286,22 @@ internal sealed partial class Activation : IActivation
if (currentWindowReference.Window is null)
{
serviceProvider.GetRequiredService<LaunchGameWindow>();
return;
}
if (currentWindowReference.Window is MainWindow)
{
await serviceProvider
.GetRequiredService<INavigationService>()
.NavigateAsync<View.Page.LaunchGamePage>(INavigationAwaiter.Default, true)
.ConfigureAwait(false);
return;
}
else
{
if (currentWindowReference.Window is MainWindow)
{
await serviceProvider
.GetRequiredService<INavigationService>()
.NavigateAsync<View.Page.LaunchGamePage>(INavigationAwaiter.Default, true)
.ConfigureAwait(false);
}
else
{
// We have a non-Main Window, just exit current process anyway
Process.GetCurrentProcess().Kill();
}
// We have a non-Main Window, just exit current process anyway
Process.GetCurrentProcess().Kill();
}
}
}

View File

@@ -43,6 +43,12 @@ internal static class LocalSetting
return Get<uint>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static long Get(string key, long defaultValue)
{
return Get<long>(key, defaultValue);
}
/// <inheritdoc cref="Get{T}(string, T)"/>
public static ulong Get(string key, ulong defaultValue)
{
@@ -150,6 +156,12 @@ internal static class LocalSetting
Set<uint>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, long value)
{
Set<long>(key, value);
}
/// <inheritdoc cref="Set{T}(string, T)"/>
public static void Set(string key, ulong value)
{
@@ -227,13 +239,11 @@ internal static class LocalSetting
Set<ApplicationDataCompositeValue>(key, value);
}
/// <summary>
/// 获取设置项的值
/// </summary>
/// <typeparam name="T">设置项的类型</typeparam>
/// <param name="key">键</param>
/// <param name="defaultValue">默认值</param>
/// <returns>获取的值</returns>
public static void Update(string key, int defaultValue, Func<int, int> modifier)
{
Set<int?>(key, modifier(Get<int>(key, defaultValue)));
}
private static T Get<T>(string key, T defaultValue = default!)
{
if (Container.Values.TryGetValue(key, out object? value))
@@ -248,12 +258,6 @@ internal static class LocalSetting
}
}
/// <summary>
/// 设置设置项的值
/// </summary>
/// <typeparam name="T">设置项的类型</typeparam>
/// <param name="key">键</param>
/// <param name="value">值</param>
private static void Set<T>(string key, T value)
{
Container.Values[key] = value;

View File

@@ -0,0 +1,85 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Core.Setting;
internal static class UnsafeLocalSetting
{
public static unsafe TEnum Get<TEnum>(string key, TEnum defaultValue = default!)
where TEnum : unmanaged, Enum
{
switch (Type.GetTypeCode(typeof(TEnum)))
{
case TypeCode.Byte:
{
byte result = LocalSetting.Get(key, *(byte*)&defaultValue);
return *(TEnum*)&result;
}
case TypeCode.Int16:
{
short result = LocalSetting.Get(key, *(short*)&defaultValue);
return *(TEnum*)&result;
}
case TypeCode.UInt16:
{
ushort result = LocalSetting.Get(key, *(ushort*)&defaultValue);
return *(TEnum*)&result;
}
case TypeCode.Int32:
{
int result = LocalSetting.Get(key, *(int*)&defaultValue);
return *(TEnum*)&result;
}
case TypeCode.UInt32:
{
uint result = LocalSetting.Get(key, *(uint*)&defaultValue);
return *(TEnum*)&result;
}
case TypeCode.Int64:
{
long result = LocalSetting.Get(key, *(long*)&defaultValue);
return *(TEnum*)&result;
}
default:
// sbyte not supported
throw new InvalidCastException();
}
}
public static unsafe void Set<TEnum>(string key, TEnum value)
where TEnum : unmanaged, Enum
{
switch (Type.GetTypeCode(typeof(TEnum)))
{
case TypeCode.Byte:
LocalSetting.Set(key, *(byte*)&value);
break;
case TypeCode.Int16:
LocalSetting.Set(key, *(short*)&value);
break;
case TypeCode.UInt16:
LocalSetting.Set(key, *(ushort*)&value);
break;
case TypeCode.Int32:
LocalSetting.Set(key, *(int*)&value);
break;
case TypeCode.UInt32:
LocalSetting.Set(key, *(uint*)&value);
break;
case TypeCode.Int64:
LocalSetting.Set(key, *(long*)&value);
break;
case TypeCode.UInt64:
LocalSetting.Set(key, *(ulong*)&value);
break;
default:
throw new InvalidCastException();
}
}
}