Ability to set composer default font (#287)
* Added ability to set Composer font * Added missing translations and refactoring * Remove unused methods * Small fixes
This commit is contained in:
@@ -135,7 +135,7 @@ namespace Wino
|
||||
services.AddTransient(typeof(AccountDetailsPageViewModel));
|
||||
services.AddTransient(typeof(SignatureManagementPageViewModel));
|
||||
services.AddTransient(typeof(MessageListPageViewModel));
|
||||
services.AddTransient(typeof(ReadingPanePageViewModel));
|
||||
services.AddTransient(typeof(ReadComposePanePageViewModel));
|
||||
services.AddTransient(typeof(MergedAccountDetailsPageViewModel));
|
||||
services.AddTransient(typeof(LanguageTimePageViewModel));
|
||||
}
|
||||
|
||||
@@ -19,7 +19,11 @@ namespace Wino.Dialogs
|
||||
{
|
||||
private Func<Task<string>> _getHTMLBodyFunction;
|
||||
private readonly TaskCompletionSource<bool> _domLoadedTask = new TaskCompletionSource<bool>();
|
||||
|
||||
private readonly INativeAppService _nativeAppService = App.Current.Services.GetService<INativeAppService>();
|
||||
private readonly IFontService _fontService = App.Current.Services.GetService<IFontService>();
|
||||
private readonly IPreferencesService _preferencesService = App.Current.Services.GetService<IPreferencesService>();
|
||||
|
||||
public AccountSignature Result;
|
||||
|
||||
public bool IsComposerDarkMode
|
||||
@@ -36,7 +40,7 @@ namespace Wino.Dialogs
|
||||
|
||||
SignatureNameTextBox.Header = Translator.SignatureEditorDialog_SignatureName_TitleNew;
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_DEFAULT_BACKGROUND_COLOR", "00FFFFFF");
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--enable-features=OverlayScrollbar,msOverlayScrollbarWinStyle,msOverlayScrollbarWinStyleAnimation");
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--enable-features=OverlayScrollbar,msOverlayScrollbarWinStyle,msOverlayScrollbarWinStyleAnimation,FontAccess");
|
||||
|
||||
// TODO: Should be added additional logic to enable/disable primary button when webview content changed.
|
||||
IsPrimaryButtonEnabled = true;
|
||||
@@ -275,6 +279,7 @@ namespace Wino.Dialogs
|
||||
await _domLoadedTask.Task;
|
||||
|
||||
await UpdateEditorThemeAsync();
|
||||
await InitializeEditorAsync();
|
||||
|
||||
if (string.IsNullOrEmpty(htmlBody))
|
||||
{
|
||||
@@ -288,6 +293,16 @@ namespace Wino.Dialogs
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> InitializeEditorAsync()
|
||||
{
|
||||
var fonts = _fontService.GetFonts();
|
||||
var composerFont = _preferencesService.ComposerFont;
|
||||
int composerFontSize = _preferencesService.ComposerFontSize;
|
||||
var readerFont = _preferencesService.ReaderFont;
|
||||
int readerFontSize = _preferencesService.ReaderFontSize;
|
||||
return await ExecuteScriptFunctionAsync("initializeJodit", fonts, composerFont, composerFontSize, readerFont, readerFontSize);
|
||||
}
|
||||
|
||||
private async void ChromiumInitialized(Microsoft.UI.Xaml.Controls.WebView2 sender, Microsoft.UI.Xaml.Controls.CoreWebView2InitializedEventArgs args)
|
||||
{
|
||||
var editorBundlePath = (await _nativeAppService.GetEditorBundlePathAsync()).Replace("editor.html", string.Empty);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const editor = Jodit.make("#editor", {
|
||||
const joditConfig = {
|
||||
"useSearch": false,
|
||||
"toolbar": true,
|
||||
"buttons": "bold,italic,underline,strikethrough,brush,ul,ol,font,fontsize,paragraph,image,link,indent,outdent,align,lineHeight,table",
|
||||
@@ -6,7 +6,6 @@ const editor = Jodit.make("#editor", {
|
||||
"toolbarAdaptive": false,
|
||||
"toolbarInlineForSelection": false,
|
||||
"showCharsCounter": false,
|
||||
style: { font: "14px Arial" },
|
||||
"showWordsCounter": false,
|
||||
"showXPathInStatusbar": false,
|
||||
"disablePlugins": "add-new-line",
|
||||
@@ -16,61 +15,85 @@ const editor = Jodit.make("#editor", {
|
||||
},
|
||||
"enter": "DIV",
|
||||
"minHeight": 200
|
||||
});
|
||||
}
|
||||
|
||||
// Handle the image input change event
|
||||
imageInput.addEventListener('change', () => {
|
||||
const file = imageInput.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
const base64Image = event.target.result;
|
||||
insertImages([base64Image]);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
// This method should be called first all the time.
|
||||
function initializeJodit(fonts, defaultComposerFont, defaultComposerFontSize, defaultReaderFont, defaultReaderFontSize) {
|
||||
const fontsWithFallabckObject = fonts.reduce((acc, font) => { acc[`'${font}',Arial,sans-serif`] = font; return acc; }, {});
|
||||
const mergedConfig = {
|
||||
...joditConfig,
|
||||
controls: {
|
||||
font: {
|
||||
list: Jodit.atom(fontsWithFallabckObject)
|
||||
}
|
||||
},
|
||||
style: { font: `${defaultReaderFontSize}px ${defaultReaderFont}` },
|
||||
}
|
||||
});
|
||||
|
||||
const disabledButtons = ["indent", "outdent"];
|
||||
const ariaPressedButtons = ["bold", "italic", "underline", "strikethrough", "ul", "ol"];
|
||||
Jodit.plugins.add('inlineFonts', jodit => {
|
||||
jodit.events.on('afterEnter', e => {
|
||||
const current = jodit.selection.current().parentNode;
|
||||
current.style.fontFamily = `'${defaultComposerFont}',Arial,sans-serif`;
|
||||
current.style.fontSize = `${defaultComposerFontSize}px`;
|
||||
});
|
||||
});
|
||||
|
||||
const alignmentButton = document.querySelector(`[ref='left']`).firstChild.firstChild;
|
||||
const alignmentObserver = new MutationObserver(function () {
|
||||
const value = alignmentButton.firstChild.getAttribute('class').split(' ')[0];
|
||||
window.chrome.webview.postMessage({ type: 'alignment', value: value });
|
||||
});
|
||||
alignmentObserver.observe(alignmentButton, { childList: true, attributes: true, attributeFilter: ["class"] });
|
||||
// Don't add const/let/var here, it should be global
|
||||
editor = Jodit.make("#editor", mergedConfig);
|
||||
|
||||
const ariaObservers = ariaPressedButtons.map(button => {
|
||||
const buttonContainer = document.querySelector(`[ref='${button}']`);
|
||||
const observer = new MutationObserver(function () { pressedChanged(buttonContainer) });
|
||||
observer.observe(buttonContainer.firstChild, { attributes: true, attributeFilter: ["aria-pressed"] });
|
||||
// Handle the image input change event
|
||||
imageInput.addEventListener('change', () => {
|
||||
const file = imageInput.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
const base64Image = event.target.result;
|
||||
insertImages([base64Image]);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
});
|
||||
|
||||
return observer;
|
||||
});
|
||||
// Listeners for button events
|
||||
const disabledButtons = ["indent", "outdent"];
|
||||
const ariaPressedButtons = ["bold", "italic", "underline", "strikethrough", "ul", "ol"];
|
||||
|
||||
const disabledObservers = disabledButtons.map(button => {
|
||||
const buttonContainer = document.querySelector(`[ref='${button}']`);
|
||||
const observer = new MutationObserver(function () { disabledButtonChanged(buttonContainer) });
|
||||
observer.observe(buttonContainer.firstChild, { attributes: true, attributeFilter: ["disabled"] });
|
||||
const alignmentButton = document.querySelector(`[ref='left']`).firstChild.firstChild;
|
||||
const alignmentObserver = new MutationObserver(function () {
|
||||
const value = alignmentButton.firstChild.getAttribute('class').split(' ')[0];
|
||||
window.chrome.webview.postMessage({ type: 'alignment', value: value });
|
||||
});
|
||||
alignmentObserver.observe(alignmentButton, { childList: true, attributes: true, attributeFilter: ["class"] });
|
||||
|
||||
return observer;
|
||||
});
|
||||
const ariaObservers = ariaPressedButtons.map(button => {
|
||||
const buttonContainer = document.querySelector(`[ref='${button}']`);
|
||||
const observer = new MutationObserver(function () { pressedChanged(buttonContainer) });
|
||||
observer.observe(buttonContainer.firstChild, { attributes: true, attributeFilter: ["aria-pressed"] });
|
||||
|
||||
function pressedChanged(buttonContainer) {
|
||||
const ref = buttonContainer.getAttribute('ref');
|
||||
const value = buttonContainer.firstChild.getAttribute('aria-pressed');
|
||||
window.chrome.webview.postMessage({ type: ref, value: value });
|
||||
return observer;
|
||||
});
|
||||
|
||||
const disabledObservers = disabledButtons.map(button => {
|
||||
const buttonContainer = document.querySelector(`[ref='${button}']`);
|
||||
const observer = new MutationObserver(function () { disabledButtonChanged(buttonContainer) });
|
||||
observer.observe(buttonContainer.firstChild, { attributes: true, attributeFilter: ["disabled"] });
|
||||
|
||||
return observer;
|
||||
});
|
||||
|
||||
function pressedChanged(buttonContainer) {
|
||||
const ref = buttonContainer.getAttribute('ref');
|
||||
const value = buttonContainer.firstChild.getAttribute('aria-pressed');
|
||||
window.chrome.webview.postMessage({ type: ref, value: value });
|
||||
}
|
||||
|
||||
function disabledButtonChanged(buttonContainer) {
|
||||
const ref = buttonContainer.getAttribute('ref');
|
||||
const value = buttonContainer.firstChild.getAttribute('disabled');
|
||||
window.chrome.webview.postMessage({ type: ref, value: value });
|
||||
}
|
||||
}
|
||||
|
||||
function disabledButtonChanged(buttonContainer) {
|
||||
const ref = buttonContainer.getAttribute('ref');
|
||||
const value = buttonContainer.firstChild.getAttribute('disabled');
|
||||
console.log(buttonContainer, ref, value);
|
||||
window.chrome.webview.postMessage({ type: ref, value: value });
|
||||
}
|
||||
|
||||
|
||||
function RenderHTML(htmlString) {
|
||||
editor.s.insertHTML(htmlString);
|
||||
editor.synchronizeValues();
|
||||
|
||||
@@ -166,9 +166,9 @@ namespace Wino.Services
|
||||
set => SaveProperty(propertyName: nameof(CurrentLanguage), value);
|
||||
}
|
||||
|
||||
public ReaderFont ReaderFont
|
||||
public string ReaderFont
|
||||
{
|
||||
get => _configurationService.Get(nameof(ReaderFont), ReaderFont.Calibri);
|
||||
get => _configurationService.Get(nameof(ReaderFont), "Calibri");
|
||||
set => SaveProperty(propertyName: nameof(ReaderFont), value);
|
||||
}
|
||||
|
||||
@@ -178,6 +178,18 @@ namespace Wino.Services
|
||||
set => SaveProperty(propertyName: nameof(ReaderFontSize), value);
|
||||
}
|
||||
|
||||
public string ComposerFont
|
||||
{
|
||||
get => _configurationService.Get(nameof(ComposerFont), "Calibri");
|
||||
set => SaveProperty(propertyName: nameof(ComposerFont), value);
|
||||
}
|
||||
|
||||
public int ComposerFontSize
|
||||
{
|
||||
get => _configurationService.Get(nameof(ComposerFontSize), 14);
|
||||
set => SaveProperty(propertyName: nameof(ComposerFontSize), value);
|
||||
}
|
||||
|
||||
public bool IsNavigationPaneOpened
|
||||
{
|
||||
get => _configurationService.Get(nameof(IsNavigationPaneOpened), true);
|
||||
|
||||
@@ -72,8 +72,8 @@ namespace Wino.Services
|
||||
return typeof(PersonalizationPage);
|
||||
case WinoPage.MessageListPage:
|
||||
return typeof(MessageListPage);
|
||||
case WinoPage.ReadingPanePage:
|
||||
return typeof(ReadingPanePage);
|
||||
case WinoPage.ReadComposePanePage:
|
||||
return typeof(ReadComposePanePage);
|
||||
case WinoPage.MailRenderingPage:
|
||||
return typeof(MailRenderingPage);
|
||||
case WinoPage.ComposePage:
|
||||
|
||||
6
Wino.Mail/Views/Abstract/ReadComposePanePageAbstract.cs
Normal file
6
Wino.Mail/Views/Abstract/ReadComposePanePageAbstract.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
using Wino.Mail.ViewModels;
|
||||
|
||||
namespace Wino.Views.Abstract
|
||||
{
|
||||
public abstract class ReadComposePanePageAbstract : BasePage<ReadComposePanePageViewModel> { }
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
using Wino.Mail.ViewModels;
|
||||
|
||||
namespace Wino.Views.Abstract
|
||||
{
|
||||
public abstract class ReadingPanePageAbstract : BasePage<ReadingPanePageViewModel> { }
|
||||
}
|
||||
@@ -59,7 +59,7 @@ namespace Wino.Views
|
||||
InitializeComponent();
|
||||
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_DEFAULT_BACKGROUND_COLOR", "00FFFFFF");
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--enable-features=OverlayScrollbar,msOverlayScrollbarWinStyle,msOverlayScrollbarWinStyleAnimation");
|
||||
Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--enable-features=OverlayScrollbar,msOverlayScrollbarWinStyle,msOverlayScrollbarWinStyleAnimation,FontAccess");
|
||||
}
|
||||
|
||||
private static async void OnIsComposerDarkModeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
@@ -389,6 +389,7 @@ namespace Wino.Views
|
||||
await DOMLoadedTask.Task;
|
||||
|
||||
await UpdateEditorThemeAsync();
|
||||
await InitializeEditorAsync();
|
||||
|
||||
if (string.IsNullOrEmpty(htmlBody))
|
||||
{
|
||||
@@ -400,6 +401,16 @@ namespace Wino.Views
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> InitializeEditorAsync()
|
||||
{
|
||||
var fonts = ViewModel.FontService.GetFonts();
|
||||
var composerFont = ViewModel.PreferencesService.ComposerFont;
|
||||
int composerFontSize = ViewModel.PreferencesService.ComposerFontSize;
|
||||
var readerFont = ViewModel.PreferencesService.ReaderFont;
|
||||
int readerFontSize = ViewModel.PreferencesService.ReaderFontSize;
|
||||
return await ExecuteScriptFunctionAsync("initializeJodit", fonts, composerFont, composerFontSize, readerFont, readerFontSize);
|
||||
}
|
||||
|
||||
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
|
||||
{
|
||||
base.OnNavigatingFrom(e);
|
||||
|
||||
@@ -17,6 +17,7 @@ using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Messages.Mails;
|
||||
using Wino.Core.Messages.Shell;
|
||||
using Wino.Core.Services;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Views.Abstract;
|
||||
|
||||
@@ -273,13 +274,11 @@ namespace Wino.Views
|
||||
await ExecuteScriptFunctionAsync("ChangeFontSize", _fontService.GetCurrentReaderFontSize());
|
||||
|
||||
// Prepare font family name with fallback to sans-serif by default.
|
||||
var fontName = _fontService.GetCurrentReaderFont()?.FontFamilyName ?? "Arial";
|
||||
var fontName = _fontService.GetCurrentReaderFont();
|
||||
|
||||
// If font family name is not supported by the browser, fallback to sans-serif.
|
||||
fontName += ", sans-serif";
|
||||
|
||||
// var fontName = "Starborn";
|
||||
|
||||
await ExecuteScriptFunctionAsync("ChangeFontFamily", fontName);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace Wino.Views.Settings
|
||||
{
|
||||
public sealed partial class ReadingPanePage : ReadingPanePageAbstract
|
||||
public sealed partial class ReadComposePanePage : ReadComposePanePageAbstract
|
||||
{
|
||||
public ReadingPanePage()
|
||||
public ReadComposePanePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
@@ -68,10 +68,10 @@
|
||||
|
||||
<controls:SettingsCard
|
||||
Command="{x:Bind ViewModel.NavigateSubDetailCommand}"
|
||||
CommandParameter="{x:Bind enums:WinoPage.ReadingPanePage}"
|
||||
CommandParameter="{x:Bind enums:WinoPage.ReadComposePanePage}"
|
||||
IsClickEnabled="True"
|
||||
Header="{x:Bind domain:Translator.SettingsReadingPane_Title}"
|
||||
Description="{x:Bind domain:Translator.SettingsReadingPane_Description}">
|
||||
Header="{x:Bind domain:Translator.SettingsReadComposePane_Title}"
|
||||
Description="{x:Bind domain:Translator.SettingsReadComposePane_Description}">
|
||||
<controls:SettingsCard.HeaderIcon>
|
||||
<PathIcon
|
||||
Data="F1 M 20 2.5 L 20 3.75 L 8.75 3.75 L 8.75 2.5 Z M 17.5 15 L 0 15 L 0 13.75 L 17.5 13.75 Z M 2.5 10 L 20 10 L 20 11.25 L 2.5 11.25 Z M 2.5 17.5 L 20 17.5 L 20 18.75 L 2.5 18.75 Z M 3.125 7.5 C 2.695312 7.5 2.291667 7.416992 1.914062 7.250977 C 1.536458 7.084961 1.206055 6.860352 0.922852 6.577148 C 0.639648 6.293945 0.415039 5.963542 0.249023 5.585938 C 0.083008 5.208334 0 4.804688 0 4.375 C 0 3.945312 0.083008 3.541668 0.249023 3.164062 C 0.415039 2.786459 0.639648 2.456055 0.922852 2.172852 C 1.206055 1.889648 1.536458 1.665039 1.914062 1.499023 C 2.291667 1.333008 2.695312 1.25 3.125 1.25 C 3.554688 1.25 3.958333 1.333008 4.335938 1.499023 C 4.713542 1.665039 5.043945 1.889648 5.327148 2.172852 C 5.610352 2.456055 5.834961 2.786459 6.000977 3.164062 C 6.166992 3.541668 6.25 3.945312 6.25 4.375 L 5 4.375 C 5 4.114584 4.951172 3.870443 4.853516 3.642578 C 4.755859 3.414715 4.622396 3.216146 4.453125 3.046875 C 4.283854 2.877605 4.085286 2.744141 3.857422 2.646484 C 3.629557 2.548828 3.385417 2.5 3.125 2.5 C 2.864583 2.5 2.620443 2.548828 2.392578 2.646484 C 2.164713 2.744141 1.966146 2.877605 1.796875 3.046875 C 1.627604 3.216146 1.494141 3.414715 1.396484 3.642578 C 1.298828 3.870443 1.25 4.114584 1.25 4.375 C 1.25 4.635418 1.298828 4.879559 1.396484 5.107422 C 1.494141 5.335287 1.627604 5.533854 1.796875 5.703125 C 1.966146 5.872396 2.164713 6.005859 2.392578 6.103516 C 2.620443 6.201172 2.864583 6.25 3.125 6.25 L 17.5 6.25 L 17.5 7.5 Z "
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Wino.Views
|
||||
WinoPage.AboutPage => typeof(AboutPage),
|
||||
WinoPage.PersonalizationPage => typeof(PersonalizationPage),
|
||||
WinoPage.MessageListPage => typeof(MessageListPage),
|
||||
WinoPage.ReadingPanePage => typeof(ReadingPanePage),
|
||||
WinoPage.ReadComposePanePage => typeof(ReadComposePanePage),
|
||||
WinoPage.LanguageTimePage => typeof(LanguageTimePage),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
@@ -356,7 +356,7 @@
|
||||
<Compile Include="Views\Abstract\MessageListPageAbstract.cs" />
|
||||
<Compile Include="Views\Abstract\NewAccountManagementPageAbstract.cs" />
|
||||
<Compile Include="Views\Abstract\PersonalizationPageAbstract.cs" />
|
||||
<Compile Include="Views\Abstract\ReadingPanePageAbstract.cs" />
|
||||
<Compile Include="Views\Abstract\ReadComposePanePageAbstract.cs" />
|
||||
<Compile Include="Views\Abstract\SettingOptionsPageAbstract.cs" />
|
||||
<Compile Include="Views\Abstract\SettingsPageAbstract.cs" />
|
||||
<Compile Include="Views\Abstract\SettingsPageBase.cs" />
|
||||
@@ -419,8 +419,8 @@
|
||||
<Compile Include="AppShell.xaml.cs">
|
||||
<DependentUpon>AppShell.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Settings\ReadingPanePage.xaml.cs">
|
||||
<DependentUpon>ReadingPanePage.xaml</DependentUpon>
|
||||
<Compile Include="Views\Settings\ReadComposePanePage.xaml.cs">
|
||||
<DependentUpon>ReadComposePanePage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Settings\SettingOptionsPage.xaml.cs">
|
||||
<DependentUpon>SettingOptionsPage.xaml</DependentUpon>
|
||||
@@ -647,7 +647,7 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Views\Settings\ReadingPanePage.xaml">
|
||||
<Page Include="Views\Settings\ReadComposePanePage.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
|
||||
Reference in New Issue
Block a user