diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs b/src/Snap.Hutao/Snap.Hutao/Control/Extension/WebView2Extension.cs
similarity index 83%
rename from src/Snap.Hutao/Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs
rename to src/Snap.Hutao/Snap.Hutao/Control/Extension/WebView2Extension.cs
index 52e972d2..9d28ef31 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/CoreWebView2Extension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Control/Extension/WebView2Extension.cs
@@ -1,16 +1,17 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using Microsoft.UI.Xaml.Controls;
using Microsoft.Web.WebView2.Core;
using System.Diagnostics;
-namespace Snap.Hutao.Web.Bridge;
+namespace Snap.Hutao.Control.Extension;
///
/// Bridge 拓展
///
[HighQuality]
-internal static class CoreWebView2Extension
+internal static class WebView2Extension
{
[Conditional("RELEASE")]
public static void DisableDevToolsForReleaseBuild(this CoreWebView2 webView)
@@ -37,4 +38,9 @@ internal static class CoreWebView2Extension
manager.DeleteCookie(item);
}
}
+
+ public static bool IsDisposed(this WebView2 webView2)
+ {
+ return WinRTExtension.IsDisposed(webView2);
+ }
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs
index 46c03ce5..94150ea4 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs
@@ -25,7 +25,6 @@ internal sealed class ImageCache : IImageCache, IImageCacheFilePathOperation
{
private const string CacheFolderName = nameof(ImageCache);
- // TODO: use FrozenDictionary
private static readonly FrozenDictionary RetryCountToDelay = new Dictionary()
{
[0] = TimeSpan.FromSeconds(4),
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/Abstraction/OverseaSupportFactory.cs b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/Abstraction/OverseaSupportFactory.cs
index 1d3ef60d..49d10903 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/Abstraction/OverseaSupportFactory.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/Abstraction/OverseaSupportFactory.cs
@@ -3,6 +3,12 @@
namespace Snap.Hutao.Core.DependencyInjection.Abstraction;
+///
+/// 由于 AddHttpClient 不支持 KeyedService, 所以使用工厂模式
+///
+/// 抽象类型
+/// 官服/米游社类型
+/// 国际/HoYoLAB类型
internal abstract class OverseaSupportFactory : IOverseaSupportFactory
where TClientCN : notnull, TClient
where TClientOS : notnull, TClient
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/ServiceProviderExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/ServiceProviderExtension.cs
index 7850ffb9..bdaafd82 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/ServiceProviderExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/ServiceProviderExtension.cs
@@ -22,7 +22,7 @@ internal static class ServiceProviderExtension
{
if (serviceProvider is null)
{
- return false;
+ return true;
}
return serviceProvider.GetType().GetField("_disposed")?.GetValue(serviceProvider) is true;
diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/StructExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/StructExtension.cs
index c8b7f949..3d19fe1a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Extension/StructExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Extension/StructExtension.cs
@@ -67,4 +67,4 @@ internal static class StructExtension
{
return size.Width * size.Height;
}
-}
\ No newline at end of file
+}
diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/WinRTExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/WinRTExtension.cs
new file mode 100644
index 00000000..d88586a0
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/Extension/WinRTExtension.cs
@@ -0,0 +1,19 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using System.Runtime.CompilerServices;
+using WinRT;
+
+namespace Snap.Hutao.Extension;
+
+internal static class WinRTExtension
+{
+ public static bool IsDisposed(this IWinRTObject obj)
+ {
+ return GetDisposed(obj.NativeObject);
+ }
+
+ // protected bool disposed;
+ [UnsafeAccessor(UnsafeAccessorKind.Field, Name ="disposed")]
+ private static extern ref bool GetDisposed(IObjectReference objRef);
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs
index f6b0c259..64dddd00 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.Indexing.cs
@@ -84,7 +84,6 @@ internal sealed partial class MetadataService
Dictionary displays = await FromCacheAsDictionaryAsync(FileNameDisplayItem, a => a.Id, token).ConfigureAwait(false);
Dictionary materials = await GetIdToMaterialMapAsync(token).ConfigureAwait(false);
- // TODO: Cache this
Dictionary results = new(displays);
foreach ((MaterialId id, DisplayItem material) in materials)
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs
index 159074db..afa1d250 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs
@@ -4,8 +4,8 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Web.WebView2.Core;
+using Snap.Hutao.Control.Extension;
using Snap.Hutao.Control.Theme;
-using Snap.Hutao.Web.Bridge;
using Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement;
using System.Text;
using System.Text.RegularExpressions;
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Control/WebViewer.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Control/WebViewer.xaml.cs
index 1f53bba9..26a63db1 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Control/WebViewer.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/View/Control/WebViewer.xaml.cs
@@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.Messaging;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Web.WebView2.Core;
+using Snap.Hutao.Control.Extension;
using Snap.Hutao.Message;
using Snap.Hutao.Service.Notification;
using Snap.Hutao.Service.User;
@@ -94,53 +95,52 @@ internal partial class WebViewer : UserControl, IRecipient
return;
}
- // TODO: replace with .NET 8 UnsafeAccessor
- try
+ if (WebView.IsDisposed())
{
- CoreWebView2? coreWebView2 = WebView?.CoreWebView2;
-
- if (coreWebView2 is null)
- {
- return;
- }
-
- if (SourceProvider is not null)
- {
- if (UserAndUid.TryFromUser(user, out UserAndUid? userAndUid))
- {
- string source = SourceProvider.GetSource(userAndUid);
- if (!string.IsNullOrEmpty(source))
- {
- try
- {
- await coreWebView2.Profile.ClearBrowsingDataAsync();
- }
- catch (InvalidCastException)
- {
- infoBarService.Warning(SH.ViewControlWebViewerCoreWebView2ProfileQueryInterfaceFailed);
- await coreWebView2.DeleteCookiesAsync(userAndUid.IsOversea).ConfigureAwait(true);
- }
-
- CoreWebView2Navigator navigator = new(coreWebView2);
- await navigator.NavigateAsync("about:blank").ConfigureAwait(true);
-
- coreWebView2
- .SetCookie(user.CookieToken, user.LToken, userAndUid.IsOversea)
- .SetMobileUserAgent(userAndUid.IsOversea);
- jsBridge?.Detach();
- jsBridge = SourceProvider.CreateJSBridge(serviceProvider, coreWebView2, userAndUid);
-
- await navigator.NavigateAsync(source).ConfigureAwait(true);
- }
- }
- else
- {
- infoBarService.Warning(SH.MustSelectUserAndUid);
- }
- }
+ return;
}
- catch (ObjectDisposedException)
+
+ CoreWebView2? coreWebView2 = WebView?.CoreWebView2;
+
+ if (coreWebView2 is null)
{
+ return;
+ }
+
+ if (SourceProvider is null)
+ {
+ return;
+ }
+
+ if (!UserAndUid.TryFromUser(user, out UserAndUid? userAndUid))
+ {
+ infoBarService.Warning(SH.MustSelectUserAndUid);
+ return;
+ }
+
+ string source = SourceProvider.GetSource(userAndUid);
+ if (!string.IsNullOrEmpty(source))
+ {
+ try
+ {
+ await coreWebView2.Profile.ClearBrowsingDataAsync();
+ }
+ catch (InvalidCastException)
+ {
+ infoBarService.Warning(SH.ViewControlWebViewerCoreWebView2ProfileQueryInterfaceFailed);
+ await coreWebView2.DeleteCookiesAsync(userAndUid.IsOversea).ConfigureAwait(true);
+ }
+
+ CoreWebView2Navigator navigator = new(coreWebView2);
+ await navigator.NavigateAsync("about:blank").ConfigureAwait(true);
+
+ coreWebView2
+ .SetCookie(user.CookieToken, user.LToken, userAndUid.IsOversea)
+ .SetMobileUserAgent(userAndUid.IsOversea);
+ jsBridge?.Detach();
+ jsBridge = SourceProvider.CreateJSBridge(serviceProvider, coreWebView2, userAndUid);
+
+ await navigator.NavigateAsync(source).ConfigureAwait(true);
}
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/ISupportLoginByWebView.cs b/src/Snap.Hutao/Snap.Hutao/View/Page/ISupportLoginByWebView.cs
index 203ca5a1..a6101a73 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/ISupportLoginByWebView.cs
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/ISupportLoginByWebView.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
+using Snap.Hutao.Control.Extension;
using Snap.Hutao.Service.Navigation;
using Snap.Hutao.Service.Notification;
using Snap.Hutao.Service.User;
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarProperty.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarProperty.cs
index fd4ad553..6c35eba6 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarProperty.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarProperty.cs
@@ -6,6 +6,7 @@ using Microsoft.UI.Xaml.Media;
using Snap.Hutao.Control.Collection.Alternating;
using Snap.Hutao.Model;
using Snap.Hutao.Model.Intrinsic;
+using System.Collections.Frozen;
using System.Collections.Immutable;
namespace Snap.Hutao.ViewModel.AvatarProperty;
@@ -16,8 +17,7 @@ namespace Snap.Hutao.ViewModel.AvatarProperty;
[HighQuality]
internal sealed class AvatarProperty : ObservableObject, INameIcon, IAlternatingItem
{
- // TODO: use FrozenDictionary
- private static readonly ImmutableDictionary PropertyIcons = new Dictionary()
+ private static readonly FrozenDictionary PropertyIcons = new Dictionary()
{
[FightProperty.FIGHT_PROP_SKILL_CD_MINUS_RATIO] = Web.HutaoEndpoints.StaticFile("Property", "UI_Icon_CDReduce.png").ToUri(),
[FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY] = Web.HutaoEndpoints.StaticFile("Property", "UI_Icon_ChargeEfficiency.png").ToUri(),
@@ -37,7 +37,7 @@ internal sealed class AvatarProperty : ObservableObject, INameIcon, IAlternating
[FightProperty.FIGHT_PROP_MAX_HP] = Web.HutaoEndpoints.StaticFile("Property", "UI_Icon_MaxHp.png").ToUri(),
[FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT] = Web.HutaoEndpoints.StaticFile("Property", "UI_Icon_PhysicalAttackUp.png").ToUri(),
[FightProperty.FIGHT_PROP_SHIELD_COST_MINUS_RATIO] = Web.HutaoEndpoints.StaticFile("Property", "UI_Icon_ShieldCostMinus.png").ToUri(),
- }.ToImmutableDictionary();
+ }.ToFrozenDictionary();
private Brush? background;
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/HoyolabCoreWebView2Extension.cs b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/HoyolabCoreWebView2Extension.cs
index 7131fdcc..a9d97c86 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Bridge/HoyolabCoreWebView2Extension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Bridge/HoyolabCoreWebView2Extension.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using Microsoft.Web.WebView2.Core;
+using Snap.Hutao.Control.Extension;
using Snap.Hutao.Web.Hoyolab;
namespace Snap.Hutao.Web.Bridge;
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/Announcement.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/Announcement.cs
index cc3429fd..e9b03136 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/Announcement.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Hk4e/Common/Announcement/Announcement.cs
@@ -70,7 +70,7 @@ internal sealed class Announcement : AnnouncementContent
{
// TODO: validate correctness
// UTC+8
- DateTimeOffset currentTime = DateTimeOffset.UtcNow.AddHours(8);
+ DateTimeOffset currentTime = DateTimeOffset.Now;
TimeSpan current = currentTime - StartTime;
TimeSpan total = EndTime - StartTime;
return current / total;