mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	appearance tab in hidden subtree
This commit is contained in:
		| @@ -218,20 +218,20 @@ export default class DesktopLayout { | ||||
|             .child(new DeleteNotesDialog()) | ||||
|             .child(new InfoDialog()) | ||||
|             .child(new ConfirmDialog()) | ||||
|             .child(new PromptDialog()) | ||||
|             .child(new OptionsDialog() | ||||
|                 .child(new AppearanceOptions()) | ||||
|                 .child(new KeyboardShortcutsOptions()) | ||||
|                 .child(new TextNotesOptions()) | ||||
|                 .child(new CodeNotesOptions()) | ||||
|                 .child(new ImageOptions()) | ||||
|                 .child(new SpellcheckOptions()) | ||||
|                 .child(new PasswordOptions()) | ||||
|                 .child(new EtapiOptions()) | ||||
|                 .child(new BackupOptions()) | ||||
|                 .child(new SyncOptions()) | ||||
|                 .child(new OtherOptions()) | ||||
|                 .child(new AdvancedOptions()) | ||||
|             ); | ||||
|             .child(new PromptDialog()); | ||||
|             // .child(new OptionsDialog() | ||||
|             //     .child(new AppearanceOptions()) | ||||
|             //     .child(new KeyboardShortcutsOptions()) | ||||
|             //     .child(new TextNotesOptions()) | ||||
|             //     .child(new CodeNotesOptions()) | ||||
|             //     .child(new ImageOptions()) | ||||
|             //     .child(new SpellcheckOptions()) | ||||
|             //     .child(new PasswordOptions()) | ||||
|             //     .child(new EtapiOptions()) | ||||
|             //     .child(new BackupOptions()) | ||||
|             //     .child(new SyncOptions()) | ||||
|             //     .child(new OtherOptions()) | ||||
|             //     .child(new AdvancedOptions()) | ||||
|             // ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import BasicWidget from "../../basic_widget.js"; | ||||
| import server from "../../../services/server.js"; | ||||
| import toastService from "../../../services/toast.js"; | ||||
| import NoteContextAwareWidget from "../../note_context_aware_widget.js"; | ||||
|  | ||||
| export default class OptionsTab extends BasicWidget { | ||||
| export default class OptionsTab extends NoteContextAwareWidget { | ||||
|     async updateOption(name, value) { | ||||
|         const opts = { [name]: value }; | ||||
|  | ||||
| @@ -34,4 +34,10 @@ export default class OptionsTab extends BasicWidget { | ||||
|     setCheckboxState($checkbox, optionValue) { | ||||
|         $checkbox.prop('checked', optionValue === 'true'); | ||||
|     } | ||||
|  | ||||
|     async refreshWithNote(note) { | ||||
|         const options = await server.get('options'); | ||||
|  | ||||
|         this.optionsLoaded(options); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,12 +1,22 @@ | ||||
| import TypeWidget from "./type_widget.js"; | ||||
| import AppearanceOptions from "./options/appearance.js"; | ||||
|  | ||||
| const TPL = `<div class="note-detail-widget note-detail-printable"></div>`; | ||||
| const TPL = `<div class="note-detail-content-widget note-detail-printable"> | ||||
|     <style> | ||||
|         .note-detail-content-widget-content { | ||||
|             padding: 15px; | ||||
|         } | ||||
|     </style> | ||||
|  | ||||
|     <div class="note-detail-content-widget-content"></div> | ||||
| </div>`; | ||||
|  | ||||
| export default class ContentWidgetTypeWidget extends TypeWidget { | ||||
|     static getType() { return "content-widget"; } | ||||
|  | ||||
|     doRender() { | ||||
|         this.$widget = $(TPL); | ||||
|         this.$content = this.$widget.find(".note-detail-content-widget-content"); | ||||
|  | ||||
|         super.doRender(); | ||||
|     } | ||||
| @@ -14,10 +24,19 @@ export default class ContentWidgetTypeWidget extends TypeWidget { | ||||
|     async doRefresh(note) { | ||||
|         const contentWidget = note.getLabelValue('contentWidget'); | ||||
|  | ||||
|         this.$content.empty(); | ||||
|         this.children = []; | ||||
|  | ||||
|         if (contentWidget === 'optionsAppearance') { | ||||
|             this.$widget.empty().append("HI!"); | ||||
|             const widget = new AppearanceOptions(); | ||||
|  | ||||
|             await widget.handleEvent('setNoteContext', { noteContext: this.noteContext }); | ||||
|             this.child(widget); | ||||
|  | ||||
|             this.$content.append(widget.render()); | ||||
|             await widget.refresh(); | ||||
|         } else { | ||||
|             this.$widget.empty().append(`Unknown widget of type "${contentWidget}"`); | ||||
|             this.$content.append(`Unknown widget of type "${contentWidget}"`); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										326
									
								
								src/public/app/widgets/type_widgets/options/appearance.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								src/public/app/widgets/type_widgets/options/appearance.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,326 @@ | ||||
| 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"; | ||||
|  | ||||
| const FONT_FAMILIES = [ | ||||
|     { value: "theme", label: "Theme defined" }, | ||||
|     { value: "serif", label: "Serif" }, | ||||
|     { value: "sans-serif", label: "Sans Serif" }, | ||||
|     { value: "monospace", label: "Monospace" }, | ||||
|     { value: "Arial", label: "Arial" }, | ||||
|     { value: "Verdana", label: "Verdana" }, | ||||
|     { value: "Helvetica", label: "Helvetica" }, | ||||
|     { value: "Tahoma", label: "Tahoma" }, | ||||
|     { value: "Trebuchet MS", label: "Trebuchet MS" }, | ||||
|     { value: "Times New Roman", label: "Times New Roman" }, | ||||
|     { value: "Georgia", label: "Georgia" }, | ||||
|     { value: "Garamond", label: "Garamond" }, | ||||
|     { value: "Courier New", label: "Courier New" }, | ||||
|     { value: "Brush Script MT", label: "Brush Script MT" }, | ||||
|     { value: "Impact", label: "Impact" }, | ||||
|     { value: "American Typewriter", label: "American Typewriter" }, | ||||
|     { value: "Andalé Mono", label: "Andalé Mono" }, | ||||
|     { value: "Lucida Console", label: "Lucida Console" }, | ||||
|     { value: "Monaco", label: "Monaco" }, | ||||
|     { value: "Bradley Hand", label: "Bradley Hand" }, | ||||
|     { value: "Luminari", label: "Luminari" }, | ||||
|     { value: "Comic Sans MS", label: "Comic Sans MS" }, | ||||
| ]; | ||||
|  | ||||
| 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> | ||||
|      | ||||
|     <div class="form-group row"> | ||||
|         <div class="col-6"> | ||||
|             <label>Font family</label> | ||||
|             <select class="main-font-family form-control"></select> | ||||
|         </div> | ||||
|      | ||||
|         <div class="col-6"> | ||||
|             <label>Size</label> | ||||
|  | ||||
|             <div class="input-group"> | ||||
|                 <input type="number" class="main-font-size form-control" min="50" max="200" step="10"/> | ||||
|                 <div class="input-group-append"> | ||||
|                     <span class="input-group-text">%</span> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <h5>Note tree font</h5> | ||||
|  | ||||
|     <div class="form-group row"> | ||||
|         <div class="col-4"> | ||||
|             <label>Font family</label> | ||||
|             <select class="tree-font-family form-control"></select> | ||||
|         </div> | ||||
|      | ||||
|         <div class="col-4"> | ||||
|             <label>Size</label> | ||||
|  | ||||
|             <div class="input-group"> | ||||
|                 <input type="number" class="tree-font-size form-control" min="50" max="200" step="10"/> | ||||
|                 <div class="input-group-append"> | ||||
|                     <span class="input-group-text">%</span> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|      | ||||
|     <h5>Note detail font</h5> | ||||
|      | ||||
|     <div class="form-group row"> | ||||
|         <div class="col-4"> | ||||
|             <label>Font family</label> | ||||
|             <select class="detail-font-family form-control"></select> | ||||
|         </div> | ||||
|          | ||||
|         <div class="col-4"> | ||||
|             <label>Size</label> | ||||
|  | ||||
|             <div class="input-group"> | ||||
|                 <input type="number" class="detail-font-size form-control" min="50" max="200" step="10"/> | ||||
|                 <div class="input-group-append"> | ||||
|                     <span class="input-group-text">%</span> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|      | ||||
|     <h5>Monospace (code) font</h5> | ||||
|      | ||||
|     <div class="form-group row"> | ||||
|         <div class="col-4"> | ||||
|             <label>Font family</label> | ||||
|             <select class="monospace-font-family form-control"></select> | ||||
|         </div> | ||||
|      | ||||
|         <div class="col-4"> | ||||
|             <label>Size</label> | ||||
|  | ||||
|             <div class="input-group"> | ||||
|                 <input type="number" class="monospace-font-size form-control" min="50" max="200" step="10"/> | ||||
|                 <div class="input-group-append"> | ||||
|                     <span class="input-group-text">%</span> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <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  | ||||
|         <button class="btn btn-micro reload-frontend-button">reload frontend</button> | ||||
|     </p> | ||||
| </div> | ||||
| </div>`; | ||||
|  | ||||
| export default class AppearanceOptions extends OptionsTab { | ||||
|     get tabTitle() { return "Appearance" } | ||||
|  | ||||
|     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"); | ||||
|  | ||||
|         this.$treeFontSize = this.$widget.find(".tree-font-size"); | ||||
|         this.$treeFontFamily = this.$widget.find(".tree-font-family"); | ||||
|  | ||||
|         this.$detailFontSize = this.$widget.find(".detail-font-size"); | ||||
|         this.$detailFontFamily = this.$widget.find(".detail-font-family"); | ||||
|  | ||||
|         this.$monospaceFontSize = this.$widget.find(".monospace-font-size"); | ||||
|         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); | ||||
|         } | ||||
|  | ||||
|         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.$mainFontSize.val(options.mainFontSize); | ||||
|         this.fillFontFamilyOptions(this.$mainFontFamily, options.mainFontFamily); | ||||
|  | ||||
|         this.$treeFontSize.val(options.treeFontSize); | ||||
|         this.fillFontFamilyOptions(this.$treeFontFamily, options.treeFontFamily); | ||||
|  | ||||
|         this.$detailFontSize.val(options.detailFontSize); | ||||
|         this.fillFontFamilyOptions(this.$detailFontFamily, options.detailFontFamily); | ||||
|  | ||||
|         this.$monospaceFontSize.val(options.monospaceFontSize); | ||||
|         this.fillFontFamilyOptions(this.$monospaceFontFamily, options.monospaceFontFamily); | ||||
|  | ||||
|         this.$maxContentWidth.val(options.maxContentWidth); | ||||
|     } | ||||
|  | ||||
|     fillFontFamilyOptions($select, currentValue) { | ||||
|         $select.empty(); | ||||
|  | ||||
|         for (const {value, label} of FONT_FAMILIES) { | ||||
|             $select.append($("<option>") | ||||
|                 .attr("value", value) | ||||
|                 .prop("selected", value === currentValue) | ||||
|                 .text(label)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -582,7 +582,7 @@ function createOptionNotes() { | ||||
|             branchId: OPTIONS_ROOT, | ||||
|             noteId: OPTIONS_ROOT, | ||||
|             title: 'Options', | ||||
|             type: 'doc', | ||||
|             type: 'book', | ||||
|             content: '', | ||||
|             parentNoteId: getHiddenRoot().noteId | ||||
|         }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user