mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 04:51:31 +08:00 
			
		
		
		
	appearance options broken up into individual widgets
This commit is contained in:
		
							parent
							
								
									9e83368f87
								
							
						
					
					
						commit
						f336435adb
					
				| @ -15,20 +15,6 @@ const TPL = ` | ||||
|             overflow-y: auto; | ||||
|             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> | ||||
| 
 | ||||
|     <div class="modal-dialog modal-lg" style="min-width: 1000px;" role="document"> | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import server from "../../../services/server.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 = ` | ||||
| <div class="options-section"> | ||||
| @ -51,7 +51,7 @@ const TPL = ` | ||||
|     <button id="vacuum-database-button" class="btn">Vacuum database</button> | ||||
| </div>`; | ||||
| 
 | ||||
| export default class AdvancedOptions extends OptionsTab { | ||||
| export default class AdvancedOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "Advanced" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import server from "../../../services/server.js"; | ||||
| import utils from "../../../services/utils.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 = [ | ||||
|     { value: "theme", label: "Theme defined" }, | ||||
| @ -188,7 +188,7 @@ const TPL = ` | ||||
| </div> | ||||
| `;
 | ||||
| 
 | ||||
| export default class AppearanceOptions extends OptionsTab { | ||||
| export default class AppearanceOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "Appearance" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import server from "../../../services/server.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 = ` | ||||
| <div class="options-section"> | ||||
| @ -35,7 +35,7 @@ const TPL = ` | ||||
| </div> | ||||
| `;
 | ||||
| 
 | ||||
| export default class BackupOptions extends OptionsTab { | ||||
| export default class BackupOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "Backup" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -2,7 +2,7 @@ import mimeTypesService from "../../../services/mime_types.js"; | ||||
| import options from "../../../services/options.js"; | ||||
| import server from "../../../services/server.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 = ` | ||||
| <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> | ||||
| </div>`; | ||||
| 
 | ||||
| export default class CodeNotesOptions extends OptionsTab { | ||||
| export default class CodeNotesOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "Code notes" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import server from "../../../services/server.js"; | ||||
| import dialogService from "../../../services/dialog.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 = ` | ||||
| <div class="options-section"> | ||||
| @ -46,7 +46,7 @@ const TPL = ` | ||||
|     } | ||||
| </style>`; | ||||
| 
 | ||||
| export default class EtapiOptions extends OptionsTab { | ||||
| export default class EtapiOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "ETAPI" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import OptionsTab from "./options_tab.js"; | ||||
| import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js"; | ||||
| 
 | ||||
| const TPL = ` | ||||
| <style> | ||||
| @ -36,7 +36,7 @@ const TPL = ` | ||||
| </div> | ||||
| `;
 | ||||
| 
 | ||||
| export default class ImageOptions extends OptionsTab { | ||||
| export default class ImageOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "Images" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import server from "../../../services/server.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 = ` | ||||
| <div class="options-section"> | ||||
| @ -50,7 +50,7 @@ const TPL = ` | ||||
|     </div> | ||||
| </div>`; | ||||
| 
 | ||||
| export default class OtherOptions extends OptionsTab { | ||||
| export default class OtherOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "Other" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import server from "../../../services/server.js"; | ||||
| import protectedSessionHolder from "../../../services/protected_session_holder.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 = ` | ||||
| <div class="options-section"> | ||||
| @ -45,7 +45,7 @@ const TPL = ` | ||||
|     </div> | ||||
| </div>`; | ||||
| 
 | ||||
| export default class PasswordOptions extends OptionsTab { | ||||
| export default class PasswordOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "Password" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import server from "../../../services/server.js"; | ||||
| import utils from "../../../services/utils.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 = ` | ||||
| <div class="options-section"> | ||||
| @ -39,7 +39,7 @@ const TPL = ` | ||||
| 
 | ||||
| let globActions; | ||||
| 
 | ||||
| export default class KeyboardShortcutsOptions extends OptionsTab { | ||||
| export default class KeyboardShortcutsOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "Shortcuts" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import utils from "../../../services/utils.js"; | ||||
| import OptionsTab from "./options_tab.js"; | ||||
| import OptionsWidget from "../../type_widgets/options/appearance/options_widget.js"; | ||||
| 
 | ||||
| const TPL = ` | ||||
| <div class="options-section"> | ||||
| @ -24,7 +24,7 @@ const TPL = ` | ||||
|     <p><strong>Available language codes: </strong> <span id="available-language-codes"></span></p> | ||||
| </div>`; | ||||
| 
 | ||||
| export default class SpellcheckOptions extends OptionsTab { | ||||
| export default class SpellcheckOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "Spellcheck" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import server from "../../../services/server.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 = ` | ||||
| <div class="options-section"> | ||||
| @ -40,7 +40,7 @@ const TPL = ` | ||||
|     <button id="test-sync-button" class="btn">Test sync</button> | ||||
| </div>`; | ||||
| 
 | ||||
| export default class SyncOptions extends OptionsTab { | ||||
| export default class SyncOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "Sync" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import server from "../../../services/server.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 = ` | ||||
| <p><strong>Settings on this options tab are saved automatically after each change.</strong></p> | ||||
| @ -37,7 +37,7 @@ const TPL = ` | ||||
|     </div> | ||||
| </div>`; | ||||
| 
 | ||||
| export default class TextNotesOptions extends OptionsTab { | ||||
| export default class TextNotesOptions extends OptionsWidget { | ||||
|     get tabTitle() { return "Text notes" } | ||||
| 
 | ||||
|     lazyRender() { | ||||
|  | ||||
| @ -1,5 +1,9 @@ | ||||
| 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">
 | ||||
|     <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>`; | ||||
| 
 | ||||
| const CONTENT_WIDGETS = { | ||||
|     optionsAppearance: [ | ||||
|         ZoomFactorOptions, | ||||
|         NativeTitleBarOptions, | ||||
|         ThemeOptions, | ||||
|         FontsOptions, | ||||
|         MaxContentWidthOptions | ||||
|     ] | ||||
| }; | ||||
| 
 | ||||
| export default class ContentWidgetTypeWidget extends TypeWidget { | ||||
|     static getType() { return "content-widget"; } | ||||
| 
 | ||||
| @ -27,14 +41,18 @@ export default class ContentWidgetTypeWidget extends TypeWidget { | ||||
|         this.$content.empty(); | ||||
|         this.children = []; | ||||
| 
 | ||||
|         if (contentWidget === 'optionsAppearance') { | ||||
|             const widget = new AppearanceOptions(); | ||||
|         const contentWidgets = CONTENT_WIDGETS[contentWidget]; | ||||
| 
 | ||||
|             await widget.handleEvent('setNoteContext', { noteContext: this.noteContext }); | ||||
|             this.child(widget); | ||||
|         if (contentWidgets) { | ||||
|             for (const clazz of contentWidgets) { | ||||
|                 const widget = new clazz(); | ||||
| 
 | ||||
|             this.$content.append(widget.render()); | ||||
|             await widget.refresh(); | ||||
|                 await widget.handleEvent('setNoteContext', {noteContext: this.noteContext}); | ||||
|                 this.child(widget); | ||||
| 
 | ||||
|                 this.$content.append(widget.render()); | ||||
|                 await widget.refresh(); | ||||
|             } | ||||
|         } else { | ||||
|             this.$content.append(`Unknown widget of type "${contentWidget}"`); | ||||
|         } | ||||
|  | ||||
| @ -1,7 +1,5 @@ | ||||
| import server from "../../../services/server.js"; | ||||
| import utils from "../../../services/utils.js"; | ||||
| import appContext from "../../../components/app_context.js"; | ||||
| import OptionsTab from "../../dialogs/options/options_tab.js"; | ||||
| import OptionsWidget from "./options_widget.js"; | ||||
| import utils from "../../../../services/utils.js"; | ||||
| 
 | ||||
| const FONT_FAMILIES = [ | ||||
|     { value: "theme", label: "Theme defined" }, | ||||
| @ -29,55 +27,7 @@ const FONT_FAMILIES = [ | ||||
| ]; | ||||
| 
 | ||||
| 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="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> | ||||
|      | ||||
|     <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>Not all listed fonts may be available on your system.</p> | ||||
| </div> | ||||
| 
 | ||||
| <p> | ||||
|     To apply font changes, click on  | ||||
|     <button class="btn btn-micro reload-frontend-button">reload frontend</button> | ||||
| </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  | ||||
|         To apply font changes, click on  | ||||
|         <button class="btn btn-micro reload-frontend-button">reload frontend</button> | ||||
|     </p> | ||||
| </div> | ||||
| </div>`; | ||||
| 
 | ||||
| export default class AppearanceOptions extends OptionsTab { | ||||
|     get tabTitle() { return "Appearance" } | ||||
| 
 | ||||
| export default class FontsOptions extends OptionsWidget { | ||||
|     doRender() { | ||||
|         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.$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.$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) { | ||||
|         if (utils.isElectron()) { | ||||
|             this.$zoomFactorSelect.val(options.zoomFactor); | ||||
|         } | ||||
|         else { | ||||
|             this.$zoomFactorSelect.prop('disabled', true); | ||||
|         if (options.overrideThemeFonts !== 'true') { | ||||
|             this.toggleInt(false); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         this.$nativeTitleBarSelect.val(options.nativeTitleBarVisible === 'true' ? 'show' : 'hide'); | ||||
| 
 | ||||
|         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.toggleInt(true); | ||||
| 
 | ||||
|         this.$mainFontSize.val(options.mainFontSize); | ||||
|         this.fillFontFamilyOptions(this.$mainFontFamily, options.mainFontFamily); | ||||
| @ -310,7 +159,17 @@ export default class AppearanceOptions extends OptionsTab { | ||||
|         this.$monospaceFontSize.val(options.monospaceFontSize); | ||||
|         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) { | ||||
| @ -323,4 +182,4 @@ export default class AppearanceOptions extends OptionsTab { | ||||
|                 .text(label)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -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'); | ||||
|     } | ||||
| } | ||||
| @ -1,8 +1,15 @@ | ||||
| import server from "../../../services/server.js"; | ||||
| import toastService from "../../../services/toast.js"; | ||||
| import NoteContextAwareWidget from "../../note_context_aware_widget.js"; | ||||
| import server from "../../../../services/server.js"; | ||||
| import toastService from "../../../../services/toast.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) { | ||||
|         const opts = { [name]: value }; | ||||
| 
 | ||||
| @ -40,4 +47,10 @@ export default class OptionsTab extends NoteContextAwareWidget { | ||||
| 
 | ||||
|         this.optionsLoaded(options); | ||||
|     } | ||||
| 
 | ||||
|     async entitiesReloadedEvent({loadResults}) { | ||||
|         if (loadResults.options.length > 0) { | ||||
|             this.refresh(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -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); | ||||
|     } | ||||
| } | ||||
| @ -967,3 +967,17 @@ button.close:hover { | ||||
|     top: 1px; | ||||
|     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; | ||||
| } | ||||
|  | ||||
| @ -575,6 +575,17 @@ function createLauncherTemplates() { | ||||
| 
 | ||||
| const OPTIONS_ROOT = "opt_root"; | ||||
| 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() { | ||||
|     if (!(OPTIONS_ROOT in becca.notes)) { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam