diff options
| author | Andrew Dolgov <fox@fakecake.org> | 2025-08-04 20:09:08 +0300 |
|---|---|---|
| committer | Andrew Dolgov <fox@fakecake.org> | 2025-08-04 20:09:08 +0300 |
| commit | 906063b1d118fb8c94299fc1f23135519bf8a47f (patch) | |
| tree | a35399d82497cbc965e9ab71871eda3b801b58f7 | |
| parent | 851ddf4bbe750e30816b6c494165e9860bd39b92 (diff) | |
| parent | 19fc3bff213d56f52982eb53bdc8eb9d910f882e (diff) | |
Merge branch 'configurable-default-themes' into 'master'
make default light/dark themes configurable, add support for main application and login form
See merge request tt-rss/tt-rss!169
| -rw-r--r-- | classes/Config.php | 8 | ||||
| -rw-r--r-- | classes/Handler_Public.php | 25 | ||||
| -rw-r--r-- | classes/OPML.php | 27 | ||||
| -rw-r--r-- | include/functions.php | 4 | ||||
| -rwxr-xr-x | include/login_form.php | 5 | ||||
| -rw-r--r-- | index.php | 3 | ||||
| -rw-r--r-- | js/App.js | 4 | ||||
| -rw-r--r-- | js/utility.js | 5 | ||||
| -rw-r--r-- | prefs.php | 3 |
9 files changed, 51 insertions, 33 deletions
diff --git a/classes/Config.php b/classes/Config.php index 7be529e41..49715a576 100644 --- a/classes/Config.php +++ b/classes/Config.php @@ -214,6 +214,12 @@ class Config { /** scheduled task to send digests, value should be valid cron expression */ const SCHEDULE_SEND_HEADLINES_DIGESTS = "SCHEDULE_SEND_HEADLINES_DIGESTS"; + /** default (fallback) light theme path */ + const DEFAULT_LIGHT_THEME = "DEFAULT_LIGHT_THEME"; + + /** default (fallback) dark (night) theme path */ + const DEFAULT_DARK_THEME = "DEFAULT_DARK_THEME"; + /** default values for all global configuration options */ private const _DEFAULTS = [ Config::DB_TYPE => [ "pgsql", Config::T_STRING ], @@ -280,6 +286,8 @@ class Config { Config::SCHEDULE_EXPIRE_ERROR_LOG => ["@hourly", Config::T_STRING], Config::SCHEDULE_EXPIRE_LOCK_FILES => ["@hourly", Config::T_STRING], Config::SCHEDULE_SEND_HEADLINES_DIGESTS => ["@hourly", Config::T_STRING], + Config::DEFAULT_LIGHT_THEME => [ "light.css", Config::T_STRING], + Config::DEFAULT_DARK_THEME => [ "night.css", Config::T_STRING], ]; private static ?Config $instance = null; diff --git a/classes/Handler_Public.php b/classes/Handler_Public.php index 405d16d24..23f4dd2d2 100644 --- a/classes/Handler_Public.php +++ b/classes/Handler_Public.php @@ -438,16 +438,24 @@ class Handler_Public extends Handler { <link rel="icon" type="image/png" sizes="72x72" href="images/favicon-72px.png"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <?php - echo stylesheet_tag("themes/light.css"); echo javascript_tag("lib/dojo/dojo.js"); echo javascript_tag("lib/dojo/tt-rss-layer.js"); + echo javascript_tag("js/common.js"); + echo javascript_tag("js/utility.js"); ?> <?= Config::get_override_links() ?> </head> - <body class='flat ttrss_utility'> + <body class='flat ttrss_utility css_loading'> <div class='container'> <script type="text/javascript"> + const __csrf_token = "<?= $_SESSION["csrf_token"]; ?>"; + + const __default_light_theme = "<?= get_theme_path(Config::get(Config::DEFAULT_LIGHT_THEME), 'themes/light.css') ?>"; + const __default_dark_theme = "<?= get_theme_path(Config::get(Config::DEFAULT_DARK_THEME), 'themes/night.css') ?>"; + </script> + + <script type="text/javascript"> require(['dojo/parser', "dojo/ready", 'dijit/form/Button','dijit/form/CheckBox', 'dijit/form/Form', 'dijit/form/Select','dijit/form/TextBox','dijit/form/ValidationTextBox'],function(parser, ready){ ready(function() { @@ -455,6 +463,19 @@ class Handler_Public extends Handler { }); }); </script> + + <style type="text/css"> + @media (prefers-color-scheme: dark) { + body { + background : #303030; + } + } + + body.css_loading * { + display : none; + } + </style> + <?php print "<h1>".__("Password recovery")."</h1>"; diff --git a/classes/OPML.php b/classes/OPML.php index bae00b8bc..0560cc5f5 100644 --- a/classes/OPML.php +++ b/classes/OPML.php @@ -20,33 +20,6 @@ class OPML extends Handler_Protected { return $rc; } - function import(): void { - $owner_uid = $_SESSION["uid"]; - - header('Content-Type: text/html; charset=utf-8'); - - print "<html> - <head> - ".stylesheet_tag("themes/light.css")." - <title>".__("OPML Utility")."</title> - <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/> - </head> - <body class='claro ttrss_utility'> - <h1>".__('OPML Utility')."</h1><div class='content'>"; - - Feeds::_add_cat("Imported feeds", $owner_uid); - - $this->opml_notice(__("Importing OPML...")); - - $this->opml_import($owner_uid); - - print "<br><form method=\"GET\" action=\"prefs.php\"> - <input type=\"submit\" value=\"".__("Return to preferences")."\"> - </form>"; - - print "</div></body></html>"; - } - // Export private function opml_export_category(int $owner_uid, int $cat_id, bool $hide_private_feeds = false, bool $include_settings = true): string { diff --git a/include/functions.php b/include/functions.php index ae403ca84..24b5c8538 100644 --- a/include/functions.php +++ b/include/functions.php @@ -464,14 +464,14 @@ return false; } - function get_theme_path(string $theme): string { + function get_theme_path(string $theme, string $default = ""): string { $check = "themes/$theme"; if (file_exists($check)) return $check; $check = "themes.local/$theme"; if (file_exists($check)) return $check; - return ""; + return $default; } function theme_exists(string $theme): bool { diff --git a/include/login_form.php b/include/login_form.php index 8fa578c11..e601ca619 100755 --- a/include/login_form.php +++ b/include/login_form.php @@ -34,6 +34,11 @@ </script> <script type="text/javascript"> + const __default_light_theme = "<?= get_theme_path(Config::get(Config::DEFAULT_LIGHT_THEME), 'themes/light.css') ?>"; + const __default_dark_theme = "<?= get_theme_path(Config::get(Config::DEFAULT_DARK_THEME), 'themes/night.css') ?>"; + </script> + + <script type="text/javascript"> /* exported Plugins */ const Plugins = {}; @@ -29,6 +29,9 @@ <script type="text/javascript"> const __csrf_token = "<?= $_SESSION["csrf_token"]; ?>"; + + const __default_light_theme = "<?= get_theme_path(Config::get(Config::DEFAULT_LIGHT_THEME), 'themes/light.css') ?>"; + const __default_dark_theme = "<?= get_theme_path(Config::get(Config::DEFAULT_DARK_THEME), 'themes/night.css') ?>"; </script> <?php UserHelper::print_user_stylesheet() ?> @@ -173,7 +173,7 @@ const App = { if (link) { if (navigator.onLine) { - const css_override = is_night ? "themes/night.css" : "themes/light.css"; + const css_override = is_night ? App.getInitParam("default_dark_theme") : App.getInitParam("default_light_theme"); link.setAttribute("href", css_override + "?" + Date.now()); } else if (retry < 5) { console.log("nightModeChanged: we're offline, will attempt to retry..."); @@ -704,6 +704,8 @@ const App = { window.onerror = this.Error.onWindowError; this.setInitParam("csrf_token", __csrf_token); + this.setInitParam("default_light_theme", __default_light_theme); + this.setInitParam("default_dark_theme", __default_dark_theme); this.setupNightModeDetection(() => { parser.parse(); diff --git a/js/utility.js b/js/utility.js index 43ad5644e..070e9e2d1 100644 --- a/js/utility.js +++ b/js/utility.js @@ -7,8 +7,11 @@ window.addEventListener("load", function() { apply_night_mode: function (is_night, link) { console.log("night mode changed to", is_night); + const light_theme = typeof __default_light_theme != 'undefined' ? __default_light_theme : 'themes/light.css'; + const dark_theme = typeof __default_dark_theme != 'undefined' ? __default_dark_theme : 'themes/dark.css'; + if (link) { - const css_override = is_night ? "themes/night.css" : "themes/light.css"; + const css_override = is_night ? dark_theme : light_theme; link.setAttribute("href", css_override + "?" + Date.now()); } @@ -29,6 +29,9 @@ <script type="text/javascript"> const __csrf_token = "<?= $_SESSION["csrf_token"]; ?>"; + + const __default_light_theme = "<?= get_theme_path(Config::get(Config::DEFAULT_LIGHT_THEME), 'themes/light.css') ?>"; + const __default_dark_theme = "<?= get_theme_path(Config::get(Config::DEFAULT_DARK_THEME), 'themes/night.css') ?>"; </script> <?php UserHelper::print_user_stylesheet() ?> |