switching themes via loading only specific CSS

This commit is contained in:
zadam 2021-09-26 15:24:37 +02:00
parent 2fcb0c05c0
commit 113bebed3b
15 changed files with 219 additions and 232 deletions

Binary file not shown.

View File

@ -1,2 +1,4 @@
-- black theme has been removed, dark is closest replacement
UPDATE options SET value = 'dark' WHERE name = 'theme' AND value = 'black';
UPDATE options SET value = 'light' WHERE name = 'theme' AND value = 'white';

View File

@ -95,20 +95,12 @@ export default class ApperanceOptions {
this.$detailFontSize = $("#detail-font-size");
this.$body = $("body");
this.$themeSelect.on('change', () => {
this.$themeSelect.on('change', async () => {
const newTheme = this.$themeSelect.val();
this.toggleBodyClass("theme-", newTheme);
await server.put('options/theme/' + newTheme);
const noteId = $(this).find(":selected").attr("data-note-id");
if (noteId) {
// make sure the CSS is loaded
// if the CSS has been loaded and then updated then the changes won't take effect though
libraryLoader.requireCss(`api/notes/download/${noteId}`);
}
server.put('options/theme/' + newTheme);
utils.reloadFrontendApp("theme change");
});
this.$zoomFactorSelect.on('change', () => { appContext.triggerCommand('setZoomFactorAndSave', {zoomFactor: this.$zoomFactorSelect.val()}); });

View File

@ -23,19 +23,7 @@ function SetupModel() {
this.password1 = ko.observable();
this.password2 = ko.observable();
this.theme = ko.observable("white");
this.theme.subscribe(function(newTheme) {
const $body = $("body");
for (const clazz of Array.from($body[0].classList)) { // create copy to safely iterate over while removing classes
if (clazz.startsWith("theme-")) {
$body.removeClass(clazz);
}
}
$body.addClass("theme-" + newTheme);
});
this.theme = ko.observable("light");
this.syncServerHost = ko.observable();
this.syncProxy = ko.observable();

View File

@ -14,7 +14,7 @@ const TPL = `
}
.global-menu-button {
background-image: url("images/icon-color.png");
background-image: url("images/icon-black.png");
background-repeat: no-repeat;
background-position: 50% 45%;
width: 100%;

View File

@ -229,7 +229,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
"libraries/katex/katex.min.css",
"stylesheets/print.css",
"stylesheets/relation_map.css",
"stylesheets/themes.css"
"stylesheets/ckeditor-theme.css"
],
debug: true
});

View File

@ -1,143 +1,3 @@
:root {
--main-font-family: MontserratLight;
--main-font-size: normal;
--tree-font-family: MontserratLight;
--tree-font-size: normal;
--detail-font-family: MontserratLight;
--detail-font-size: normal;
--font-family-monospace: JetBrainsLight;
--detail-text-font-family: MontserratLight;
--main-background-color: white;
--main-text-color: black;
--main-border-color: #ccc;
--accented-background-color: #f5f5f5;
--more-accented-background-color: #ddd;
--button-background-color: transparent;
--button-disabled-background-color: #ddd;
--button-border-color: #ddd;
--button-text-color: black;
--button-border-radius: 5px;
--primary-button-background-color: #6c757d;
--primary-button-text-color: white;
--primary-button-border-color: #6c757d;
--muted-text-color: #666;
--input-text-color: black;
--input-background-color: transparent;
--hover-item-text-color: black;
--hover-item-background-color: #ddd;
--active-item-text-color: black;
--active-item-background-color: #ddd;
--menu-text-color: black;
--menu-background-color: white;
--modal-background-color: white;
--modal-backdrop-color: black;
--left-pane-background-color: #F3F3F3;
--left-pane-text-color: #333;
--launcher-pane-background-color: #F3F3F3;
--launcher-pane-text-color: #333;
--active-tab-background-color: #ddd;
--active-tab-text-color: black;
--inactive-tab-background-color: #f5f5f5;
--inactive-tab-text-color: #666;
--scrollbar-border-color: #ddd;
--tooltip-background-color: #f8f8f8;
--link-color: blue;
}
body.theme-dark {
--main-font-family: MontserratLight;
--main-font-size: normal;
--tree-font-family: MontserratLight;
--tree-font-size: normal;
--detail-font-family: MontserratLight;
--detail-font-size: normal;
--font-family-monospace: JetBrainsLight;
--detail-text-font-family: MontserratLight;
--main-background-color: #333;
--main-text-color: #ccc;
--main-border-color: #aaa;
--accented-background-color: #555;
--more-accented-background-color: #777;
--button-background-color: transparent;
--button-disabled-background-color: #222;
--button-border-color: #ccc;
--button-text-color: currentColor;
--button-border-radius: 5px;
--primary-button-background-color: #888;
--primary-button-text-color: white;
--primary-button-border-color: #999;
--muted-text-color: #bbb;
--input-text-color: #ccc;
--input-background-color: #333;
--hover-item-text-color: black;
--hover-item-background-color: #777;
--active-item-text-color: black;
--active-item-background-color: #777;
--menu-text-color: white;
--menu-background-color: #222;
--modal-background-color: #333;
--modal-backdrop-color: #444;
--left-pane-background-color: #1f1f1f;
--left-pane-text-color: #AAAAAA;
--launcher-pane-background-color: #1f1f1f;
--launcher-pane-text-color: #AAAAAA;
--active-tab-background-color: #666;
--active-tab-text-color: #ccc;
--inactive-tab-background-color: #444;
--inactive-tab-text-color: #bbb;
--scrollbar-border-color: #888;
--tooltip-background-color: #333;
--link-color: lightskyblue;
}
body.theme-dark .global-menu-button {
background-image: url("../images/icon-grey.png");
}
body.theme-dark ::-webkit-calendar-picker-indicator {
filter: invert(1);
}
body.theme-dark .CodeMirror {
filter: invert(90%) hue-rotate(180deg);
}
body {
/* -- Overrides generic colors. ------------------------------------------------------------- */
@ -242,39 +102,3 @@ body {
--ck-color-widget-type-around-button: var(--main-border-color);
--ck-color-widget-type-around-button-hover: var(--main-border-color);
}
body {
background-color: var(--main-background-color);
color: var(--main-text-color);
font-family: var(--main-font-family);
}
a, a:visited, a:hover {
color: var(--link-color);
}
input, select, textarea {
color: var(--input-text-color) !important;
background: var(--input-background-color) !important;
}
#left-pane input, select, textarea {
color: var(--left-pane-text-color) !important;
background: var(--left-pane-background-color) !important;
}
input::placeholder {
color: var(--muted-text-color);
}
table td, table th {
color: var(--main-text-color);
}
.ck .todo-list__checkmark {
top: 10px !important;
}
.modal-backdrop {
background-color: var(--modal-backdrop-color) !important;
}

View File

@ -18,6 +18,39 @@ body {
on the last line of the editor. */
position: fixed;
width: 100%;
background-color: var(--main-background-color);
color: var(--main-text-color);
font-family: var(--main-font-family);
}
a, a:visited, a:hover {
color: var(--link-color);
}
input, select, textarea {
color: var(--input-text-color) !important;
background: var(--input-background-color) !important;
}
#left-pane input, select, textarea {
color: var(--left-pane-text-color) !important;
background: var(--left-pane-background-color) !important;
}
input::placeholder {
color: var(--muted-text-color);
}
table td, table th {
color: var(--main-text-color);
}
.ck .todo-list__checkmark {
top: 10px !important;
}
.modal-backdrop {
background-color: var(--modal-backdrop-color) !important;
}
.component {

View File

@ -0,0 +1,75 @@
:root {
--main-font-family: MontserratLight;
--main-font-size: normal;
--tree-font-family: MontserratLight;
--tree-font-size: normal;
--detail-font-family: MontserratLight;
--detail-font-size: normal;
--font-family-monospace: JetBrainsLight;
--detail-text-font-family: MontserratLight;
--main-background-color: #333;
--main-text-color: #ccc;
--main-border-color: #aaa;
--accented-background-color: #555;
--more-accented-background-color: #777;
--button-background-color: transparent;
--button-disabled-background-color: #222;
--button-border-color: #ccc;
--button-text-color: currentColor;
--button-border-radius: 5px;
--primary-button-background-color: #888;
--primary-button-text-color: white;
--primary-button-border-color: #999;
--muted-text-color: #bbb;
--input-text-color: #ccc;
--input-background-color: #333;
--hover-item-text-color: black;
--hover-item-background-color: #777;
--active-item-text-color: black;
--active-item-background-color: #777;
--menu-text-color: white;
--menu-background-color: #222;
--modal-background-color: #333;
--modal-backdrop-color: #444;
--left-pane-background-color: #1f1f1f;
--left-pane-text-color: #AAAAAA;
--launcher-pane-background-color: #1f1f1f;
--launcher-pane-text-color: #AAAAAA;
--active-tab-background-color: #666;
--active-tab-text-color: #ccc;
--inactive-tab-background-color: #444;
--inactive-tab-text-color: #bbb;
--scrollbar-border-color: #888;
--tooltip-background-color: #333;
--link-color: lightskyblue;
}
body .global-menu-button {
background-image: url("../images/icon-grey.png");
}
body ::-webkit-calendar-picker-indicator {
filter: invert(1);
}
body .CodeMirror {
filter: invert(90%) hue-rotate(180deg);
}

View File

@ -0,0 +1,66 @@
/* Light theme is special since it's also baseline/default so when a theme does not define some variable then
value from this theme will be used. For this reason this theme uses "html" instead of ":root"
since it's less "specific" and thus serves as default */
html {
--main-font-family: MontserratLight;
--main-font-size: normal;
--tree-font-family: MontserratLight;
--tree-font-size: normal;
--detail-font-family: MontserratLight;
--detail-font-size: normal;
--font-family-monospace: JetBrainsLight;
--detail-text-font-family: MontserratLight;
--main-background-color: white;
--main-text-color: black;
--main-border-color: #ccc;
--accented-background-color: #f5f5f5;
--more-accented-background-color: #ddd;
--button-background-color: transparent;
--button-disabled-background-color: #ddd;
--button-border-color: #ddd;
--button-text-color: black;
--button-border-radius: 5px;
--primary-button-background-color: #6c757d;
--primary-button-text-color: white;
--primary-button-border-color: #6c757d;
--muted-text-color: #666;
--input-text-color: black;
--input-background-color: transparent;
--hover-item-text-color: black;
--hover-item-background-color: #ddd;
--active-item-text-color: black;
--active-item-background-color: #ddd;
--menu-text-color: black;
--menu-background-color: white;
--modal-background-color: white;
--modal-backdrop-color: black;
--left-pane-background-color: #F3F3F3;
--left-pane-text-color: #333;
--launcher-pane-background-color: #F3F3F3;
--launcher-pane-text-color: #333;
--active-tab-background-color: #ddd;
--active-tab-text-color: black;
--inactive-tab-background-color: #f5f5f5;
--inactive-tab-text-color: #666;
--scrollbar-border-color: #ddd;
--tooltip-background-color: #f8f8f8;
--link-color: blue;
}

View File

@ -19,7 +19,7 @@ function index(req, res) {
res.render(view, {
csrfToken: csrfToken,
theme: options.theme,
themeCssUrl: getThemeCssUrl(options.theme),
headingStyle: options.headingStyle,
mainFontSize: parseInt(options.mainFontSize),
treeFontSize: parseInt(options.treeFontSize),
@ -36,8 +36,28 @@ function index(req, res) {
});
}
function getThemeCssUrl(theme) {
if (theme === 'light') {
return false; // light theme is always loaded as baseline
}
if (theme === 'dark') {
return `stylesheets/theme-dark.css`;
}
else {
const themeNote = attributeService.getNoteWithLabel('appTheme', theme);
if (themeNote) {
return `api/notes/download/${themeNote.noteId}`;
}
else {
return false; // baseline light theme
}
}
}
function getAppCssNoteIds() {
return attributeService.getNoteIdsWithLabels(['appCss', 'appTheme']);
return attributeService.getNotesWithLabel('appCss').map(note => note.noteId);
}
module.exports = {

View File

@ -69,18 +69,6 @@ function getNotesWithLabel(name, value) {
});
}
function getNoteIdsWithLabels(names) {
const noteIds = new Set();
for (const name of names) {
for (const attr of becca.findAttributes('label', name)) {
noteIds.add(attr.noteId);
}
}
return Array.from(noteIds);
}
// TODO: should be in search service
function getNoteWithLabel(name, value) {
const notes = getNotesWithLabel(name, value);
@ -179,7 +167,6 @@ function sanitizeAttributeName(origName) {
module.exports = {
getNotesWithLabel,
getNoteIdsWithLabels,
getNoteWithLabel,
createLabel,
createRelation,

View File

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

View File

@ -131,7 +131,10 @@
<script src="app/mobile.js" crossorigin type="module"></script>
<link href="stylesheets/themes.css" rel="stylesheet">
<link href="stylesheets/ckeditor-theme.css" rel="stylesheet">
<% if (themeCssUrl) { %>
<link href="<%= themeCssUrl %>" rel="stylesheet">
<% } %>
<link href="stylesheets/style.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="libraries/boxicons/css/boxicons.min.css">

View File

@ -6,15 +6,6 @@
<title>Setup</title>
<style>
@font-face {
font-family: MontserratLight;
src: url(../fonts/Montserrat-Light.ttf);
}
body {
font-family: MontserratLight;
}
.lds-ring {
display: inline-block;
position: relative;
@ -101,8 +92,8 @@
<div style="display: flex; justify-content: space-around;">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="theme" id="theme-white" value="white" data-bind="checked: theme" checked>
<label class="form-check-label" for="theme-white">white</label>
<input class="form-check-input" type="radio" name="theme" id="theme-light" value="light" data-bind="checked: theme" checked>
<label class="form-check-label" for="theme-light">light</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="theme" id="theme-dark" value="dark" data-bind="checked: theme">
@ -217,6 +208,6 @@
<script src="libraries/knockout.min.js"></script>
<script src="app/setup.js" crossorigin type="module"></script>
<link href="stylesheets/themes.css" rel="stylesheet">
<link href="stylesheets/theme-light.css" rel="stylesheet">
</body>
</html>