appearance options broken up into individual widgets

This commit is contained in:
zadam 2022-12-06 22:43:35 +01:00
parent 9e83368f87
commit f336435adb
22 changed files with 261 additions and 210 deletions

View File

@ -15,20 +15,6 @@ const TPL = `
overflow-y: auto; overflow-y: auto;
max-height: 85vh; max-height: 85vh;
} }
.options-dialog .options-section:first-of-type h4 {
margin-top: 0;
}
.options-dialog .options-section h4 {
margin-top: 15px;
margin-bottom: 15px;
}
.options-dialog .options-section h5 {
margin-top: 10px;
margin-bottom: 10px;
}
</style> </style>
<div class="modal-dialog modal-lg" style="min-width: 1000px;" role="document"> <div class="modal-dialog modal-lg" style="min-width: 1000px;" role="document">

View File

@ -1,6 +1,6 @@
import server from "../../../services/server.js"; import server from "../../../services/server.js";
import toastService from "../../../services/toast.js"; import toastService from "../../../services/toast.js";
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -51,7 +51,7 @@ const TPL = `
<button id="vacuum-database-button" class="btn">Vacuum database</button> <button id="vacuum-database-button" class="btn">Vacuum database</button>
</div>`; </div>`;
export default class AdvancedOptions extends OptionsTab { export default class AdvancedOptions extends OptionsWidget {
get tabTitle() { return "Advanced" } get tabTitle() { return "Advanced" }
lazyRender() { lazyRender() {

View File

@ -1,7 +1,7 @@
import server from "../../../services/server.js"; import server from "../../../services/server.js";
import utils from "../../../services/utils.js"; import utils from "../../../services/utils.js";
import appContext from "../../../components/app_context.js"; import appContext from "../../../components/app_context.js";
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const FONT_FAMILIES = [ const FONT_FAMILIES = [
{ value: "theme", label: "Theme defined" }, { value: "theme", label: "Theme defined" },
@ -188,7 +188,7 @@ const TPL = `
</div> </div>
`; `;
export default class AppearanceOptions extends OptionsTab { export default class AppearanceOptions extends OptionsWidget {
get tabTitle() { return "Appearance" } get tabTitle() { return "Appearance" }
lazyRender() { lazyRender() {

View File

@ -1,6 +1,6 @@
import server from "../../../services/server.js"; import server from "../../../services/server.js";
import toastService from "../../../services/toast.js"; import toastService from "../../../services/toast.js";
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -35,7 +35,7 @@ const TPL = `
</div> </div>
`; `;
export default class BackupOptions extends OptionsTab { export default class BackupOptions extends OptionsWidget {
get tabTitle() { return "Backup" } get tabTitle() { return "Backup" }
lazyRender() { lazyRender() {

View File

@ -2,7 +2,7 @@ import mimeTypesService from "../../../services/mime_types.js";
import options from "../../../services/options.js"; import options from "../../../services/options.js";
import server from "../../../services/server.js"; import server from "../../../services/server.js";
import toastService from "../../../services/toast.js"; import toastService from "../../../services/toast.js";
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -38,7 +38,7 @@ const TPL = `
<ul id="options-mime-types" style="max-height: 500px; overflow: auto; list-style-type: none;"></ul> <ul id="options-mime-types" style="max-height: 500px; overflow: auto; list-style-type: none;"></ul>
</div>`; </div>`;
export default class CodeNotesOptions extends OptionsTab { export default class CodeNotesOptions extends OptionsWidget {
get tabTitle() { return "Code notes" } get tabTitle() { return "Code notes" }
lazyRender() { lazyRender() {

View File

@ -1,7 +1,7 @@
import server from "../../../services/server.js"; import server from "../../../services/server.js";
import dialogService from "../../../services/dialog.js"; import dialogService from "../../../services/dialog.js";
import toastService from "../../../services/toast.js"; import toastService from "../../../services/toast.js";
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -46,7 +46,7 @@ const TPL = `
} }
</style>`; </style>`;
export default class EtapiOptions extends OptionsTab { export default class EtapiOptions extends OptionsWidget {
get tabTitle() { return "ETAPI" } get tabTitle() { return "ETAPI" }
lazyRender() { lazyRender() {

View File

@ -1,4 +1,4 @@
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const TPL = ` const TPL = `
<style> <style>
@ -36,7 +36,7 @@ const TPL = `
</div> </div>
`; `;
export default class ImageOptions extends OptionsTab { export default class ImageOptions extends OptionsWidget {
get tabTitle() { return "Images" } get tabTitle() { return "Images" }
lazyRender() { lazyRender() {

View File

@ -1,6 +1,6 @@
import server from "../../../services/server.js"; import server from "../../../services/server.js";
import toastService from "../../../services/toast.js"; import toastService from "../../../services/toast.js";
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -50,7 +50,7 @@ const TPL = `
</div> </div>
</div>`; </div>`;
export default class OtherOptions extends OptionsTab { export default class OtherOptions extends OptionsWidget {
get tabTitle() { return "Other" } get tabTitle() { return "Other" }
lazyRender() { lazyRender() {

View File

@ -1,7 +1,7 @@
import server from "../../../services/server.js"; import server from "../../../services/server.js";
import protectedSessionHolder from "../../../services/protected_session_holder.js"; import protectedSessionHolder from "../../../services/protected_session_holder.js";
import toastService from "../../../services/toast.js"; import toastService from "../../../services/toast.js";
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -45,7 +45,7 @@ const TPL = `
</div> </div>
</div>`; </div>`;
export default class PasswordOptions extends OptionsTab { export default class PasswordOptions extends OptionsWidget {
get tabTitle() { return "Password" } get tabTitle() { return "Password" }
lazyRender() { lazyRender() {

View File

@ -1,7 +1,7 @@
import server from "../../../services/server.js"; import server from "../../../services/server.js";
import utils from "../../../services/utils.js"; import utils from "../../../services/utils.js";
import dialogService from "../../../services/dialog.js"; import dialogService from "../../../services/dialog.js";
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -39,7 +39,7 @@ const TPL = `
let globActions; let globActions;
export default class KeyboardShortcutsOptions extends OptionsTab { export default class KeyboardShortcutsOptions extends OptionsWidget {
get tabTitle() { return "Shortcuts" } get tabTitle() { return "Shortcuts" }
lazyRender() { lazyRender() {

View File

@ -1,5 +1,5 @@
import utils from "../../../services/utils.js"; import utils from "../../../services/utils.js";
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -24,7 +24,7 @@ const TPL = `
<p><strong>Available language codes: </strong> <span id="available-language-codes"></span></p> <p><strong>Available language codes: </strong> <span id="available-language-codes"></span></p>
</div>`; </div>`;
export default class SpellcheckOptions extends OptionsTab { export default class SpellcheckOptions extends OptionsWidget {
get tabTitle() { return "Spellcheck" } get tabTitle() { return "Spellcheck" }
lazyRender() { lazyRender() {

View File

@ -1,6 +1,6 @@
import server from "../../../services/server.js"; import server from "../../../services/server.js";
import toastService from "../../../services/toast.js"; import toastService from "../../../services/toast.js";
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const TPL = ` const TPL = `
<div class="options-section"> <div class="options-section">
@ -40,7 +40,7 @@ const TPL = `
<button id="test-sync-button" class="btn">Test sync</button> <button id="test-sync-button" class="btn">Test sync</button>
</div>`; </div>`;
export default class SyncOptions extends OptionsTab { export default class SyncOptions extends OptionsWidget {
get tabTitle() { return "Sync" } get tabTitle() { return "Sync" }
lazyRender() { lazyRender() {

View File

@ -1,6 +1,6 @@
import server from "../../../services/server.js"; import server from "../../../services/server.js";
import toastService from "../../../services/toast.js"; import toastService from "../../../services/toast.js";
import OptionsTab from "./options_tab.js"; import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js";
const TPL = ` const TPL = `
<p><strong>Settings on this options tab are saved automatically after each change.</strong></p> <p><strong>Settings on this options tab are saved automatically after each change.</strong></p>
@ -37,7 +37,7 @@ const TPL = `
</div> </div>
</div>`; </div>`;
export default class TextNotesOptions extends OptionsTab { export default class TextNotesOptions extends OptionsWidget {
get tabTitle() { return "Text notes" } get tabTitle() { return "Text notes" }
lazyRender() { lazyRender() {

View File

@ -1,5 +1,9 @@
import TypeWidget from "./type_widget.js"; import TypeWidget from "./type_widget.js";
import AppearanceOptions from "./options/appearance.js"; import ZoomFactorOptions from "./options/appearance/zoom_factor.js";
import NativeTitleBarOptions from "./options/appearance/native_title_bar.js";
import ThemeOptions from "./options/appearance/theme.js";
import FontsOptions from "./options/appearance/fonts.js";
import MaxContentWidthOptions from "./options/appearance/max_content_width.js";
const TPL = `<div class="note-detail-content-widget note-detail-printable"> const TPL = `<div class="note-detail-content-widget note-detail-printable">
<style> <style>
@ -11,6 +15,16 @@ const TPL = `<div class="note-detail-content-widget note-detail-printable">
<div class="note-detail-content-widget-content"></div> <div class="note-detail-content-widget-content"></div>
</div>`; </div>`;
const CONTENT_WIDGETS = {
optionsAppearance: [
ZoomFactorOptions,
NativeTitleBarOptions,
ThemeOptions,
FontsOptions,
MaxContentWidthOptions
]
};
export default class ContentWidgetTypeWidget extends TypeWidget { export default class ContentWidgetTypeWidget extends TypeWidget {
static getType() { return "content-widget"; } static getType() { return "content-widget"; }
@ -27,14 +41,18 @@ export default class ContentWidgetTypeWidget extends TypeWidget {
this.$content.empty(); this.$content.empty();
this.children = []; this.children = [];
if (contentWidget === 'optionsAppearance') { const contentWidgets = CONTENT_WIDGETS[contentWidget];
const widget = new AppearanceOptions();
if (contentWidgets) {
for (const clazz of contentWidgets) {
const widget = new clazz();
await widget.handleEvent('setNoteContext', {noteContext: this.noteContext}); await widget.handleEvent('setNoteContext', {noteContext: this.noteContext});
this.child(widget); this.child(widget);
this.$content.append(widget.render()); this.$content.append(widget.render());
await widget.refresh(); await widget.refresh();
}
} else { } else {
this.$content.append(`Unknown widget of type "${contentWidget}"`); this.$content.append(`Unknown widget of type "${contentWidget}"`);
} }

View File

@ -1,7 +1,5 @@
import server from "../../../services/server.js"; import OptionsWidget from "./options_widget.js";
import utils from "../../../services/utils.js"; import utils from "../../../../services/utils.js";
import appContext from "../../../components/app_context.js";
import OptionsTab from "../../dialogs/options/options_tab.js";
const FONT_FAMILIES = [ const FONT_FAMILIES = [
{ value: "theme", label: "Theme defined" }, { value: "theme", label: "Theme defined" },
@ -29,55 +27,7 @@ const FONT_FAMILIES = [
]; ];
const TPL = ` const TPL = `
<div>
<p><strong>Settings on this options tab are saved automatically after each change.</strong></p>
<style>
.options-section .row {
/* rows otherwise overflow horizontally and force a scrollbar */
margin-left: auto;
margin-right: auto;
}
</style>
<div class="options-section"> <div class="options-section">
<div class="form-group row">
<div class="col-6">
<label>Zoom factor (desktop build only)</label>
<input type="number" class="zoom-factor-select form-control" min="0.3" max="2.0" step="0.1"/>
</div>
<div class="col-6">
<label>Native title bar (requires app restart)</label>
<select class="native-title-bar-select form-control">
<option value="show">enabled</option>
<option value="hide">disabled</option>
</select>
</div>
</div>
<p>Zooming can be controlled with CTRL+- and CTRL+= shortcuts as well.</p>
</div>
<div class="options-section">
<h4>Theme</h4>
<div class="form-group row">
<div class="col-6">
<label>Theme</label>
<select class="theme-select form-control"></select>
</div>
<div class="col-6">
<label>Override theme fonts</label>
<input type="checkbox" class="override-theme-fonts form-control">
</div>
</div>
</div>
<div class="overriden-font-settings options-section">
<h4>Fonts</h4> <h4>Fonts</h4>
<h5>Main font</h5> <h5>Main font</h5>
@ -163,46 +113,17 @@ const TPL = `
<p>Note that tree and detail font sizing is relative to the main font size setting.</p> <p>Note that tree and detail font sizing is relative to the main font size setting.</p>
<p>Not all listed fonts may be available on your system.</p> <p>Not all listed fonts may be available on your system.</p>
</div>
<p> <p>
To apply font changes, click on To apply font changes, click on
<button class="btn btn-micro reload-frontend-button">reload frontend</button> <button class="btn btn-micro reload-frontend-button">reload frontend</button>
</p> </p>
<div class="options-section">
<h4>Content width</h4>
<p>Trilium by default limits max content width to improve readability for maximized screens on wide screens.</p>
<div class="form-group row">
<div class="col-4">
<label>Max content width in pixels</label>
<input type="number" min="200" step="10" class="max-content-width form-control">
</div>
</div>
<p>
To content width changes, click on
<button class="btn btn-micro reload-frontend-button">reload frontend</button>
</p>
</div>
</div>`; </div>`;
export default class AppearanceOptions extends OptionsTab { export default class FontsOptions extends OptionsWidget {
get tabTitle() { return "Appearance" }
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$zoomFactorSelect = this.$widget.find(".zoom-factor-select");
this.$nativeTitleBarSelect = this.$widget.find(".native-title-bar-select");
this.$themeSelect = this.$widget.find(".theme-select");
this.$overrideThemeFonts = this.$widget.find(".override-theme-fonts");
this.$overridenFontSettings = this.$widget.find(".overriden-font-settings");
this.$mainFontSize = this.$widget.find(".main-font-size"); this.$mainFontSize = this.$widget.find(".main-font-size");
this.$mainFontFamily = this.$widget.find(".main-font-family"); this.$mainFontFamily = this.$widget.find(".main-font-family");
@ -216,87 +137,15 @@ export default class AppearanceOptions extends OptionsTab {
this.$monospaceFontFamily = this.$widget.find(".monospace-font-family"); this.$monospaceFontFamily = this.$widget.find(".monospace-font-family");
this.$widget.find(".reload-frontend-button").on("click", () => utils.reloadFrontendApp("changes from appearance options")); this.$widget.find(".reload-frontend-button").on("click", () => utils.reloadFrontendApp("changes from appearance options"));
this.$body = this.$widget.find("body");
this.$themeSelect.on('change', async () => {
const newTheme = this.$themeSelect.val();
await server.put('options/theme/' + newTheme);
utils.reloadFrontendApp("theme change");
});
this.$overrideThemeFonts.on('change', async () => {
this.updateCheckboxOption('overrideThemeFonts', this.$overrideThemeFonts);
this.$overridenFontSettings.toggle(this.$overrideThemeFonts.is(":checked"));
});
this.$zoomFactorSelect.on('change', () => { appContext.triggerCommand('setZoomFactorAndSave', {zoomFactor: this.$zoomFactorSelect.val()}); });
this.$nativeTitleBarSelect.on('change', () => {
const nativeTitleBarVisible = this.$nativeTitleBarSelect.val() === 'show' ? 'true' : 'false';
this.updateOption('nativeTitleBarVisible', nativeTitleBarVisible);
});
const optionsToSave = [
'mainFontFamily', 'mainFontSize',
'treeFontFamily', 'treeFontSize',
'detailFontFamily', 'detailFontSize',
'monospaceFontFamily', 'monospaceFontSize'
];
for (const optionName of optionsToSave) {
this['$' + optionName].on('change', () =>
this.updateOption(optionName, this['$' + optionName].val()));
}
this.$maxContentWidth = this.$widget.find(".max-content-width");
this.$maxContentWidth.on('change', async () =>
this.updateOption('maxContentWidth', this.$maxContentWidth.val()))
}
toggleBodyClass(prefix, value) {
for (const clazz of Array.from(this.$body[0].classList)) { // create copy to safely iterate over while removing classes
if (clazz.startsWith(prefix)) {
this.$body.removeClass(clazz);
}
}
this.$body.addClass(prefix + value);
} }
async optionsLoaded(options) { async optionsLoaded(options) {
if (utils.isElectron()) { if (options.overrideThemeFonts !== 'true') {
this.$zoomFactorSelect.val(options.zoomFactor); this.toggleInt(false);
} return;
else {
this.$zoomFactorSelect.prop('disabled', true);
} }
this.$nativeTitleBarSelect.val(options.nativeTitleBarVisible === 'true' ? 'show' : 'hide'); this.toggleInt(true);
const themes = [
{ val: 'light', title: 'Light' },
{ val: 'dark', title: 'Dark' }
].concat(await server.get('options/user-themes'));
this.$themeSelect.empty();
for (const theme of themes) {
this.$themeSelect.append($("<option>")
.attr("value", theme.val)
.attr("data-note-id", theme.noteId)
.text(theme.title));
}
this.$themeSelect.val(options.theme);
this.setCheckboxState(this.$overrideThemeFonts, options.overrideThemeFonts);
this.$overridenFontSettings.toggle(options.overrideThemeFonts === 'true');
this.$mainFontSize.val(options.mainFontSize); this.$mainFontSize.val(options.mainFontSize);
this.fillFontFamilyOptions(this.$mainFontFamily, options.mainFontFamily); this.fillFontFamilyOptions(this.$mainFontFamily, options.mainFontFamily);
@ -310,7 +159,17 @@ export default class AppearanceOptions extends OptionsTab {
this.$monospaceFontSize.val(options.monospaceFontSize); this.$monospaceFontSize.val(options.monospaceFontSize);
this.fillFontFamilyOptions(this.$monospaceFontFamily, options.monospaceFontFamily); this.fillFontFamilyOptions(this.$monospaceFontFamily, options.monospaceFontFamily);
this.$maxContentWidth.val(options.maxContentWidth); const optionsToSave = [
'mainFontFamily', 'mainFontSize',
'treeFontFamily', 'treeFontSize',
'detailFontFamily', 'detailFontSize',
'monospaceFontFamily', 'monospaceFontSize'
];
for (const optionName of optionsToSave) {
this['$' + optionName].on('change', () =>
this.updateOption(optionName, this['$' + optionName].val()));
}
} }
fillFontFamilyOptions($select, currentValue) { fillFontFamilyOptions($select, currentValue) {

View File

@ -0,0 +1,38 @@
import OptionsWidget from "./options_widget.js";
import utils from "../../../../services/utils.js";
const TPL = `
<div class="options-section">
<h4>Content width</h4>
<p>Trilium by default limits max content width to improve readability for maximized screens on wide screens.</p>
<div class="form-group row">
<div class="col-4">
<label>Max content width in pixels</label>
<input type="number" min="200" step="10" class="max-content-width form-control">
</div>
</div>
<p>
To apply content width changes, click on
<button class="btn btn-micro reload-frontend-button">reload frontend</button>
</p>
</div>`;
export default class MaxContentWidthOptions extends OptionsWidget {
doRender() {
this.$widget = $(TPL);
this.$maxContentWidth = this.$widget.find(".max-content-width");
this.$maxContentWidth.on('change', async () =>
this.updateOption('maxContentWidth', this.$maxContentWidth.val()))
this.$widget.find(".reload-frontend-button").on("click", () => utils.reloadFrontendApp("changes from appearance options"));
}
async optionsLoaded(options) {
this.$maxContentWidth.val(options.maxContentWidth);
}
}

View File

@ -0,0 +1,27 @@
import OptionsWidget from "./options_widget.js";
const TPL = `
<div class="options-section">
<h4>Native title bar (requires app restart)</h4>
<select class="native-title-bar-select form-control">
<option value="show">enabled</option>
<option value="hide">disabled</option>
</select>
</div>`;
export default class NativeTitleBarOptions extends OptionsWidget {
doRender() {
this.$widget = $(TPL);
this.$nativeTitleBarSelect = this.$widget.find(".native-title-bar-select");
this.$nativeTitleBarSelect.on('change', () => {
const nativeTitleBarVisible = this.$nativeTitleBarSelect.val() === 'show' ? 'true' : 'false';
this.updateOption('nativeTitleBarVisible', nativeTitleBarVisible);
});
}
async optionsLoaded(options) {
this.$nativeTitleBarSelect.val(options.nativeTitleBarVisible === 'true' ? 'show' : 'hide');
}
}

View File

@ -1,8 +1,15 @@
import server from "../../../services/server.js"; import server from "../../../../services/server.js";
import toastService from "../../../services/toast.js"; import toastService from "../../../../services/toast.js";
import NoteContextAwareWidget from "../../note_context_aware_widget.js"; import NoteContextAwareWidget from "../../../note_context_aware_widget.js";
import attributeService from "../../../../services/attributes.js";
export default class OptionsWidget extends NoteContextAwareWidget {
constructor() {
super();
this.contentSized();
}
export default class OptionsTab extends NoteContextAwareWidget {
async updateOption(name, value) { async updateOption(name, value) {
const opts = { [name]: value }; const opts = { [name]: value };
@ -40,4 +47,10 @@ export default class OptionsTab extends NoteContextAwareWidget {
this.optionsLoaded(options); this.optionsLoaded(options);
} }
async entitiesReloadedEvent({loadResults}) {
if (loadResults.options.length > 0) {
this.refresh();
}
}
} }

View File

@ -0,0 +1,58 @@
import OptionsWidget from "./options_widget.js";
import server from "../../../../services/server.js";
import utils from "../../../../services/utils.js";
const TPL = `
<div class="options-section">
<h4>Theme</h4>
<div class="form-group row">
<div class="col-6">
<label>Theme</label>
<select class="theme-select form-control"></select>
</div>
<div class="col-6">
<label>Override theme fonts</label>
<input type="checkbox" class="override-theme-fonts form-control">
</div>
</div>
</div>`;
export default class ThemeOptions extends OptionsWidget {
doRender() {
this.$widget = $(TPL);
this.$themeSelect = this.$widget.find(".theme-select");
this.$overrideThemeFonts = this.$widget.find(".override-theme-fonts");
this.$themeSelect.on('change', async () => {
const newTheme = this.$themeSelect.val();
await server.put('options/theme/' + newTheme);
utils.reloadFrontendApp("theme change");
});
this.$overrideThemeFonts.on('change', () => this.updateCheckboxOption('overrideThemeFonts', this.$overrideThemeFonts));
}
async optionsLoaded(options) {
const themes = [
{ val: 'light', title: 'Light' },
{ val: 'dark', title: 'Dark' }
].concat(await server.get('options/user-themes'));
this.$themeSelect.empty();
for (const theme of themes) {
this.$themeSelect.append($("<option>")
.attr("value", theme.val)
.attr("data-note-id", theme.noteId)
.text(theme.title));
}
this.$themeSelect.val(options.theme);
this.setCheckboxState(this.$overrideThemeFonts, options.overrideThemeFonts);
}
}

View File

@ -0,0 +1,27 @@
import appContext from "../../../../components/app_context.js";
import OptionsWidget from "./options_widget.js";
import utils from "../../../../services/utils.js";
const TPL = `
<div class="options-section">
<h4>Zoom factor (desktop build only)</h4>
<input type="number" class="zoom-factor-select form-control" min="0.3" max="2.0" step="0.1"/>
<p>Zooming can be controlled with CTRL+- and CTRL+= shortcuts as well.</p>
</div>`;
export default class ZoomFactorOptions extends OptionsWidget {
isEnabled() {
return super.isEnabled() && utils.isElectron();
}
doRender() {
this.$widget = $(TPL);
this.$zoomFactorSelect = this.$widget.find(".zoom-factor-select");
this.$zoomFactorSelect.on('change', () => { appContext.triggerCommand('setZoomFactorAndSave', {zoomFactor: this.$zoomFactorSelect.val()}); });
}
async optionsLoaded(options) {
this.$zoomFactorSelect.val(options.zoomFactor);
}
}

View File

@ -967,3 +967,17 @@ button.close:hover {
top: 1px; top: 1px;
margin-right: 3px; margin-right: 3px;
} }
.options-section:first-of-type h4 {
margin-top: 0;
}
.options-section h4 {
margin-top: 15px;
margin-bottom: 15px;
}
.options-section h5 {
margin-top: 10px;
margin-bottom: 10px;
}

View File

@ -575,6 +575,17 @@ function createLauncherTemplates() {
const OPTIONS_ROOT = "opt_root"; const OPTIONS_ROOT = "opt_root";
const OPTIONS_APPEARANCE = "opt_appearance"; const OPTIONS_APPEARANCE = "opt_appearance";
const OPTIONS_ADVANCED = "opt_advanced";
const OPTIONS_BACKUP = "opt_backup";
const OPTIONS_CODE_NOTES = "opt_code_notes";
const OPTIONS_ETAPI = "opt_etapi";
const OPTIONS_IMAGES = "opt_images";
const OPTIONS_OTHER = "opt_other";
const OPTIONS_PASSWORD = "opt_password";
const OPTIONS_SHORTCUTS = "opt_shortcuts";
const OPTIONS_SPELLCHECK = "opt_spellcheck";
const OPTIONS_SYNC = "opt_sync";
const OPTIONS_TEXT_NOTES = "opt_textnotes";
function createOptionNotes() { function createOptionNotes() {
if (!(OPTIONS_ROOT in becca.notes)) { if (!(OPTIONS_ROOT in becca.notes)) {