mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
switching themes via loading only specific CSS
This commit is contained in:
parent
2fcb0c05c0
commit
113bebed3b
BIN
db/demo.zip
BIN
db/demo.zip
Binary file not shown.
@ -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';
|
||||
|
@ -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()}); });
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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%;
|
||||
|
@ -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
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
@ -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 {
|
||||
|
75
src/public/stylesheets/theme-dark.css
Normal file
75
src/public/stylesheets/theme-dark.css
Normal 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);
|
||||
}
|
66
src/public/stylesheets/theme-light.css
Normal file
66
src/public/stylesheets/theme-light.css
Normal 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;
|
||||
}
|
@ -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 = {
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user