Added option to use Breeze Dark only if the client's dark mode is enabled (#276)

* Add option to enable / disable Breeze Dark depending on the client's system settings. This uses the prefers-color-scheme media query to determine whether to apply the theme or not.

Co-authored-by: bela <bela@firstnode.eu>
Co-authored-by: untbu <git@firstnode.eu>
This commit is contained in:
untbu 2021-11-01 10:59:03 +01:00 committed by GitHub
parent 9e9f8f7bd6
commit 6a74e6a4b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 356 additions and 10 deletions

View File

@ -3,3 +3,4 @@
- cyrosy <github@cyrosy.fr>
- Esteban Flores <esflores@microsoft.com>
- Valdnet <47037905+Valdnet@users.noreply.github.com>
- untbu <git@firstnode.eu>

View File

@ -2,6 +2,10 @@
## [Unreleased]
### Added
- [#98](https://github.com/mwalbeck/nextcloud-breeze-dark/issues/98) Added option to use Breeze Dark only if the client's dark mode is enabled
## 22.0.2 - 2021-10-03
### Added

190
css/guest-automatic.css Normal file
View File

@ -0,0 +1,190 @@
/**
* Breeze Dark theme for Nextcloud
*
* @copyright Copyright (c) 2019, Magnus Walbeck <mw@mwalbeck.org>
*
* @license GNU AGPL version 3 or any later version, see COPYING file for more.
*/
@media (prefers-color-scheme: dark) {
:root {
/* Primary Breeze colours */
--color-paper-white: rgba(252, 252, 252, 1);
--color-cardboard-gray: rgba(239, 240, 241, 1);
--color-icon-gray: rgba(77, 77, 77, 1);
--color-charcoal-gray: rgba(49, 54, 59, 1);
--color-shade-black: rgba(35, 38, 41, 1);
--color-plasma-blue: rgba(61, 174, 233, 1);
/* Secondary Breeze colours */
--color-icon-red: rgba(218, 68, 83, 1);
--color-danger-red: rgba(237, 21, 21, 1);
--color-beware-orange: rgba(246, 116, 0, 1);
--color-icon-yellow: rgba(253, 188, 75, 1);
--color-sunbeam-yellow: rgba(201, 206, 59, 1);
--color-verdant-green: rgba(17, 209, 22, 1);
--color-icon-blue: rgba(29, 153, 243, 1);
/* Other Breeze Colours */
--color-noble-fir: rgba(39, 174, 96, 1);
--color-abyss-blue: rgba(41, 128, 185, 1);
--color-coastal-fog: rgba(127, 140, 141, 1);
--color-alternate-gray: rgba(189, 195, 199, 1);
/* An approximation of the blue hover colour seen in breeze dark */
--color-hover-blue: rgba(61, 174, 233, 0.4);
/* An approximation of the grey border colour seen in breeze dark */
--color-border-grey: rgba(103, 107, 110, 1);
/*Grey translucent colour for dashboard */
--color-dashboard-grey: rgba(49, 54, 59, 0.8);
--color-main-text: var(--color-cardboard-gray) !important;
--color-main-background: var(--color-charcoal-gray) !important;
--color-main-background-translucent: var(--color-main-background) !important;
--color-background-hover: var(--color-hover-blue) !important;
--color-background-dark: var(--color-main-background) !important;
--color-background-darker: var(--color-shade-black) !important;
--color-background-translucent: var(--color-dashboard-grey) !important;
--color-primary: var(--color-plasma-blue) !important;
--color-primary-light: var(--color-primary) !important;
--color-primary-text: var(--color-paper-white) !important;
--color-primary-text-dark: var(--color-main-text) !important;
--color-primary-element: var(--color-primary) !important;
--color-primary-element-light: var(--color-primary) !important;
--color-error: var(--color-icon-red) !important;
--color-warning: var(--color-beware-orange) !important;
--color-neutral: var(--color-sunbeam-yellow) !important;
--color-success: var(--color-noble-fir) !important;
--color-text-maxcontrast: var(--color-alternate-gray) !important;
--color-text-light: var(--color-main-text) !important;
--color-text-lighter: var(--color-text-maxcontrast) !important;
--color-text-dark: rgba(0, 0, 0, 1) !important;
--color-text-selection: var(--color-hover-blue) !important;
--color-text-link: rgba(30, 168, 226, 1) !important;
--color-loading-light: var(--color-alternate-gray) !important;
--color-loading-dark: var(--color-coastal-fog) !important;
--color-box-shadow: rgba(0, 0, 0, 0) !important;
--color-border: var(--color-border-grey) !important;
--color-border-dark: var(--color-border) !important;
--color-icon: rgba(242, 242, 242, 1);
}
/* Login Screen ------------------------------------------------------------- */
#body-login {
background-color: var(--color-main-background) !important;
background-image: url("../../../apps/theming/image/background"),
url("../../../core/img/background.png") !important;
}
#body-login a,
#body-login p.info {
color: var(--color-main-text) !important;
}
#body-login input[type="text"],
#body-login input[type="tel"],
#body-login input[type="password"],
#body-login input[type="email"] {
background: var(--color-background-darker) !important;
color: var(--color-main-text) !important;
}
#body-login input[type="tel"] {
border: 1px solid var(--color-border);
}
#body-login .groupbottom input {
box-shadow: unset !important;
}
#body-login .toggle-password,
#body-login #email-icon {
filter: invert(95%);
}
#body-login input[type="submit"],
#body-login input[type="submit"].primary,
#body-login input[type="button"],
#body-login button.primary,
#body-login .button {
background-color: var(--color-main-background) !important;
border: 1px solid var(--color-border) !important;
color: var(--color-main-text) !important;
}
#body-login input[type="submit"]:hover,
#body-login input[type="submit"].primary:hover,
#body-login input[type="button"]:hover,
#body-login button.primary:hover,
#body-login .button:hover {
border-color: var(--color-primary-element) !important;
opacity: 1;
}
#body-login input[type="submit"]:active,
#body-login input[type="submit"]:focus,
#body-login input[type="submit"].primary:active,
#body-login input[type="submit"].primary:focus,
#body-login input[type="button"]:active,
#body-login input[type="button"]:focus,
#body-login button.primary:active,
#body-login button.primary:focus,
#body-login .button:active,
#body-login .button:focus {
background-color: var(--color-primary) !important;
border-color: var(--color-primary-element) !important;
}
#body-login .two-factor-provider:hover,
#body-login .two-factor-provider:focus,
#body-login .two-factor-provider:active {
background-color: var(--color-background-hover);
border-color: var(--color-primary-element) !important;
}
#body-login .warning input[type="password"] {
border: 1px solid var(--color-border);
}
#body-login .warning input[type="submit"] {
background-color: inherit !important;
border: unset !important;
}
/* SAML Login */
#saml-select-user-back-end {
box-sizing: border-box;
margin: 0 auto;
width: 260px;
}
#saml-select-user-back-end .login-option {
background-color: var(--color-main-background);
border-color: var(--color-border);
border-radius: 100px;
box-sizing: border-box;
height: 50px;
min-width: 260px;
}
#saml-select-user-back-end .login-option:hover {
background-color: var(--color-primary);
border-color: var(--color-primary-element);
}
#saml-select-user-back-end .login-option a {
line-height: 50px;
}
#saml-select-user-back-end .login-option a:hover {
text-decoration: none;
}
}

34
css/server-automatic.scss Normal file
View File

@ -0,0 +1,34 @@
/**
* =============================================================================
* Breeze Dark for Nextcloud
* Source code: https://github.com/mwalbeck/nextcloud-breeze-dark
* Made with the help of contributors! See AUTHORS.md
* =============================================================================
*
* @copyright Copyright (C) 2017 Magnus Walbeck <mw@mwalbeck.org>
*
* @author Magnus Walbeck <mw@mwalbeck.org>
*
* @license GNU AGPL version 3 or any later version
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
:root {
--breezedark-automatic-activation-enabled: 1;
}
@media (prefers-color-scheme: dark) {
@import "server";
}

View File

@ -21,7 +21,22 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
document.addEventListener("DOMContentLoaded", function () {
document.body.classList.add("theme--dark", "theme--breezedark");
document.body.classList.remove("theme--light");
});
const cssMediaDark = window.matchMedia("(prefers-color-scheme: dark)");
function updateColorSheme() {
if (
getComputedStyle(document.body).getPropertyValue(
"--breezedark-automatic-activation-enabled"
) != 1 ||
cssMediaDark.matches
) {
document.body.classList.add("theme--dark", "theme--breezedark");
document.body.classList.remove("theme--light");
} else {
document.body.classList.remove("theme--dark", "theme--breezedark");
document.body.classList.add("theme--light");
}
}
cssMediaDark.addEventListener("change", updateColorSheme);
document.addEventListener("DOMContentLoaded", updateColorSheme);

View File

@ -44,6 +44,11 @@ window.addEventListener("DOMContentLoaded", function () {
$("#breezedark-theme-enabled").change(function () {
$.post(OC.generateUrl("apps/breezedark/settings/admin"), {
theme_enabled: this.checked ? 1 : 0,
theme_automatic_activation_enabled: $("#breezedark-automatic-activation-enabled").prop(
"checked"
)
? 1
: 0,
theme_login_page: $("#breezedark-theme-login-page").prop("checked") ? 1 : 0,
})
.done(function () {
@ -60,12 +65,41 @@ window.addEventListener("DOMContentLoaded", function () {
"disabled",
!$("#breezedark-theme-enabled").prop("checked")
);
$("#breezedark-automatic-activation-enabled").prop(
"disabled",
!$("#breezedark-theme-enabled").prop("checked")
);
});
$("#breezedark-automatic-activation-enabled").change(function () {
$.post(OC.generateUrl("apps/breezedark/settings/admin"), {
theme_enabled: $("#breezedark-theme-enabled").prop("checked") ? 1 : 0,
theme_automatic_activation_enabled: this.checked ? 1 : 0,
theme_login_page: $("#breezedark-theme-login-page").prop("checked") ? 1 : 0,
})
.done(function () {
postSuccess(
"label[for='breezedark-automatic-activation-enabled']",
"breezedark-theme-automatic-activation-enabled-msg"
);
})
.fail(function () {
postError(
"label[for='breezedark-automatic-activation-enabled']",
"breezedark-theme-automatic-activation-enabled-msg"
);
});
});
$("#breezedark-theme-login-page").change(function () {
$.post(OC.generateUrl("apps/breezedark/settings/admin"), {
theme_login_page: this.checked ? 1 : 0,
theme_enabled: $("#breezedark-theme-enabled").prop("checked") ? 1 : 0,
theme_automatic_activation_enabled: $("#breezedark-automatic-activation-enabled").prop(
"checked"
)
? 1
: 0,
})
.done(function () {
postSuccess(

View File

@ -26,6 +26,11 @@ window.addEventListener("DOMContentLoaded", function () {
$("#breezedark-enabled").change(function () {
$.post(OC.generateUrl("apps/breezedark/settings"), {
theme_enabled: this.checked ? 1 : 0,
theme_automatic_activation_enabled: $("#breezedark-automatic-activation-enabled").prop(
"checked"
)
? 1
: 0,
})
.done(function () {
$("label[for='breezedark-enabled']").append(
@ -47,5 +52,36 @@ window.addEventListener("DOMContentLoaded", function () {
$("#breezedark-enabled-msg").remove();
}, 3000);
});
$("#breezedark-automatic-activation-enabled").prop(
"disabled",
!$("#breezedark-enabled").prop("checked")
);
});
$("#breezedark-automatic-activation-enabled").change(function () {
$.post(OC.generateUrl("apps/breezedark/settings"), {
theme_enabled: $("#breezedark-enabled").prop("checked") ? 1 : 0,
theme_automatic_activation_enabled: this.checked ? 1 : 0,
})
.done(function () {
$("label[for='breezedark-automatic-activation-enabled']").append(
" <span id='breezedark-automatic-activation-enabled-msg' class='msg success'>" +
t("breezedark", "Saved") +
"</span>"
);
setTimeout(function () {
$("#breezedark-automatic-activation-enabled-msg").remove();
}, 3000);
})
.fail(function () {
$("label[for='breezedark-automatic-activation-enabled']").append(
" <span id='breezedark-automatic-activation-enabled-msg' class='msg error'>" +
t("breezedark", "Error") +
"</span>"
);
setTimeout(function () {
$("#breezedark-automatic-activation-enabled-msg").remove();
}, 3000);
});
});
});

View File

@ -74,13 +74,14 @@ class Application extends App implements IBootstrap
$default = $config->getAppValue($this->appName, "theme_enabled", "0");
$loginPage = $config->getAppValue($this->appName, "theme_login_page", "1");
$cachebuster = $config->getAppValue($this->appName, "theme_cachebuster", "0");
$automaticActivation = $config->getAppValue($this->appName, "theme_automatic_activation_enabled", "0");
if (!is_null($user) and $config->getUserValue($user->getUID(), $this->appName, "theme_enabled", $default)) {
// When shown the 2FA login page you are logged in while also being on a login page,
// so a logged in user still needs the guests.css stylesheet
$this->addStyling($urlGenerator, $loginPage, $cachebuster);
$this->addStyling($urlGenerator, $loginPage, $cachebuster, $config->getUserValue($user->getUID(), $this->appName, "theme_automatic_activation_enabled", $automaticActivation));
} elseif (is_null($user) and $default) {
$this->addStyling($urlGenerator, $loginPage, $cachebuster);
$this->addStyling($urlGenerator, $loginPage, $cachebuster, $automaticActivation);
}
}
@ -90,15 +91,24 @@ class Application extends App implements IBootstrap
* @param IURLGenerator $urlGenerator
* @param string $loginPage
* @param string $cachebuster
* @param string $automaticActivation
*/
public function addStyling(IURLGenerator $urlGenerator, string $loginPage, string $cachebuster): void
public function addStyling(IURLGenerator $urlGenerator, string $loginPage, string $cachebuster, string $automaticActivation): void
{
Util::addStyle($this->appName, 'server');
if ($automaticActivation) {
Util::addStyle($this->appName, 'server-automatic');
} else {
Util::addStyle($this->appName, 'server');
}
Util::addScript($this->appName, 'breezedark');
// If the styling for the login page is wanted, load the stylesheet.
if ($loginPage) {
Util::addStyle($this->appName, 'guest');
if ($automaticActivation) {
Util::addStyle($this->appName, 'guest-automatic');
} else {
Util::addStyle($this->appName, 'guest');
}
}
// Only request the stylesheet if there is any styling to request

View File

@ -74,6 +74,12 @@ class SettingsController extends Controller
} else {
$this->config->setUserValue($this->userId, $this->appName, "theme_enabled", "0");
}
if ($this->request->getParam("theme_automatic_activation_enabled")) {
$this->config->setUserValue($this->userId, $this->appName, "theme_automatic_activation_enabled", "1");
} else {
$this->config->setUserValue($this->userId, $this->appName, "theme_automatic_activation_enabled", "0");
}
}
/**
@ -92,6 +98,12 @@ class SettingsController extends Controller
} else {
$this->config->setAppValue($this->appName, "theme_login_page", "0");
}
if ($this->request->getParam("theme_automatic_activation_enabled")) {
$this->config->setAppValue($this->appName, "theme_automatic_activation_enabled", "1");
} else {
$this->config->setAppValue($this->appName, "theme_automatic_activation_enabled", "0");
}
}
/**

View File

@ -61,10 +61,12 @@ class Admin implements ISettings
{
$themeEnabled = $this->config->getAppValue($this->appName, 'theme_enabled', "0");
$themeLoginPage = $this->config->getAppValue($this->appName, 'theme_login_page', "1");
$themeAutomaticActivation = $this->config->getAppValue($this->appName, 'theme_automatic_activation_enabled', "0");
$themeCustomStyling = $this->config->getAppValue($this->appName, 'theme_custom_styling', "");
return new TemplateResponse('breezedark', 'admin', [
"themeEnabled" => $themeEnabled,
"themeLoginPage" => $themeLoginPage,
"themeAutomaticActivation" => $themeAutomaticActivation,
"themeCustomStyling" => $themeCustomStyling
]);
}

View File

@ -73,9 +73,12 @@ class Personal implements ISettings
public function getForm(): TemplateResponse
{
$default = $this->config->getAppValue($this->appName, 'theme_enabled', "0");
$defaultAutomaticActivation = $this->config->getAppValue($this->appName, 'theme_automatic_activation_enabled', "0");
$themeEnabled = $this->config->getUserValue($this->userId, $this->appName, 'theme_enabled', $default);
$themeAutomaticActivation = $this->config->getUserValue($this->userId, $this->appName, 'theme_automatic_activation_enabled', $defaultAutomaticActivation);
return new TemplateResponse('breezedark', 'personal', [
"themeEnabled" => $themeEnabled,
"themeAutomaticActivation" => $themeAutomaticActivation,
"appWebPath" => $this->appWebPath
]);
}

View File

@ -33,6 +33,9 @@ script('breezedark', 'settings-admin');
<p><?php p($l->t("This setting will enable the theme by default, for any unauthenticated users and users who haven't set a preference.")); ?></p>
<input type="checkbox" class="checkbox" id="breezedark-theme-enabled" <?php p($themeEnabled ? "checked" : ""); ?>>
<label for="breezedark-theme-enabled"><?php p($l->t("Enable Breeze Dark theme by default")); ?></label>
<p><?php p($l->t("This setting will enable the automated activation by the clients system settings by default, for any unauthenticated users and users who haven't set a preference.")); ?></p>
<input type="checkbox" class="checkbox" id="breezedark-automatic-activation-enabled" <?php p($themeEnabled ? "" : "disabled");?> <?php p($themeAutomaticActivation ? "checked" : ""); ?>>
<label for="breezedark-automatic-activation-enabled"><?php p($l->t("Enable Breeze Dark automated activation by the clients system settings by default")); ?></label>
<p><?php p($l->t("This setting will allow you to choose if the login page should be themed when the theme is enabled by default.")); ?></p>
<input type="checkbox" class="checkbox" id="breezedark-theme-login-page" <?php p($themeEnabled ? "" : "disabled");?> <?php p($themeLoginPage ? "checked" : "");?>>
<label for="breezedark-theme-login-page"><?php p($l->t("Theme the login page")); ?></label>

View File

@ -38,6 +38,8 @@ script('breezedark', 'settings-personal');
<p><?php p($l->t("A Dark theme based on Breeze Dark by the KDE project. Please refresh the page for changes to take effect.")); ?></p>
<input type="checkbox" class="checkbox" id="breezedark-enabled" <?php p($themeEnabled ? "checked" : ""); ?>>
<label for="breezedark-enabled"><?php p($l->t("Enable Breeze Dark theme")); ?></label>
<input type="checkbox" class="checkbox" id="breezedark-automatic-activation-enabled" <?php p($themeEnabled ? "" : "disabled");?> <?php p($themeAutomaticActivation ? "checked" : ""); ?>>
<label for="breezedark-automatic-activation-enabled"><?php p($l->t("Enable Breeze Dark automated activation by clients system settings")); ?></label>
</div>
</div>
</div>