فهرست منبع

Added: Dark mode for Origine +Origine compact themes (#4843)

* first draft

* fix: theme slider: properties box

* improved colors

* option to enable/disable dark mode

* fixes

* Update app/i18n/fr/conf.php

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>

* i18n english improved

* fix dark background color for favorites + hover colors

* select list: no, auto

Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
maTh 3 سال پیش
والد
کامیت
b5a418ec16

+ 2 - 0
app/Controllers/configureController.php

@@ -25,6 +25,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController {
 	 * The options available on the page are:
 	 *   - language (default: en)
 	 *   - theme (default: Origin)
+	 *   - darkMode (default: no)
 	 *   - content width (default: thin)
 	 *   - display of read action in header
 	 *   - display of favorite action in header
@@ -44,6 +45,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController {
 			FreshRSS_Context::$user_conf->language = Minz_Request::param('language', 'en');
 			FreshRSS_Context::$user_conf->timezone = Minz_Request::param('timezone', '');
 			FreshRSS_Context::$user_conf->theme = Minz_Request::param('theme', FreshRSS_Themes::$defaultTheme);
+			FreshRSS_Context::$user_conf->darkMode = Minz_Request::param('darkMode', 'no');
 			FreshRSS_Context::$user_conf->content_width = Minz_Request::param('content_width', 'thin');
 			FreshRSS_Context::$user_conf->topline_read = Minz_Request::param('topline_read', false);
 			FreshRSS_Context::$user_conf->topline_favorite = Minz_Request::param('topline_favorite', false);

+ 7 - 0
app/Models/ConfigurationSetter.php

@@ -234,6 +234,13 @@ class FreshRSS_ConfigurationSetter {
 		$data['sticky_post'] = $this->handleBool($value);
 	}
 
+	private function _darkMode(&$data, $value) {
+		if (!in_array($value, [ 'no', 'auto'], true)) {
+			$value = 'no';
+		}
+		$data['darkMode'] = $value;
+	}
+
 	private function _bottomline_date(&$data, $value) {
 		$data['bottomline_date'] = $this->handleBool($value);
 	}

+ 1 - 0
app/Models/UserConfiguration.php

@@ -53,6 +53,7 @@
  * @property bool $sides_close_article
  * @property bool $sticky_post
  * @property string $theme
+ * @property string $darkMode
  * @property string $token
  * @property bool $topline_date
  * @property bool $topline_display_authors

+ 1 - 0
app/i18n/cz/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Zobrazení',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Spodní řádek',
 			'display_authors' => 'Autoři',

+ 1 - 0
app/i18n/de/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Anzeige',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Fußzeile',
 			'display_authors' => 'Autoren',

+ 1 - 0
app/i18n/el/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Display',	// TODO
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Bottom line',	// TODO
 			'display_authors' => 'Authors',	// TODO

+ 1 - 0
app/i18n/en-us/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Display',	// IGNORE
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Bottom line',	// IGNORE
 			'display_authors' => 'Authors',	// IGNORE

+ 1 - 0
app/i18n/en/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Display',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Bottom line',
 			'display_authors' => 'Authors',

+ 1 - 0
app/i18n/es/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Visualización',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Línea inferior',
 			'display_authors' => 'Autores/Autoras',

+ 1 - 0
app/i18n/fr/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Affichage',
+		'darkMode' => 'Mode sombre automatique (bêta)',
 		'icon' => array(
 			'bottom_line' => 'Ligne du bas',
 			'display_authors' => 'Auteurs',

+ 1 - 0
app/i18n/he/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'תצוגה',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'שורה תחתונה',
 			'display_authors' => 'Authors',	// TODO

+ 1 - 0
app/i18n/id/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Display',	// TODO
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Bottom line',	// TODO
 			'display_authors' => 'Authors',	// TODO

+ 1 - 0
app/i18n/it/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Visualizzazione',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Barra in fondo',
 			'display_authors' => 'Autori',

+ 1 - 0
app/i18n/ja/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => '表示',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => '行の下部',
 			'display_authors' => '著者',

+ 1 - 0
app/i18n/ko/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => '표시',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => '하단',
 			'display_authors' => '저자',

+ 1 - 0
app/i18n/nl/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Opmaak',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Onderaan',
 			'display_authors' => 'Auteurs',

+ 1 - 0
app/i18n/oc/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Afichatge',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Linha enbàs',
 			'display_authors' => 'Autors',

+ 1 - 0
app/i18n/pl/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Wyświetlanie',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Dolny margines',
 			'display_authors' => 'Autorzy',

+ 1 - 0
app/i18n/pt-br/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Exibição',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Linha inferior',
 			'display_authors' => 'Autores',

+ 1 - 0
app/i18n/ru/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Отображение',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Нижняя линия',
 			'display_authors' => 'Авторы',

+ 1 - 0
app/i18n/sk/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Zobrazenie',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Spodný riadok',
 			'display_authors' => 'Autori',

+ 1 - 0
app/i18n/tr/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => 'Görünüm',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => 'Alt çizgi',
 			'display_authors' => 'Yazarlar',

+ 1 - 0
app/i18n/zh-cn/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => '显示',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => '底栏',
 			'display_authors' => '作者',

+ 1 - 0
app/i18n/zh-tw/conf.php

@@ -32,6 +32,7 @@ return array(
 	),
 	'display' => array(
 		'_' => '顯示',
+		'darkMode' => 'Automatic dark mode (beta)',	// TODO
 		'icon' => array(
 			'bottom_line' => '底欄',
 			'display_authors' => '作者',

+ 1 - 1
app/layout/layout.phtml

@@ -52,7 +52,7 @@ if (_t('gen.dir') === 'rtl') {
 		<meta name="robots" content="noindex,nofollow" />
 <?php } ?>
 	</head>
-	<body class="<?= Minz_Request::actionName() ?>">
+	<body class="<?= Minz_Request::actionName() ?><?= (FreshRSS_Context::$user_conf->darkMode === 'no') ? '' : ' darkMode_' . FreshRSS_Context::$user_conf->darkMode ?>">
 <?php
 	if (!Minz_Request::param('ajax')) {
 		flush();

+ 10 - 0
app/views/configure/display.phtml

@@ -95,6 +95,16 @@
 			</div>
 		</div>
 
+		<div class="form-group">
+			<label class="group-name" for="darkMode"><?= _t('conf.display.darkMode') ?></label>
+			<div class="group-controls">
+				<select name="darkMode" id="darkMode" data-leave-validation="<?= FreshRSS_Context::$user_conf->darkMode ?>">
+					<option value="no"<?php FreshRSS_Context::$user_conf->darkMode === 'no' ? ' selected' : '' ?>>No</option>
+					<option value="auto"<?php FreshRSS_Context::$user_conf->darkMode === 'auto' ? ' selected' : '' ?>>Auto</option>
+				</select>
+			</div>
+		</div>
+
 		<?php $width = FreshRSS_Context::$user_conf->content_width; ?>
 		<div class="form-group">
 			<label class="group-name" for="content_width"><?= _t('conf.display.width.content') ?></label>

+ 1 - 0
config-user.default.php

@@ -64,6 +64,7 @@ return array (
 		'site' => true,
 	),
 	'theme' => 'Origine',
+	'darkMode' => 'no',
 	'content_width' => 'thin',
 	'shortcuts' => array (
 		'actualize' => 'q',

+ 0 - 5
p/themes/Origine-compact/origine-compact.css

@@ -40,11 +40,6 @@ a.btn,
 }
 
 /*=== Dropdown */
-.item ~ .dropdown-header,
-.item.separator {
-	border-top-color: #ddd;
-}
-
 /*=== Alerts */
 /*=== Pagination */
 /*=== Boxes */

+ 0 - 5
p/themes/Origine-compact/origine-compact.rtl.css

@@ -40,11 +40,6 @@ a.btn,
 }
 
 /*=== Dropdown */
-.item ~ .dropdown-header,
-.item.separator {
-	border-top-color: #ddd;
-}
-
 /*=== Alerts */
 /*=== Pagination */
 /*=== Boxes */

+ 111 - 8
p/themes/Origine/origine.css

@@ -12,8 +12,10 @@
 	--background-color-hover: #f6f6f6;
 
 	--unread-article-background-color: #fff3ed;
+	--unread-article-background-color-hover: #faeee8;
 	--unread-article-border-color: #ff5300;
 	--favorite-article-background-color: #fff6da;
+	--favorite-article-background-color-hover: #fcf2d6;
 	--favorite-article-border-color: #ffc300;
 
 	--contrast-background-color: #0084cc;
@@ -825,34 +827,42 @@ a:hover .icon {
 	border-left: 2px solid var(--contrast-border-color-active);
 }
 
-.flux .flux_header:hover {
-	background-color: var(--background-color-hover) !important;
+.flux .flux_header:hover,
+.flux .flux_header:hover .item {
+	background-color: var(--background-color-hover);
 }
 
-.flux .flux_header:not(.current):hover .item.title {
-	background: inherit;
+.flux .flux_header:not(.current):hover .flux_header,
+.flux .flux_header:not(.current):hover .flux_header .item {
+	background-color: var(--background-color-hover);
 }
 
 .flux.not_read {
 	border-left: 2px solid var(--unread-article-border-color);
 }
 
-.flux.not_read .flux_header {
+.flux.not_read .flux_header .item {
 	background-color: var(--unread-article-background-color);
 }
 
-.flux.not_read:not(.current):hover .item.title {
-	background: inherit;
+.flux.not_read:not(.current):hover .flux_header,
+.flux.not_read:not(.current):hover .flux_header .item {
+	background-color: var(--unread-article-background-color-hover);
 }
 
 .flux.favorite {
 	border-left: 2px solid var(--favorite-article-border-color);
 }
 
-.flux.favorite:not(.current) {
+.flux.favorite:not(.current) .flux_header .item {
 	background-color: var(--favorite-article-background-color);
 }
 
+.flux.favorite:not(.current):hover .flux_header,
+.flux.favorite:not(.current):hover .flux_header .item {
+	background-color: var(--favorite-article-background-color-hover);
+}
+
 .flux_header {
 	font-size: 0.9rem;
 	border-top: 1px solid var(--border-color);
@@ -1188,3 +1198,96 @@ a:hover .icon {
 		display: none;
 	}
 }
+
+@media screen and (prefers-color-scheme: dark) {
+	:root .darkMode_auto {
+		--frss-background-color: #000;
+		--frss-background-color-middle: #222;
+		--frss-border-color: #444;
+		--frss-font-color-grey-dark: #999;
+		--frss-font-color-dark: #ddd;
+		--frss-modal-background-color-transparent: #000000a3;
+		--frss-background-color-transparent: #000000a3;
+		--frss-scrollbar-handle: #fff1;
+		--frss-scrollbar-handle-hover: #fff4;
+
+		--background-color-light-gradient: #111;
+		--background-color-light: #111;
+		--background-color-light-shadowed: #191919;
+		--background-color-grey: #1f1f1f;
+		--background-color-hover: #09090977;
+
+		--unread-article-background-color: #201f1e;
+		--unread-article-background-color-hover: #1a1918;
+		--unread-article-border-color: #ff5300;
+		--favorite-article-background-color: #24221d;
+		--favorite-article-background-color-hover: #1d1b17;
+		--favorite-article-border-color: #ffc300;
+
+		--contrast-background-color: #0084cc;
+		--contrast-background-color-gradient: #0045cc;
+		--contrast-background-color-hover: #06c;
+		--contrast-background-color-active: #038;
+		--contrast-border-color: #0062b7;
+
+		--contrast-background-font-color: #eee;
+
+		--attention-background-color-gradient1: #ea4a46;
+		--attention-background-color-gradient2: #911811;
+
+		--attention-background-color-gradient1-hover: #d14641;
+		--attention-background-color-gradient2-hover: #bd362f;
+		--attention-background-color-active: #bd362f;
+		--attention-border-color: #c44742;
+
+		--empty-feed-color: #e67e22;
+		--error-feed-color: #bd362f;
+
+		--alert-warn-background-color: #ffffe022;
+		--alert-warn-font-color: #ccc;
+		--alert-warn-border-color: #eeb;
+		--alert-success-background-color: #e8ffe814;
+		--alert-success-font-color: #96c196;
+		--alert-success-border-color: #cec;
+		--alert-error-background-color: #fdda;
+		--alert-error-font-color: #693a3a;
+		--alert-error-boder-color: #ecc;
+
+		--notification-good-background-color: #ffe;
+		--notification-good-border-color: #eeb;
+		--notification-good-font-color: #916a37;
+		--notification-bad-background-color: #fdd;
+		--notification-bad-font-color: #643838;
+		--notification-bad-border-color: #ecc;
+		--notification-close-background-color-hover: #aaa2;
+
+		--font-color: #ccc;
+		--font-color-grey: #aaa;
+		--font-color-light-shadowed: #555;
+		--font-color-light: #ccc;
+
+		--text-shadow-color: #1c1c1c;
+		--text-shadow-color-dark: #666;
+		--box-shadow-color: #4446;
+		--box-shadow-color-inset: #1f1f1f;
+
+		--font-color-link: #467eb3;
+		--font-color-link-hover: #0062be;
+
+		--border-color: #222;
+		--border-color-shadow-side: #333;
+		--contrast-border-color-active: #0062be;
+
+		--form-element-font-color-focus: #879db1;
+		--form-element-border-color-focus: #0062be;
+		--form-element-focus-box-shadow-color-inset: #110;
+		--form-element-border-color-invalid: #f00;
+		--form-element-invalid-box-shadow-color-inset: #fdd;
+	}
+
+	.btn.active,
+	.btn:active,
+	.dropdown-target:target ~ .btn.dropdown-toggle {
+		background: var(--border-color);
+	}
+}

+ 111 - 8
p/themes/Origine/origine.rtl.css

@@ -12,8 +12,10 @@
 	--background-color-hover: #f6f6f6;
 
 	--unread-article-background-color: #fff3ed;
+	--unread-article-background-color-hover: #faeee8;
 	--unread-article-border-color: #ff5300;
 	--favorite-article-background-color: #fff6da;
+	--favorite-article-background-color-hover: #fcf2d6;
 	--favorite-article-border-color: #ffc300;
 
 	--contrast-background-color: #0084cc;
@@ -825,34 +827,42 @@ a:hover .icon {
 	border-right: 2px solid var(--contrast-border-color-active);
 }
 
-.flux .flux_header:hover {
-	background-color: var(--background-color-hover) !important;
+.flux .flux_header:hover,
+.flux .flux_header:hover .item {
+	background-color: var(--background-color-hover);
 }
 
-.flux .flux_header:not(.current):hover .item.title {
-	background: inherit;
+.flux .flux_header:not(.current):hover .flux_header,
+.flux .flux_header:not(.current):hover .flux_header .item {
+	background-color: var(--background-color-hover);
 }
 
 .flux.not_read {
 	border-right: 2px solid var(--unread-article-border-color);
 }
 
-.flux.not_read .flux_header {
+.flux.not_read .flux_header .item {
 	background-color: var(--unread-article-background-color);
 }
 
-.flux.not_read:not(.current):hover .item.title {
-	background: inherit;
+.flux.not_read:not(.current):hover .flux_header,
+.flux.not_read:not(.current):hover .flux_header .item {
+	background-color: var(--unread-article-background-color-hover);
 }
 
 .flux.favorite {
 	border-right: 2px solid var(--favorite-article-border-color);
 }
 
-.flux.favorite:not(.current) {
+.flux.favorite:not(.current) .flux_header .item {
 	background-color: var(--favorite-article-background-color);
 }
 
+.flux.favorite:not(.current):hover .flux_header,
+.flux.favorite:not(.current):hover .flux_header .item {
+	background-color: var(--favorite-article-background-color-hover);
+}
+
 .flux_header {
 	font-size: 0.9rem;
 	border-top: 1px solid var(--border-color);
@@ -1188,3 +1198,96 @@ a:hover .icon {
 		display: none;
 	}
 }
+
+@media screen and (prefers-color-scheme: dark) {
+	:root .darkMode_auto {
+		--frss-background-color: #000;
+		--frss-background-color-middle: #222;
+		--frss-border-color: #444;
+		--frss-font-color-grey-dark: #999;
+		--frss-font-color-dark: #ddd;
+		--frss-modal-background-color-transparent: #000000a3;
+		--frss-background-color-transparent: #000000a3;
+		--frss-scrollbar-handle: #fff1;
+		--frss-scrollbar-handle-hover: #fff4;
+
+		--background-color-light-gradient: #111;
+		--background-color-light: #111;
+		--background-color-light-shadowed: #191919;
+		--background-color-grey: #1f1f1f;
+		--background-color-hover: #09090977;
+
+		--unread-article-background-color: #201f1e;
+		--unread-article-background-color-hover: #1a1918;
+		--unread-article-border-color: #ff5300;
+		--favorite-article-background-color: #24221d;
+		--favorite-article-background-color-hover: #1d1b17;
+		--favorite-article-border-color: #ffc300;
+
+		--contrast-background-color: #0084cc;
+		--contrast-background-color-gradient: #0045cc;
+		--contrast-background-color-hover: #06c;
+		--contrast-background-color-active: #038;
+		--contrast-border-color: #0062b7;
+
+		--contrast-background-font-color: #eee;
+
+		--attention-background-color-gradient1: #ea4a46;
+		--attention-background-color-gradient2: #911811;
+
+		--attention-background-color-gradient1-hover: #d14641;
+		--attention-background-color-gradient2-hover: #bd362f;
+		--attention-background-color-active: #bd362f;
+		--attention-border-color: #c44742;
+
+		--empty-feed-color: #e67e22;
+		--error-feed-color: #bd362f;
+
+		--alert-warn-background-color: #ffffe022;
+		--alert-warn-font-color: #ccc;
+		--alert-warn-border-color: #eeb;
+		--alert-success-background-color: #e8ffe814;
+		--alert-success-font-color: #96c196;
+		--alert-success-border-color: #cec;
+		--alert-error-background-color: #fdda;
+		--alert-error-font-color: #693a3a;
+		--alert-error-boder-color: #ecc;
+
+		--notification-good-background-color: #ffe;
+		--notification-good-border-color: #eeb;
+		--notification-good-font-color: #916a37;
+		--notification-bad-background-color: #fdd;
+		--notification-bad-font-color: #643838;
+		--notification-bad-border-color: #ecc;
+		--notification-close-background-color-hover: #aaa2;
+
+		--font-color: #ccc;
+		--font-color-grey: #aaa;
+		--font-color-light-shadowed: #555;
+		--font-color-light: #ccc;
+
+		--text-shadow-color: #1c1c1c;
+		--text-shadow-color-dark: #666;
+		--box-shadow-color: #4446;
+		--box-shadow-color-inset: #1f1f1f;
+
+		--font-color-link: #467eb3;
+		--font-color-link-hover: #0062be;
+
+		--border-color: #222;
+		--border-color-shadow-side: #333;
+		--contrast-border-color-active: #0062be;
+
+		--form-element-font-color-focus: #879db1;
+		--form-element-border-color-focus: #0062be;
+		--form-element-focus-box-shadow-color-inset: #110;
+		--form-element-border-color-invalid: #f00;
+		--form-element-invalid-box-shadow-color-inset: #fdd;
+	}
+
+	.btn.active,
+	.btn:active,
+	.dropdown-target:target ~ .btn.dropdown-toggle {
+		background: var(--border-color);
+	}
+}