Editor optimizations
This commit is contained in:
@@ -133,6 +133,7 @@ public sealed partial class WebViewEditorControl : Control, IDisposable
|
||||
private const string PART_WebView = "WebView";
|
||||
private WebView2 _chromium = null!;
|
||||
private bool _disposedValue;
|
||||
private bool? _lastAppliedDarkTheme;
|
||||
private readonly TaskCompletionSource<bool> _domLoadedTask = new();
|
||||
|
||||
public WebViewEditorControl()
|
||||
@@ -153,8 +154,9 @@ public sealed partial class WebViewEditorControl : Control, IDisposable
|
||||
|
||||
private async Task InitializeComponent()
|
||||
{
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_DEFAULT_BACKGROUND_COLOR", "00FFFFFF");
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--enable-features=OverlayScrollbar,msOverlayScrollbarWinStyle,msOverlayScrollbarWinStyleAnimation");
|
||||
WebViewExtensions.EnsureWebView2Environment();
|
||||
|
||||
_chromium.CoreWebView2Initialized -= ChromiumInitialized;
|
||||
_chromium.CoreWebView2Initialized += ChromiumInitialized;
|
||||
|
||||
await _chromium.EnsureCoreWebView2Async();
|
||||
@@ -218,7 +220,7 @@ public sealed partial class WebViewEditorControl : Control, IDisposable
|
||||
int composerFontSize = _preferencesService.ComposerFontSize;
|
||||
var readerFont = _preferencesService.ReaderFont;
|
||||
int readerFontSize = _preferencesService.ReaderFontSize;
|
||||
return await _chromium.ExecuteScriptFunctionAsync("initializeJodit", false,
|
||||
return await _chromium.ExecuteScriptFunctionAsync("initializeJodit",
|
||||
JsonSerializer.Serialize(fonts, BasicTypesJsonContext.Default.ListString),
|
||||
JsonSerializer.Serialize(composerFont, BasicTypesJsonContext.Default.String),
|
||||
JsonSerializer.Serialize(composerFontSize, BasicTypesJsonContext.Default.Int32),
|
||||
@@ -233,16 +235,24 @@ public sealed partial class WebViewEditorControl : Control, IDisposable
|
||||
_chromium.CoreWebView2.SetVirtualHostNameToFolderMapping("app.editor", editorBundlePath, CoreWebView2HostResourceAccessKind.Allow);
|
||||
_chromium.Source = new Uri("https://app.editor/editor.html");
|
||||
|
||||
_chromium.CoreWebView2.DOMContentLoaded -= DomLoaded;
|
||||
_chromium.CoreWebView2.DOMContentLoaded += DomLoaded;
|
||||
|
||||
_chromium.CoreWebView2.WebMessageReceived -= ScriptMessageReceived;
|
||||
_chromium.CoreWebView2.WebMessageReceived += ScriptMessageReceived;
|
||||
}
|
||||
|
||||
public async Task UpdateEditorThemeAsync()
|
||||
public async Task UpdateEditorThemeAsync(bool force = false)
|
||||
{
|
||||
await _domLoadedTask.Task;
|
||||
|
||||
if (IsEditorDarkMode)
|
||||
var isDark = IsEditorDarkMode;
|
||||
|
||||
if (!force && _lastAppliedDarkTheme == isDark) return;
|
||||
|
||||
_lastAppliedDarkTheme = isDark;
|
||||
|
||||
if (isDark)
|
||||
{
|
||||
_chromium.CoreWebView2.Profile.PreferredColorScheme = CoreWebView2PreferredColorScheme.Dark;
|
||||
await _chromium.ExecuteScriptFunctionSafeAsync("SetDarkEditor");
|
||||
|
||||
@@ -5,16 +5,34 @@ namespace Wino.Mail.WinUI.Extensions;
|
||||
|
||||
public static class WebViewExtensions
|
||||
{
|
||||
private static bool _environmentInitialized;
|
||||
|
||||
/// <summary>
|
||||
/// Sets WebView2 environment variables once per process.
|
||||
/// Must be called before any WebView2 is initialized.
|
||||
/// </summary>
|
||||
public static void EnsureWebView2Environment()
|
||||
{
|
||||
if (_environmentInitialized) return;
|
||||
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_DEFAULT_BACKGROUND_COLOR", "00FFFFFF");
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS",
|
||||
"--enable-features=OverlayScrollbar,msOverlayScrollbarWinStyle,msOverlayScrollbarWinStyleAnimation,msWebView2CodeCache");
|
||||
|
||||
_environmentInitialized = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a script function in the WebView2 control.
|
||||
/// </summary>
|
||||
/// <param name="isChromiumDisposed">Weird parameter that needed in mailRendering page. TODO: should be reconsidered.</param>
|
||||
/// <param name="parameters">Parameters should be serialized to json</param>
|
||||
public static async Task<string> ExecuteScriptFunctionAsync(this Microsoft.UI.Xaml.Controls.WebView2 Chromium, string functionName, bool isChromiumDisposed = false, params string[] parameters)
|
||||
public static async Task<string> ExecuteScriptFunctionAsync(this Microsoft.UI.Xaml.Controls.WebView2 Chromium, string functionName, params string[] parameters)
|
||||
{
|
||||
if (Chromium?.CoreWebView2 == null) return string.Empty;
|
||||
|
||||
string script = functionName + "(" + string.Join(", ", parameters) + ");";
|
||||
|
||||
return isChromiumDisposed ? string.Empty : await Chromium.ExecuteScriptAsync(script);
|
||||
return await Chromium.ExecuteScriptAsync(script);
|
||||
}
|
||||
|
||||
public static async Task<string> ExecuteScriptFunctionSafeAsync(this Microsoft.UI.Xaml.Controls.WebView2 Chromium, string functionName, params string[] parameters)
|
||||
|
||||
@@ -24,14 +24,12 @@ public sealed partial class EventDetailsPage : EventDetailsPageAbstract,
|
||||
{
|
||||
private readonly IPreferencesService _preferencesService = App.Current.Services.GetService<IPreferencesService>()!;
|
||||
private TaskCompletionSource<bool> DOMLoadedTask = new TaskCompletionSource<bool>();
|
||||
private bool isChromiumDisposed = false;
|
||||
|
||||
public EventDetailsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_DEFAULT_BACKGROUND_COLOR", "00FFFFFF");
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--enable-features=OverlayScrollbar,msOverlayScrollbarWinStyle,msOverlayScrollbarWinStyleAnimation,msWebView2CodeCache");
|
||||
WebViewExtensions.EnsureWebView2Environment();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
@@ -91,11 +89,11 @@ public sealed partial class EventDetailsPage : EventDetailsPageAbstract,
|
||||
|
||||
if (string.IsNullOrEmpty(description))
|
||||
{
|
||||
await EventDetailsWebView.ExecuteScriptFunctionAsync("RenderHTML", isChromiumDisposed, JsonSerializer.Serialize(" ", BasicTypesJsonContext.Default.String));
|
||||
await EventDetailsWebView.ExecuteScriptFunctionAsync("RenderHTML", JsonSerializer.Serialize(" ", BasicTypesJsonContext.Default.String));
|
||||
}
|
||||
else
|
||||
{
|
||||
await EventDetailsWebView.ExecuteScriptFunctionAsync("RenderHTML", isChromiumDisposed,
|
||||
await EventDetailsWebView.ExecuteScriptFunctionAsync("RenderHTML",
|
||||
JsonSerializer.Serialize(description, BasicTypesJsonContext.Default.String),
|
||||
JsonSerializer.Serialize(true, BasicTypesJsonContext.Default.Boolean));
|
||||
}
|
||||
@@ -138,8 +136,6 @@ public sealed partial class EventDetailsPage : EventDetailsPageAbstract,
|
||||
EventDetailsWebView.CoreWebView2.NewWindowRequested -= WindowRequested;
|
||||
}
|
||||
|
||||
isChromiumDisposed = true;
|
||||
|
||||
EventDetailsWebView.Close();
|
||||
}
|
||||
|
||||
@@ -150,34 +146,23 @@ public sealed partial class EventDetailsPage : EventDetailsPageAbstract,
|
||||
if (ViewModel.IsDarkWebviewRenderer)
|
||||
{
|
||||
EventDetailsWebView.CoreWebView2.Profile.PreferredColorScheme = CoreWebView2PreferredColorScheme.Dark;
|
||||
await InvokeScriptSafeAsync("SetDarkEditor();");
|
||||
await EventDetailsWebView.ExecuteScriptSafeAsync("SetDarkEditor();");
|
||||
}
|
||||
else
|
||||
{
|
||||
EventDetailsWebView.CoreWebView2.Profile.PreferredColorScheme = CoreWebView2PreferredColorScheme.Light;
|
||||
await InvokeScriptSafeAsync("SetLightEditor();");
|
||||
await EventDetailsWebView.ExecuteScriptSafeAsync("SetLightEditor();");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateReaderFontPropertiesAsync()
|
||||
{
|
||||
await EventDetailsWebView.ExecuteScriptFunctionAsync("ChangeFontSize", isChromiumDisposed, JsonSerializer.Serialize(_preferencesService.ReaderFontSize, BasicTypesJsonContext.Default.Int32));
|
||||
await EventDetailsWebView.ExecuteScriptFunctionAsync("ChangeFontSize", JsonSerializer.Serialize(_preferencesService.ReaderFontSize, BasicTypesJsonContext.Default.Int32));
|
||||
|
||||
var fontName = _preferencesService.ReaderFont;
|
||||
fontName += ", sans-serif";
|
||||
|
||||
await EventDetailsWebView.ExecuteScriptFunctionAsync("ChangeFontFamily", isChromiumDisposed, JsonSerializer.Serialize(fontName, BasicTypesJsonContext.Default.String));
|
||||
}
|
||||
|
||||
private async Task<string> InvokeScriptSafeAsync(string function)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await EventDetailsWebView.ExecuteScriptAsync(function);
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
return string.Empty;
|
||||
await EventDetailsWebView.ExecuteScriptFunctionAsync("ChangeFontFamily", JsonSerializer.Serialize(fontName, BasicTypesJsonContext.Default.String));
|
||||
}
|
||||
|
||||
void IRecipient<ApplicationThemeChanged>.Receive(ApplicationThemeChanged message)
|
||||
|
||||
@@ -32,18 +32,16 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
|
||||
private readonly IMailDialogService _dialogService = App.Current.Services.GetService<IMailDialogService>()!;
|
||||
|
||||
private bool isRenderingInProgress = false;
|
||||
private bool? _lastAppliedDarkTheme;
|
||||
private TaskCompletionSource<bool> DOMLoadedTask = new TaskCompletionSource<bool>();
|
||||
|
||||
private bool isChromiumDisposed = false;
|
||||
|
||||
public WebView2 GetWebView() => Chromium;
|
||||
|
||||
public MailRenderingPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_DEFAULT_BACKGROUND_COLOR", "00FFFFFF");
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--enable-features=OverlayScrollbar,msOverlayScrollbarWinStyle,msOverlayScrollbarWinStyleAnimation,msWebView2CodeCache");
|
||||
WebViewExtensions.EnsureWebView2Environment();
|
||||
|
||||
ViewModel.DirectPrintFuncAsync = DirectPrintAsync;
|
||||
|
||||
@@ -81,17 +79,6 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
|
||||
await UpdateEditorThemeAsync();
|
||||
}
|
||||
|
||||
private async Task<string> InvokeScriptSafeAsync(string function)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await Chromium.ExecuteScriptAsync(function);
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private async Task RenderInternalAsync(string htmlBody)
|
||||
{
|
||||
isRenderingInProgress = true;
|
||||
@@ -103,12 +90,12 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
|
||||
|
||||
if (string.IsNullOrEmpty(htmlBody))
|
||||
{
|
||||
await Chromium.ExecuteScriptFunctionAsync("RenderHTML", isChromiumDisposed, JsonSerializer.Serialize(" ", BasicTypesJsonContext.Default.String));
|
||||
await Chromium.ExecuteScriptFunctionAsync("RenderHTML", JsonSerializer.Serialize(" ", BasicTypesJsonContext.Default.String));
|
||||
}
|
||||
else
|
||||
{
|
||||
var shouldLinkifyText = ViewModel.CurrentRenderModel?.MailRenderingOptions?.RenderPlaintextLinks ?? true;
|
||||
await Chromium.ExecuteScriptFunctionAsync("RenderHTML", isChromiumDisposed,
|
||||
await Chromium.ExecuteScriptFunctionAsync("RenderHTML",
|
||||
JsonSerializer.Serialize(htmlBody, BasicTypesJsonContext.Default.String),
|
||||
JsonSerializer.Serialize(shouldLinkifyText, BasicTypesJsonContext.Default.Boolean));
|
||||
}
|
||||
@@ -131,14 +118,17 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
|
||||
|
||||
async void IRecipient<HtmlRenderingRequested>.Receive(HtmlRenderingRequested message)
|
||||
{
|
||||
// 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();
|
||||
|
||||
if (message == null || string.IsNullOrEmpty(message.HtmlBody))
|
||||
{
|
||||
await RenderInternalAsync(string.Empty);
|
||||
return;
|
||||
}
|
||||
|
||||
await Chromium.EnsureCoreWebView2Async();
|
||||
|
||||
await RenderInternalAsync(message.HtmlBody);
|
||||
}
|
||||
|
||||
@@ -168,8 +158,6 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
|
||||
Chromium.CoreWebView2.NewWindowRequested -= WindowRequested;
|
||||
}
|
||||
|
||||
isChromiumDisposed = true;
|
||||
|
||||
Chromium.Close();
|
||||
GC.Collect();
|
||||
}
|
||||
@@ -261,23 +249,29 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
|
||||
{
|
||||
await DOMLoadedTask.Task;
|
||||
|
||||
if (ViewModel.IsDarkWebviewRenderer)
|
||||
var isDark = ViewModel.IsDarkWebviewRenderer;
|
||||
|
||||
if (_lastAppliedDarkTheme == isDark) return;
|
||||
|
||||
_lastAppliedDarkTheme = isDark;
|
||||
|
||||
if (isDark)
|
||||
{
|
||||
Chromium.CoreWebView2.Profile.PreferredColorScheme = CoreWebView2PreferredColorScheme.Dark;
|
||||
|
||||
await InvokeScriptSafeAsync("SetDarkEditor();");
|
||||
await Chromium.ExecuteScriptSafeAsync("SetDarkEditor();");
|
||||
}
|
||||
else
|
||||
{
|
||||
Chromium.CoreWebView2.Profile.PreferredColorScheme = CoreWebView2PreferredColorScheme.Light;
|
||||
|
||||
await InvokeScriptSafeAsync("SetLightEditor();");
|
||||
await Chromium.ExecuteScriptSafeAsync("SetLightEditor();");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateReaderFontPropertiesAsync()
|
||||
{
|
||||
await Chromium.ExecuteScriptFunctionAsync("ChangeFontSize", isChromiumDisposed, JsonSerializer.Serialize(_preferencesService.ReaderFontSize, BasicTypesJsonContext.Default.Int32));
|
||||
await Chromium.ExecuteScriptFunctionAsync("ChangeFontSize", JsonSerializer.Serialize(_preferencesService.ReaderFontSize, BasicTypesJsonContext.Default.Int32));
|
||||
|
||||
// Prepare font family name with fallback to sans-serif by default.
|
||||
var fontName = _preferencesService.ReaderFont;
|
||||
@@ -285,7 +279,7 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
|
||||
// If font family name is not supported by the browser, fallback to sans-serif.
|
||||
fontName += ", sans-serif";
|
||||
|
||||
await Chromium.ExecuteScriptFunctionAsync("ChangeFontFamily", isChromiumDisposed, JsonSerializer.Serialize(fontName, BasicTypesJsonContext.Default.String));
|
||||
await Chromium.ExecuteScriptFunctionAsync("ChangeFontFamily", JsonSerializer.Serialize(fontName, BasicTypesJsonContext.Default.String));
|
||||
}
|
||||
|
||||
void IRecipient<ApplicationThemeChanged>.Receive(ApplicationThemeChanged message)
|
||||
|
||||
Reference in New Issue
Block a user