diff --git a/assets/controllers/common/darkmode_controller.js b/assets/controllers/common/darkmode_controller.js index e7c18e67..71111166 100644 --- a/assets/controllers/common/darkmode_controller.js +++ b/assets/controllers/common/darkmode_controller.js @@ -18,43 +18,118 @@ */ import {Controller} from "@hotwired/stimulus"; -import Darkmode from "darkmode-js/src"; -import "darkmode-js" export default class extends Controller { - _darkmode; - connect() { - if (typeof window.getComputedStyle(document.body).mixBlendMode == 'undefined') { - console.warn("The browser does not support mix blend mode. Darkmode will not work."); + this.setMode(this.getMode()); + document.querySelectorAll('input[name="darkmode"]').forEach((radio) => { + radio.addEventListener('change', this._radioChanged.bind(this)); + }); + } + + /** + * Event listener for the change of radio buttons + * @private + */ + _radioChanged(event) { + const new_mode = this.getSelectedMode(); + this.setMode(new_mode); + } + + /** + * Get the current mode from the local storage + * @return {'dark', 'light', 'auto'} + */ + getMode() { + return localStorage.getItem('darkmode') ?? 'auto'; + } + + /** + * Set the mode in the local storage and apply it and change the state of the radio buttons + * @param mode + */ + setMode(mode) { + if (mode !== 'dark' && mode !== 'light' && mode !== 'auto') { + console.warn('Invalid darkmode mode: ' + mode); + mode = 'auto'; + } + + localStorage.setItem('darkmode', mode); + + this.setButtonMode(mode); + + if (mode === 'auto') { + this._setDarkmodeAuto(); + } else if (mode === 'dark') { + this._enableDarkmode(); + } else if (mode === 'light') { + this._disableDarkmode(); + } + } + + /** + * Get the selected mode via the radio buttons + * @return {'dark', 'light', 'auto'} + */ + getSelectedMode() { + return document.querySelector('input[name="darkmode"]:checked').value; + } + + /** + * Set the state of the radio buttons + * @param mode + */ + setButtonMode(mode) { + document.querySelector('input[name="darkmode"][value="' + mode + '"]').checked = true; + } + + /** + * Enable darkmode by adding the data-bs-theme="dark" to the html tag + * @private + */ + _enableDarkmode() { + //Add data-bs-theme="dark" to the html tag + document.documentElement.setAttribute('data-bs-theme', 'dark'); + } + + /** + * Disable darkmode by adding the data-bs-theme="light" to the html tag + * @private + */ + _disableDarkmode() { + //Set data-bs-theme to light + document.documentElement.setAttribute('data-bs-theme', 'light'); + } + + + /** + * Set the darkmode to auto and enable/disable it depending on the system settings, also add + * an event listener to change the darkmode if the system settings change + * @private + */ + _setDarkmodeAuto() { + if (this.getMode() !== 'auto') { return; } - try { - const darkmode = new Darkmode(); - this._darkmode = darkmode; - - //Unhide darkmode button - this._showWidget(); - - //Set the switch according to our current darkmode state - const toggler = document.getElementById("toggleDarkmode"); - toggler.checked = darkmode.isActivated(); - } - catch (e) - { - console.error(e); + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + this._enableDarkmode(); + } else { + this._disableDarkmode(); } - + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { + console.log('Prefered color scheme changed to ' + event.matches ? 'dark' : 'light'); + this._setDarkmodeAuto(); + }); } - _showWidget() { - this.element.classList.remove('hidden'); - } - - toggleDarkmode() { - this._darkmode.toggle(); + /** + * Check if darkmode is activated + * @return {boolean} + */ + isDarkmodeActivated() { + return document.documentElement.getAttribute('data-bs-theme') === 'dark'; } } \ No newline at end of file diff --git a/assets/css/app/darkmode.css b/assets/css/app/darkmode.css deleted file mode 100644 index 8ef745f4..00000000 --- a/assets/css/app/darkmode.css +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). - * - * Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -.darkmode-layer { - z-index: 2020; -} - -/** If darkmode is enabled revert the blening for images and videos, as these should be shown not inverted */ -.darkmode--activated img, -.darkmode--activated video, -.darkmode--activated object { - mix-blend-mode: difference; -} - -.darkmode--activated .hoverpic:hover { - background: black; -} - -.tools-ic-logos img { - mix-blend-mode: normal; -} \ No newline at end of file diff --git a/assets/js/app.js b/assets/js/app.js index 8242331f..fd7db935 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -22,7 +22,6 @@ import '../css/app/layout.css'; import '../css/app/helpers.css'; -import '../css/app/darkmode.css'; import '../css/app/tables.css'; import '../css/app/bs-overrides.css'; import '../css/app/treeview.css'; diff --git a/assets/js/register_events.js b/assets/js/register_events.js index 06f48ec1..d9b21ee9 100644 --- a/assets/js/register_events.js +++ b/assets/js/register_events.js @@ -62,7 +62,7 @@ class RegisterEventHelper { this.registerLoadHandler(() => { $(".tooltip").remove(); //Exclude dropdown buttons from tooltips, otherwise we run into endless errors from bootstrap (bootstrap.esm.js:614 Bootstrap doesn't allow more than one instance per element. Bound instance: bs.dropdown.) - $('a[title], button[title]:not([data-bs-toggle="dropdown"]), p[title], span[title], h6[title], h3[title], i.fas[title]') + $('a[title], label[title], button[title]:not([data-bs-toggle="dropdown"]), p[title], span[title], h6[title], h3[title], i.fas[title]') //@ts-ignore .tooltip("hide").tooltip({container: "body", placement: "auto", boundary: 'window'}); }); diff --git a/package.json b/package.json index 8c5d7599..d21e8da6 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,6 @@ "bs-custom-file-input": "^1.3.4", "clipboard": "^2.0.4", "compression-webpack-plugin": "^10.0.0", - "darkmode-js": "^1.5.0", "datatables.net-bs5": "^1.10.20", "datatables.net-buttons-bs5": "^2.2.2", "datatables.net-colreorder-bs5": "^1.5.1", diff --git a/templates/_navbar.html.twig b/templates/_navbar.html.twig index 14e40151..3ca68a21 100644 --- a/templates/_navbar.html.twig +++ b/templates/_navbar.html.twig @@ -1,6 +1,6 @@ {% import "helper.twig" as helper %} -