From 4b313b134e84b5d1e71d9b300c43751ee788d14d Mon Sep 17 00:00:00 2001 From: fanbook-wangdage <124357765+fanbook-wangdage@users.noreply.github.com> Date: Sat, 7 Feb 2026 13:07:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Emsi=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E7=95=8C=E9=9D=A2=EF=BC=8C=E4=BF=AE=E5=A4=8DWebView2=E6=9D=83?= =?UTF-8?q?=E9=99=90=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BF=AE=E5=A4=8D=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E6=9C=8D=E5=8A=A1=E5=99=A8=E6=97=B6=E4=BC=9A=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E7=AD=89=E5=BE=85=E8=BF=9B=E7=A8=8B=E9=80=80=E5=87=BA?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C=E4=B8=BA=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BC=93=E5=AD=98=E6=9D=A5=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E9=A2=91=E7=B9=81=E5=88=87=E6=8D=A2=E9=A1=B5=E9=9D=A2=E6=97=B6?= =?UTF-8?q?=E7=9A=84=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Snap.Hutao.Installer/Package.en-us.wxl | 3 +++ .../Snap.Hutao.Installer/Package.wxs | 23 ++++++++++++++----- .../Snap.Hutao.Installer/Package.zh-cn.wxl | 11 +++++++++ .../Snap.Hutao.Installer.wixproj | 13 +++++++++-- .../Snap.Hutao/Core/HutaoRuntime.cs | 11 ++++++++- .../Snap.Hutao/Package.appxmanifest | 2 +- .../Invoker/AbstractLaunchExecutionInvoker.cs | 10 ++++---- .../ConvertOnlyLaunchExecutionInvoker.cs | 5 +++- .../Snap.Hutao/UI/Xaml/Control/ScopedPage.cs | 11 ++++++++- .../Snap.Hutao/UI/Xaml/View/MainView.xaml | 7 ++++-- .../WebView2/CompactWebView2Window.xaml.cs | 6 +++-- .../Window/WebView2/WebView2Window.xaml.cs | 6 +++-- 12 files changed, 86 insertions(+), 22 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao.Installer/Package.zh-cn.wxl diff --git a/src/Snap.Hutao/Snap.Hutao.Installer/Package.en-us.wxl b/src/Snap.Hutao/Snap.Hutao.Installer/Package.en-us.wxl index 7fa02fa..968a817 100644 --- a/src/Snap.Hutao/Snap.Hutao.Installer/Package.en-us.wxl +++ b/src/Snap.Hutao/Snap.Hutao.Installer/Package.en-us.wxl @@ -4,5 +4,8 @@ This file contains the declaration of all the localizable strings. + + + diff --git a/src/Snap.Hutao/Snap.Hutao.Installer/Package.wxs b/src/Snap.Hutao/Snap.Hutao.Installer/Package.wxs index 77afbb1..40f0c13 100644 --- a/src/Snap.Hutao/Snap.Hutao.Installer/Package.wxs +++ b/src/Snap.Hutao/Snap.Hutao.Installer/Package.wxs @@ -1,21 +1,32 @@ - + - + + + + - - + - - + + + + + + + + + diff --git a/src/Snap.Hutao/Snap.Hutao.Installer/Package.zh-cn.wxl b/src/Snap.Hutao/Snap.Hutao.Installer/Package.zh-cn.wxl new file mode 100644 index 0000000..ef545db --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao.Installer/Package.zh-cn.wxl @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/src/Snap.Hutao/Snap.Hutao.Installer/Snap.Hutao.Installer.wixproj b/src/Snap.Hutao/Snap.Hutao.Installer/Snap.Hutao.Installer.wixproj index ee8d9b2..f388f64 100644 --- a/src/Snap.Hutao/Snap.Hutao.Installer/Snap.Hutao.Installer.wixproj +++ b/src/Snap.Hutao/Snap.Hutao.Installer/Snap.Hutao.Installer.wixproj @@ -4,6 +4,8 @@ x64 net10.0-windows10.0.26100.0 Release + zh-CN + zh-CN;en-US @@ -11,7 +13,7 @@ - + MainAppComponents INSTALLFOLDER true @@ -19,6 +21,13 @@ true - + + + + + + + + diff --git a/src/Snap.Hutao/Snap.Hutao/Core/HutaoRuntime.cs b/src/Snap.Hutao/Snap.Hutao/Core/HutaoRuntime.cs index 44943b1..4b1cb93 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/HutaoRuntime.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/HutaoRuntime.cs @@ -33,6 +33,8 @@ internal static class HutaoRuntime public static WebView2Version WebView2Version { get; } = InitializeWebView2(); + public static string WebView2UserDataDirectory { get; } = InitializeWebView2UserDataDirectory(); + // ⚠️ 延迟初始化以避免循环依赖 private static readonly Lazy LazyIsProcessElevated = new(GetIsProcessElevated); @@ -144,6 +146,13 @@ internal static class HutaoRuntime return cacheDir; } + private static string InitializeWebView2UserDataDirectory() + { + string directory = Path.Combine(LocalCacheDirectory, "WebView2"); + Directory.CreateDirectory(directory); + return directory; + } + private static bool CheckAppNotificationEnabled() { try @@ -226,4 +235,4 @@ internal static class HutaoRuntime return new(string.Empty, SH.CoreWebView2HelperVersionUndetected, false); } } -} \ No newline at end of file +} diff --git a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest index e5ba27d..5a2cc27 100644 --- a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest +++ b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest @@ -13,7 +13,7 @@ + Version="1.18.2.0" /> Snap Hutao diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Invoker/AbstractLaunchExecutionInvoker.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Invoker/AbstractLaunchExecutionInvoker.cs index 7e649e9..10ebc07 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Invoker/AbstractLaunchExecutionInvoker.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Invoker/AbstractLaunchExecutionInvoker.cs @@ -21,6 +21,8 @@ internal abstract class AbstractLaunchExecutionInvoker private bool invoked; protected ImmutableArray Handlers { get; init; } + protected virtual bool ShouldWaitForProcessExit { get => true; } + protected virtual bool ShouldSpinWaitGameExitAfterInvoke { get => true; } public static bool Invoking() { @@ -40,7 +42,7 @@ internal abstract class AbstractLaunchExecutionInvoker finally { Invokers.TryRemove(this, out _); - if (!Invoking()) + if (!Invoking() && ShouldSpinWaitGameExitAfterInvoke) { await GameLifeCycle.SpinWaitGameExitAsync(taskContext).ConfigureAwait(false); } @@ -132,7 +134,7 @@ internal abstract class AbstractLaunchExecutionInvoker } // 只有在没有启用Island且进程存在时才等待退出 - if (process is { IsRunning: true }) + if (ShouldWaitForProcessExit && process is { IsRunning: true }) { progress.Report(new(SH.ServiceGameLaunchPhaseWaitingProcessExit)); try @@ -148,7 +150,7 @@ internal abstract class AbstractLaunchExecutionInvoker return; } } - else if (beforeContext.LaunchOptions.IsIslandEnabled.Value) + else if (ShouldWaitForProcessExit && beforeContext.LaunchOptions.IsIslandEnabled.Value) { progress.Report(new(SH.ServiceGameLaunchPhaseWaitingProcessExit)); await taskContext.SwitchToBackgroundAsync(); @@ -170,4 +172,4 @@ internal abstract class AbstractLaunchExecutionInvoker } } } -} \ No newline at end of file +} diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Invoker/ConvertOnlyLaunchExecutionInvoker.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Invoker/ConvertOnlyLaunchExecutionInvoker.cs index 39f5200..4eb9557 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Invoker/ConvertOnlyLaunchExecutionInvoker.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Invoker/ConvertOnlyLaunchExecutionInvoker.cs @@ -9,6 +9,9 @@ namespace Snap.Hutao.Service.Game.Launching.Invoker; internal sealed class ConvertOnlyLaunchExecutionInvoker : AbstractLaunchExecutionInvoker { + protected override bool ShouldWaitForProcessExit { get => false; } + protected override bool ShouldSpinWaitGameExitAfterInvoke { get => false; } + public ConvertOnlyLaunchExecutionInvoker() { Handlers = @@ -24,4 +27,4 @@ internal sealed class ConvertOnlyLaunchExecutionInvoker : AbstractLaunchExecutio // Since this invoker is only for conversion, we do not actually need the process. return default; } -} \ No newline at end of file +} diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/ScopedPage.cs b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/ScopedPage.cs index bf1ec1b..0fe8470 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/ScopedPage.cs +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/ScopedPage.cs @@ -20,6 +20,8 @@ internal partial class ScopedPage : Page protected ScopedPage() { + // Allow a small set of recent pages to be cached to reduce navigation stutter. + NavigationCacheMode = NavigationCacheMode.Enabled; // Events/Override Methods order // ---------------------------------------------------------------------- // Page Navigation methods: @@ -103,6 +105,13 @@ internal partial class ScopedPage : Page private void OnUnloaded(object sender, RoutedEventArgs e) { + // When navigation cache is enabled, the page instance is reused. + // Do not tear down DataContext/scope here to avoid invalid state on return. + if (NavigationCacheMode != NavigationCacheMode.Disabled) + { + return; + } + // Cancel all tasks executed by the view model viewCts.Cancel(); @@ -140,4 +149,4 @@ internal partial class ScopedPage : Page Unloaded -= OnUnloaded; } -} \ No newline at end of file +} diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/MainView.xaml b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/MainView.xaml index 2ab72fb..d007f5a 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/MainView.xaml +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/MainView.xaml @@ -264,10 +264,13 @@ - + - \ No newline at end of file + diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Window/WebView2/CompactWebView2Window.xaml.cs b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Window/WebView2/CompactWebView2Window.xaml.cs index 67ddaa4..82552e2 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Window/WebView2/CompactWebView2Window.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Window/WebView2/CompactWebView2Window.xaml.cs @@ -6,6 +6,7 @@ using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Input; using Microsoft.Web.WebView2.Core; +using Snap.Hutao.Core; using Snap.Hutao.Core.Logging; using Snap.Hutao.Core.Setting; using Snap.Hutao.UI.Input.LowLevel; @@ -337,7 +338,8 @@ internal sealed partial class CompactWebView2Window : Microsoft.UI.Xaml.Window, { AdditionalBrowserArguments = "--do-not-de-elevate --autoplay-policy=no-user-gesture-required", }; - CoreWebView2Environment environment = await CoreWebView2Environment.CreateWithOptionsAsync(null, null, options); + string userDataFolder = HutaoRuntime.WebView2UserDataDirectory; + CoreWebView2Environment environment = await CoreWebView2Environment.CreateWithOptionsAsync(null, userDataFolder, options); await WebView.EnsureCoreWebView2Async(environment); } catch (SEHException ex) @@ -430,4 +432,4 @@ internal sealed partial class CompactWebView2Window : Microsoft.UI.Xaml.Window, RefreshButton.Command = RefreshCommand; ProgressRing.Visibility = Visibility.Collapsed; } -} \ No newline at end of file +} diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Window/WebView2/WebView2Window.xaml.cs b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Window/WebView2/WebView2Window.xaml.cs index 211f179..d0ab950 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Window/WebView2/WebView2Window.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Window/WebView2/WebView2Window.xaml.cs @@ -5,6 +5,7 @@ using Microsoft.UI; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.Web.WebView2.Core; +using Snap.Hutao.Core; using Snap.Hutao.Core.Logging; using Snap.Hutao.UI.Windowing; using Snap.Hutao.UI.Windowing.Abstraction; @@ -154,7 +155,8 @@ internal sealed partial class WebView2Window : Microsoft.UI.Xaml.Window, { AdditionalBrowserArguments = "--do-not-de-elevate", }; - CoreWebView2Environment environment = await CoreWebView2Environment.CreateWithOptionsAsync(null, null, options); + string userDataFolder = HutaoRuntime.WebView2UserDataDirectory; + CoreWebView2Environment environment = await CoreWebView2Environment.CreateWithOptionsAsync(null, userDataFolder, options); await WebView.EnsureCoreWebView2Async(environment); } catch (SEHException) @@ -213,4 +215,4 @@ internal sealed partial class WebView2Window : Microsoft.UI.Xaml.Window, { contentProvider.ActualTheme = sender.ActualTheme; } -} \ No newline at end of file +}