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