From a9fd624742903083c9ab177627c5c2c09d1958c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Tue, 7 Apr 2026 09:52:37 +0200 Subject: [PATCH] 2 second webview cache. --- Wino.Mail.WinUI/Controls/WebViewEditorControl.cs | 4 ++-- Wino.Mail.WinUI/Extensions/WebViewExtensions.cs | 15 +++++++++++++++ Wino.Mail.WinUI/Views/Mail/MailListPage.xaml.cs | 10 ++++++++-- .../Views/Mail/MailRenderingPage.xaml.cs | 12 +++++++++--- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Wino.Mail.WinUI/Controls/WebViewEditorControl.cs b/Wino.Mail.WinUI/Controls/WebViewEditorControl.cs index 84206270..92eafafe 100644 --- a/Wino.Mail.WinUI/Controls/WebViewEditorControl.cs +++ b/Wino.Mail.WinUI/Controls/WebViewEditorControl.cs @@ -339,10 +339,10 @@ public sealed partial class WebViewEditorControl : Control, IDisposable, IEditor return; } - WebViewExtensions.EnsureWebView2Environment(); + var sharedEnvironment = await WebViewExtensions.GetSharedEnvironmentAsync(); _chromium.CoreWebView2Initialized -= ChromiumInitialized; _chromium.CoreWebView2Initialized += ChromiumInitialized; - await _chromium.EnsureCoreWebView2Async(); + await _chromium.EnsureCoreWebView2Async(sharedEnvironment); } private Task EnsureEditorReadyAsync() diff --git a/Wino.Mail.WinUI/Extensions/WebViewExtensions.cs b/Wino.Mail.WinUI/Extensions/WebViewExtensions.cs index 0682cbf6..bb8d94c3 100644 --- a/Wino.Mail.WinUI/Extensions/WebViewExtensions.cs +++ b/Wino.Mail.WinUI/Extensions/WebViewExtensions.cs @@ -1,11 +1,15 @@ using System; +using System.Runtime.InteropServices.WindowsRuntime; using System.Threading.Tasks; +using Microsoft.Web.WebView2.Core; namespace Wino.Mail.WinUI.Extensions; public static class WebViewExtensions { + private static readonly object _environmentLock = new(); private static bool _environmentInitialized; + private static Task? _sharedEnvironmentTask; /// /// Sets WebView2 environment variables once per process. @@ -22,6 +26,17 @@ public static class WebViewExtensions _environmentInitialized = true; } + public static Task GetSharedEnvironmentAsync() + { + EnsureWebView2Environment(); + + lock (_environmentLock) + { + _sharedEnvironmentTask ??= CoreWebView2Environment.CreateAsync().AsTask(); + return _sharedEnvironmentTask; + } + } + /// /// Executes a script function in the WebView2 control. /// diff --git a/Wino.Mail.WinUI/Views/Mail/MailListPage.xaml.cs b/Wino.Mail.WinUI/Views/Mail/MailListPage.xaml.cs index 1b4d4d30..38993a19 100644 --- a/Wino.Mail.WinUI/Views/Mail/MailListPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/Mail/MailListPage.xaml.cs @@ -51,7 +51,8 @@ public sealed partial class MailListPage : MailListPageAbstract, ITitleBarSearchHost { private const double RENDERING_COLUMN_MIN_WIDTH = 375; - private const int IDLE_NAVIGATION_DELAY_MS = 120; + private const int SELECTION_SETTLE_DELAY_MS = 120; + private const int RENDERING_FRAME_RELEASE_DELAY_MS = 2000; private int _idleNavigationRequestVersion = 0; private IStatePersistanceService StatePersistenceService { get; } = WinoApplication.Current.Services.GetService() ?? throw new Exception($"Can't resolve {nameof(KeyPressService)}"); @@ -370,7 +371,7 @@ public sealed partial class MailListPage : MailListPageAbstract, { int requestVersion = ++_idleNavigationRequestVersion; - await Task.Delay(IDLE_NAVIGATION_DELAY_MS); + await Task.Delay(SELECTION_SETTLE_DELAY_MS); if (requestVersion != _idleNavigationRequestVersion) return; if (ViewModel.MailCollection.SelectedItemsCount != 0) return; @@ -380,6 +381,11 @@ public sealed partial class MailListPage : MailListPageAbstract, WeakReferenceMessenger.Default.Send(new CancelRenderingContentRequested()); } + await Task.Delay(RENDERING_FRAME_RELEASE_DELAY_MS); + + if (requestVersion != _idleNavigationRequestVersion) return; + if (ViewModel.MailCollection.SelectedItemsCount != 0) return; + // Ensure rendering frame actually navigates away from Compose/Rendering pages. // Otherwise those pages keep their messenger registrations alive. ViewModel.NavigationService.Navigate(WinoPage.IdlePage, null, NavigationReferenceFrame.RenderingFrame, NavigationTransitionType.DrillIn); diff --git a/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml.cs b/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml.cs index d6f8277d..24ac905c 100644 --- a/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml.cs @@ -85,6 +85,12 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract, await UpdateEditorThemeAsync(); } + private async Task EnsureChromiumInitializedAsync() + { + var sharedEnvironment = await WebViewExtensions.GetSharedEnvironmentAsync(); + await Chromium.EnsureCoreWebView2Async(sharedEnvironment); + } + private async Task RenderInternalAsync(string htmlBody) { isRenderingInProgress = true; @@ -128,7 +134,7 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract, // Ensure WebView2 is fully initialized before first render. // OnNavigatedTo starts initialization fire-and-forget; this await // guarantees the core is ready before we invoke any script. - await Chromium.EnsureCoreWebView2Async(); + await EnsureChromiumInitializedAsync(); if (message == null || string.IsNullOrEmpty(message.HtmlBody)) { @@ -274,7 +280,7 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract, RendererCommandBar.IsAIActionsEnabled = false; Chromium.CoreWebView2Initialized -= CoreWebViewInitialized; Chromium.CoreWebView2Initialized += CoreWebViewInitialized; - _ = Chromium.EnsureCoreWebView2Async(); + _ = EnsureChromiumInitializedAsync(); base.OnNavigatedTo(e); @@ -310,7 +316,7 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract, async void IRecipient.Receive(CancelRenderingContentRequested message) { - await Chromium.EnsureCoreWebView2Async(); + await EnsureChromiumInitializedAsync(); if (!isRenderingInProgress) {