allow overriding theme fonts

This commit is contained in:
zadam 2021-09-27 21:01:56 +02:00
parent d5bd9875f9
commit e6bc8ed3b5
13 changed files with 259 additions and 96 deletions

View File

@ -1,7 +1,31 @@
import server from "../../services/server.js";
import utils from "../../services/utils.js";
import appContext from "../../services/app_context.js";
import libraryLoader from "../../services/library_loader.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 = `
<p><strong>Settings on this options tab are saved automatically after each change.</strong></p>
@ -9,10 +33,14 @@ const TPL = `
<form>
<div class="form-group row">
<div class="col-4">
<label for="theme-select">Theme</label>
<select class="form-control" id="theme-select"></select>
<label for="heading-style">Heading style</label>
<select class="form-control" id="heading-style">
<option value="plain">Plain</option>
<option value="underline">Underline</option>
<option value="markdown">Markdown-style</option>
</select>
</div>
<div class="col-4">
<label for="zoom-factor-select">Zoom factor (desktop build only)</label>
@ -28,71 +56,144 @@ const TPL = `
</select>
</div>
</div>
<div class="form-group row">
<div class="col-4">
<label for="heading-style">Heading style</label>
<select class="form-control" id="heading-style">
<option value="plain">Plain</option>
<option value="underline">Underline</option>
<option value="markdown">Markdown-style</option>
</select>
</div>
</div>
<p>Zooming can be controlled with CTRL+- and CTRL+= shortcuts as well.</p>
<h4>Font sizes</h4>
<h4>Theme</h4>
<div class="form-group row">
<div class="col-4">
<label for="main-font-size">Main font size</label>
<div class="input-group">
<input type="number" class="form-control" id="main-font-size" min="50" max="200" step="10"/>
<div class="input-group-append">
<span class="input-group-text">%</span>
</div>
</div>
<label for="theme-select">Theme</label>
<select class="form-control" id="theme-select"></select>
</div>
<div class="col-4">
<label for="tree-font-size">Note tree font size</label>
<div class="input-group">
<input type="number" class="form-control" id="tree-font-size" min="50" max="200" step="10"/>
<div class="input-group-append">
<span class="input-group-text">%</span>
</div>
</div>
</div>
<div class="col-4">
<label for="detail-font-size">Note detail font size</label>
<div class="input-group">
<input type="number" class="form-control" id="detail-font-size" min="50" max="200" step="10"/>
<div class="input-group-append">
<span class="input-group-text">%</span>
</div>
</div>
<label for="override-theme-fonts">Override theme fonts</label>
<input type="checkbox" class="form-control" id="override-theme-fonts">
</div>
</div>
<p>Note that tree and detail font sizing is relative to the main font size setting.</p>
<div id="overriden-font-settings">
<h4>Fonts</h4>
<h5>Main font</h5>
<div class="form-group row">
<div class="col-4">
<label for="main-font-family">Font family</label>
<select class="form-control" id="main-font-family"></select>
</div>
<div class="col-4">
<label for="main-font-size">Size</label>
<div class="input-group">
<input type="number" class="form-control" id="main-font-size" 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 for="tree-font-family">Font family</label>
<select class="form-control" id="tree-font-family"></select>
</div>
<div class="col-4">
<label for="tree-font-size">Size</label>
<div class="input-group">
<input type="number" class="form-control" id="tree-font-size" 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 for="detail-font-family">Font family</label>
<select class="form-control" id="detail-font-family"></select>
</div>
<div class="col-4">
<label for="detail-font-size">Size</label>
<div class="input-group">
<input type="number" class="form-control" id="detail-font-size" min="50" max="200" step="10"/>
<div class="input-group-append">
<span class="input-group-text">%</span>
</div>
</div>
</div>
</div>
<h5>Monospace font</h5>
<div class="form-group row">
<div class="col-4">
<label for="monospace-font-family">Font family</label>
<select class="form-control" id="monospace-font-family"></select>
</div>
<div class="col-4">
<label for="monospace-font-size">Size</label>
<div class="input-group">
<input type="number" class="form-control" id="monospace-font-size" 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" id="reload-frontend-button">reload frontend</button>
</p>
</form>`;
export default class ApperanceOptions {
constructor() {
$("#options-appearance").html(TPL);
this.$themeSelect = $("#theme-select");
this.$zoomFactorSelect = $("#zoom-factor-select");
this.$nativeTitleBarSelect = $("#native-title-bar-select");
this.$headingStyle = $("#heading-style");
this.$themeSelect = $("#theme-select");
this.$overrideThemeFonts = $("#override-theme-fonts");
this.$overridenFontSettings = $("#overriden-font-settings");
this.$mainFontSize = $("#main-font-size");
this.$mainFontFamily = $("#main-font-family");
this.$treeFontSize = $("#tree-font-size");
this.$treeFontFamily = $("#tree-font-family");
this.$detailFontSize = $("#detail-font-size");
this.$detailFontFamily = $("#detail-font-family");
this.$monospaceFontSize = $("#monospace-font-size");
this.$monospaceFontFamily = $("#monospace-font-family");
$("#reload-frontend-button").on("click", () => utils.reloadFrontendApp("font changes"));
this.$body = $("body");
this.$themeSelect.on('change', async () => {
@ -103,6 +204,14 @@ export default class ApperanceOptions {
utils.reloadFrontendApp("theme change");
});
this.$overrideThemeFonts.on('change', async () => {
const isOverriden = this.$overrideThemeFonts.is(":checked");
await server.put('options/overrideThemeFonts/' + isOverriden.toString());
this.$overridenFontSettings.toggle(isOverriden);
});
this.$zoomFactorSelect.on('change', () => { appContext.triggerCommand('setZoomFactorAndSave', {zoomFactor: this.$zoomFactorSelect.val()}); });
this.$nativeTitleBarSelect.on('change', () => {
@ -119,23 +228,16 @@ export default class ApperanceOptions {
server.put('options/headingStyle/' + newHeadingStyle);
});
this.$mainFontSize.on('change', async () => {
await server.put('options/mainFontSize/' + this.$mainFontSize.val());
const optionsToSave = [
'mainFontFamily', 'mainFontSize',
'treeFontFamily', 'treeFontSize',
'detailFontFamily', 'detailFontSize',
'monospaceFontFamily', 'monospaceFontSize'
];
this.applyFontSizes();
});
this.$treeFontSize.on('change', async () => {
await server.put('options/treeFontSize/' + this.$treeFontSize.val());
this.applyFontSizes();
});
this.$detailFontSize.on('change', async () => {
await server.put('options/detailFontSize/' + this.$detailFontSize.val());
this.applyFontSizes();
});
for (const optionName of optionsToSave) {
this['$' + optionName].on('change', () => server.put(`options/${optionName}/${this['$' + optionName].val()}`));
}
}
toggleBodyClass(prefix, value) {
@ -149,6 +251,17 @@ export default class ApperanceOptions {
}
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');
this.$headingStyle.val(options.headingStyle);
const themes = [
{ val: 'white', title: 'White' },
{ val: 'dark', title: 'Dark' }
@ -165,25 +278,32 @@ export default class ApperanceOptions {
this.$themeSelect.val(options.theme);
if (utils.isElectron()) {
this.$zoomFactorSelect.val(options.zoomFactor);
}
else {
this.$zoomFactorSelect.prop('disabled', true);
}
this.$nativeTitleBarSelect.val(options.nativeTitleBarVisible === 'true' ? 'show' : 'hide');
this.$headingStyle.val(options.headingStyle);
this.$overrideThemeFonts.prop('checked', 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);
console.log(options);
this.$monospaceFontSize.val(options.monospaceFontSize);
this.fillFontFamilyOptions(this.$monospaceFontFamily, options.monospaceFontFamily);
}
applyFontSizes() {
this.$body.get(0).style.setProperty("--main-font-size", this.$mainFontSize.val() + "%");
this.$body.get(0).style.setProperty("--tree-font-size", this.$treeFontSize.val() + "%");
this.$body.get(0).style.setProperty("--detail-font-size", this.$detailFontSize.val() + "%");
fillFontFamilyOptions($select, currentValue) {
$select.empty();
for (const {value, label} of FONT_FAMILIES) {
$select.append($("<option>")
.attr("value", value)
.prop("selected", value === currentValue)
.text(label));
}
}
}

View File

@ -33,7 +33,7 @@ const TPL = `
<div class="note-detail-editable-text note-detail-printable">
<style>
.note-detail-editable-text {
font-family: var(--detail-text-font-family);
font-family: var(--detail-font-family);
padding-left: 14px;
padding-top: 10px;
}

View File

@ -31,7 +31,7 @@ const TPL = `
.note-detail-readonly-text {
padding-left: 24px;
padding-top: 10px;
font-family: var(--detail-text-font-family);
font-family: var(--detail-font-family);
min-height: 50px;
}

View File

@ -58,7 +58,7 @@ table td, table th {
}
code, kbd, pre, samp {
font-family: var(--font-family-monospace);
font-family: var(--monospace-font-family);
}
.input-group-text {
@ -227,7 +227,7 @@ div.ui-tooltip {
}
.CodeMirror * {
font-family: var(--font-family-monospace) !important;
font-family: var(--monospace-font-family) !important;
}
.CodeMirror-gutters {

View File

@ -8,8 +8,8 @@
--detail-font-family: MontserratLight;
--detail-font-size: normal;
--font-family-monospace: JetBrainsLight;
--detail-text-font-family: MontserratLight;
--monospace-font-family: JetBrainsLight;
--monospace-font-size: normal;
--main-background-color: #333;
--main-text-color: #ccc;

View File

@ -11,8 +11,8 @@ html {
--detail-font-family: MontserratLight;
--detail-font-size: normal;
--font-family-monospace: JetBrainsLight;
--detail-text-font-family: MontserratLight;
--monospace-font-family: JetBrainsLight;
--monospace-font-size: normal;
--main-background-color: white;
--main-text-color: black;

33
src/routes/api/fonts.js Normal file
View File

@ -0,0 +1,33 @@
const optionService = require('../../services/options');
function getFontCss(req, res) {
res.setHeader('Content-Type', 'text/css');
if (!optionService.getOptionBool('overrideThemeFonts')) {
res.send('');
return;
}
const optionsMap = optionService.getOptionsMap();
// using body to be more specific than themes' :root
res.send(`
body {
--main-font-family: ${optionsMap.mainFontFamily};
--main-font-size: ${optionsMap.mainFontSize}%;
--tree-font-family: ${optionsMap.treeFontFamily};
--tree-font-size: ${optionsMap.treeFontSize}%;
--detail-font-family: ${optionsMap.detailFontFamily};
--detail-font-size: ${optionsMap.detailFontSize}%;
--monospace-font-family: ${optionsMap.monospaceFontFamily};
--monospace-font-size: ${optionsMap.monospaceFontSize};
}`);
}
module.exports = {
getFontCss
};

View File

@ -17,8 +17,13 @@ const ALLOWED_OPTIONS = new Set([
'syncProxy',
'hoistedNoteId',
'mainFontSize',
'mainFontFamily',
'treeFontSize',
'treeFontFamily',
'detailFontSize',
'detailFontFamily',
'monospaceFontSize',
'monospaceFontFamily',
'openTabs',
'noteInfoWidget',
'attributesWidget',
@ -44,7 +49,8 @@ const ALLOWED_OPTIONS = new Set([
'headingStyle',
'autoCollapseNoteTree',
'autoReadonlySizeText',
'autoReadonlySizeCode'
'autoReadonlySizeCode',
'overrideThemeFonts'
]);
function getOptions() {

View File

@ -38,6 +38,7 @@ const similarNotesRoute = require('./api/similar_notes');
const keysRoute = require('./api/keys');
const backendLogRoute = require('./api/backend_log');
const statsRoute = require('./api/stats');
const fontsRoute = require('./api/fonts');
const log = require('../services/log');
const express = require('express');
@ -326,6 +327,8 @@ function register(app) {
apiRoute(POST, '/api/delete-notes-preview', notesApiRoute.getDeleteNotesPreview);
route(GET, '/api/fonts', [auth.checkApiAuthOrElectron], fontsRoute.getFontCss);
app.use('', router);
}

View File

@ -56,17 +56,15 @@ const defaultOptions = [
{ name: 'noteRevisionSnapshotTimeInterval', value: '600', isSynced: true },
{ name: 'protectedSessionTimeout', value: '600', isSynced: true },
{ name: 'zoomFactor', value: '1.0', isSynced: false },
{ name: 'overrideThemeFont', value: 'false', isSynced: false },
{ name: 'mainFontFamily', value: 'sans-serif', isSynced: false },
{ name: 'mainFontSize', value: '100', isSynced: false },
{ name: 'treeFontFamily', value: 'sans-serif', isSynced: false },
{ name: 'treeFontSize', value: '100', isSynced: false },
{ name: 'detailFontFamily', value: 'sans-serif', isSynced: false },
{ name: 'detailFontSize', value: '110', isSynced: false },
{ name: 'calendarWidget', value: '{"enabled":true,"expanded":true,"position":20}', isSynced: false },
{ name: 'editedNotesWidget', value: '{"enabled":true,"expanded":true,"position":50}', isSynced: false },
{ name: 'noteInfoWidget', value: '{"enabled":true,"expanded":true,"position":100}', isSynced: false },
{ name: 'attributesWidget', value: '{"enabled":true,"expanded":true,"position":200}', isSynced: false },
{ name: 'linkMapWidget', value: '{"enabled":true,"expanded":true,"position":300}', isSynced: false },
{ name: 'noteRevisionsWidget', value: '{"enabled":true,"expanded":true,"position":400}', isSynced: false },
{ name: 'whatLinksHereWidget', value: '{"enabled":false,"expanded":true,"position":500}', isSynced: false },
{ name: 'similarNotesWidget', value: '{"enabled":true,"expanded":true,"position":600}', isSynced: false },
{ name: 'monospaceFontFamily', value: 'monospace', isSynced: false },
{ name: 'monospaceFontSize', value: '110', isSynced: false },
{ name: 'spellCheckEnabled', value: 'true', isSynced: false },
{ name: 'spellCheckLanguageCode', value: 'en-US', isSynced: false },
{ name: 'imageMaxWidthHeight', value: '1200', isSynced: true },

View File

@ -88,7 +88,8 @@ async function createMainWindow() {
const parsedUrl = url.parse(targetUrl);
// we still need to allow internal redirects from setup and migration pages
if (!['localhost', '127.0.0.1'].includes(parsedUrl.hostname) || (parsedUrl.path && parsedUrl.path !== '/')) {
if (!['localhost', '127.0.0.1'].includes(parsedUrl.hostname) || (parsedUrl.path && parsedUrl.path !== '/' && parsedUrl.path !== '/?')) {
ev.preventDefault();
}
});

View File

@ -5,7 +5,7 @@
<link rel="shortcut icon" href="favicon.ico">
<title>Trilium Notes</title>
</head>
<body class="desktop heading-style-<%= headingStyle %>" style="--main-font-size: <%= mainFontSize %>%; --tree-font-size: <%= treeFontSize %>%; --detail-font-size: <%= detailFontSize %>%;">
<body class="desktop heading-style-<%= headingStyle %>">
<noscript>Trilium requires JavaScript to be enabled.</noscript>
<script>
@ -79,6 +79,7 @@
<script src="libraries/split.min.js"></script>
<link href="stylesheets/ckeditor-theme.css" rel="stylesheet">
<link href="api/fonts" rel="stylesheet">
<link href="stylesheets/theme-light.css" rel="stylesheet">
<% if (themeCssUrl) { %>

View File

@ -131,6 +131,7 @@
<script src="app/mobile.js" crossorigin type="module"></script>
<link href="api/fonts" rel="stylesheet">
<link href="stylesheets/ckeditor-theme.css" rel="stylesheet">
<% if (themeCssUrl) { %>
<link href="<%= themeCssUrl %>" rel="stylesheet">