2 second webview cache.

This commit is contained in:
Burak Kaan Köse
2026-04-07 09:52:37 +02:00
parent 9855170b2e
commit a9fd624742
4 changed files with 34 additions and 7 deletions
@@ -339,10 +339,10 @@ public sealed partial class WebViewEditorControl : Control, IDisposable, IEditor
return; return;
} }
WebViewExtensions.EnsureWebView2Environment(); var sharedEnvironment = await WebViewExtensions.GetSharedEnvironmentAsync();
_chromium.CoreWebView2Initialized -= ChromiumInitialized; _chromium.CoreWebView2Initialized -= ChromiumInitialized;
_chromium.CoreWebView2Initialized += ChromiumInitialized; _chromium.CoreWebView2Initialized += ChromiumInitialized;
await _chromium.EnsureCoreWebView2Async(); await _chromium.EnsureCoreWebView2Async(sharedEnvironment);
} }
private Task EnsureEditorReadyAsync() private Task EnsureEditorReadyAsync()
@@ -1,11 +1,15 @@
using System; using System;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Web.WebView2.Core;
namespace Wino.Mail.WinUI.Extensions; namespace Wino.Mail.WinUI.Extensions;
public static class WebViewExtensions public static class WebViewExtensions
{ {
private static readonly object _environmentLock = new();
private static bool _environmentInitialized; private static bool _environmentInitialized;
private static Task<CoreWebView2Environment>? _sharedEnvironmentTask;
/// <summary> /// <summary>
/// Sets WebView2 environment variables once per process. /// Sets WebView2 environment variables once per process.
@@ -22,6 +26,17 @@ public static class WebViewExtensions
_environmentInitialized = true; _environmentInitialized = true;
} }
public static Task<CoreWebView2Environment> GetSharedEnvironmentAsync()
{
EnsureWebView2Environment();
lock (_environmentLock)
{
_sharedEnvironmentTask ??= CoreWebView2Environment.CreateAsync().AsTask();
return _sharedEnvironmentTask;
}
}
/// <summary> /// <summary>
/// Executes a script function in the WebView2 control. /// Executes a script function in the WebView2 control.
/// </summary> /// </summary>
@@ -51,7 +51,8 @@ public sealed partial class MailListPage : MailListPageAbstract,
ITitleBarSearchHost ITitleBarSearchHost
{ {
private const double RENDERING_COLUMN_MIN_WIDTH = 375; 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 int _idleNavigationRequestVersion = 0;
private IStatePersistanceService StatePersistenceService { get; } = WinoApplication.Current.Services.GetService<IStatePersistanceService>() ?? throw new Exception($"Can't resolve {nameof(KeyPressService)}"); private IStatePersistanceService StatePersistenceService { get; } = WinoApplication.Current.Services.GetService<IStatePersistanceService>() ?? throw new Exception($"Can't resolve {nameof(KeyPressService)}");
@@ -370,7 +371,7 @@ public sealed partial class MailListPage : MailListPageAbstract,
{ {
int requestVersion = ++_idleNavigationRequestVersion; int requestVersion = ++_idleNavigationRequestVersion;
await Task.Delay(IDLE_NAVIGATION_DELAY_MS); await Task.Delay(SELECTION_SETTLE_DELAY_MS);
if (requestVersion != _idleNavigationRequestVersion) return; if (requestVersion != _idleNavigationRequestVersion) return;
if (ViewModel.MailCollection.SelectedItemsCount != 0) return; if (ViewModel.MailCollection.SelectedItemsCount != 0) return;
@@ -380,6 +381,11 @@ public sealed partial class MailListPage : MailListPageAbstract,
WeakReferenceMessenger.Default.Send(new CancelRenderingContentRequested()); 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. // Ensure rendering frame actually navigates away from Compose/Rendering pages.
// Otherwise those pages keep their messenger registrations alive. // Otherwise those pages keep their messenger registrations alive.
ViewModel.NavigationService.Navigate(WinoPage.IdlePage, null, NavigationReferenceFrame.RenderingFrame, NavigationTransitionType.DrillIn); ViewModel.NavigationService.Navigate(WinoPage.IdlePage, null, NavigationReferenceFrame.RenderingFrame, NavigationTransitionType.DrillIn);
@@ -85,6 +85,12 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
await UpdateEditorThemeAsync(); await UpdateEditorThemeAsync();
} }
private async Task EnsureChromiumInitializedAsync()
{
var sharedEnvironment = await WebViewExtensions.GetSharedEnvironmentAsync();
await Chromium.EnsureCoreWebView2Async(sharedEnvironment);
}
private async Task RenderInternalAsync(string htmlBody) private async Task RenderInternalAsync(string htmlBody)
{ {
isRenderingInProgress = true; isRenderingInProgress = true;
@@ -128,7 +134,7 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
// Ensure WebView2 is fully initialized before first render. // Ensure WebView2 is fully initialized before first render.
// OnNavigatedTo starts initialization fire-and-forget; this await // OnNavigatedTo starts initialization fire-and-forget; this await
// guarantees the core is ready before we invoke any script. // guarantees the core is ready before we invoke any script.
await Chromium.EnsureCoreWebView2Async(); await EnsureChromiumInitializedAsync();
if (message == null || string.IsNullOrEmpty(message.HtmlBody)) if (message == null || string.IsNullOrEmpty(message.HtmlBody))
{ {
@@ -274,7 +280,7 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
RendererCommandBar.IsAIActionsEnabled = false; RendererCommandBar.IsAIActionsEnabled = false;
Chromium.CoreWebView2Initialized -= CoreWebViewInitialized; Chromium.CoreWebView2Initialized -= CoreWebViewInitialized;
Chromium.CoreWebView2Initialized += CoreWebViewInitialized; Chromium.CoreWebView2Initialized += CoreWebViewInitialized;
_ = Chromium.EnsureCoreWebView2Async(); _ = EnsureChromiumInitializedAsync();
base.OnNavigatedTo(e); base.OnNavigatedTo(e);
@@ -310,7 +316,7 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
async void IRecipient<CancelRenderingContentRequested>.Receive(CancelRenderingContentRequested message) async void IRecipient<CancelRenderingContentRequested>.Receive(CancelRenderingContentRequested message)
{ {
await Chromium.EnsureCoreWebView2Async(); await EnsureChromiumInitializedAsync();
if (!isRenderingInProgress) if (!isRenderingInProgress)
{ {