diff --git a/.env.example b/.env.example index 5e60b082..5beeaff6 100644 --- a/.env.example +++ b/.env.example @@ -12,8 +12,9 @@ REDLIB_ROBOTS_DISABLE_INDEXING=off REDLIB_PUSHSHIFT_FRONTEND=undelete.pullpush.io # Default user settings -# Set the default theme (options: system, light, dark, black, dracula, nord, laserwave, violet, gold, rosebox, gruvboxdark, gruvboxlight) -REDLIB_DEFAULT_THEME=system +# Set the default theme (options: light, dark, black, dracula, nord, laserwave, violet, gold, rosebox, gruvboxdark, gruvboxlight) +REDLIB_DEFAULT_THEME_LIGHT=light +REDLIB_DEFAULT_THEME_DARK=dark # Set the default front page (options: default, popular, all) REDLIB_DEFAULT_FRONT_PAGE=default # Set the default layout (options: card, clean, compact) diff --git a/README.md b/README.md index 5aac1e8f..c4eeae6a 100644 --- a/README.md +++ b/README.md @@ -381,7 +381,7 @@ REDLIB_DEFAULT_SHOW_NSFW=on redlib ``` ```bash -REDLIB_DEFAULT_WIDE=on REDLIB_DEFAULT_THEME=dark redlib -r +REDLIB_DEFAULT_WIDE=on REDLIB_DEFAULT_THEME_DARK=dark redlib -r ``` You can also configure Redlib with a configuration file named `redlib.toml`. For example: @@ -434,7 +434,8 @@ Assign a default value for each user-modifiable setting by passing environment v | Name | Possible values | Default value | | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------- | -| `THEME` | `["system", "light", "dark", "black", "dracula", "nord", "laserwave", "violet", "gold", "rosebox", "gruvboxdark", "gruvboxlight", "tokyoNight", "icebergDark", "doomone", "libredditBlack", "libredditDark", "libredditLight"]` | `system` | +| `THEME_LIGHT` | `["light", "dark", "black", "dracula", "nord", "laserwave", "violet", "gold", "rosebox", "gruvboxdark", "gruvboxlight", "tokyoNight", "icebergDark", "doomone", "libredditBlack", "libredditDark", "libredditLight"]` | `light` | +| `THEME_DARK` | `["light", "dark", "black", "dracula", "nord", "laserwave", "violet", "gold", "rosebox", "gruvboxdark", "gruvboxlight", "tokyoNight", "icebergDark", "doomone", "libredditBlack", "libredditDark", "libredditLight"]` | `dark` | | `FRONT_PAGE` | `["default", "popular", "all"]` | `default` | | `LAYOUT` | `["card", "clean", "compact"]` | `card` | | `WIDE` | `["on", "off"]` | `off` | @@ -447,6 +448,7 @@ Assign a default value for each user-modifiable setting by passing environment v | `HIDE_HLS_NOTIFICATION` | `["on", "off"]` | `off` | | `AUTOPLAY_VIDEOS` | `["on", "off"]` | `off` | | `SUBSCRIPTIONS` | `+`-delimited list of subreddits (`sub1+sub2+sub3+...`) | _(none)_ | +| `FILTERS` | `+`-delimited list of subreddits (`sub1+sub2+sub3+...`) | _(none)_ | | `HIDE_AWARDS` | `["on", "off"]` | `off` | | `DISABLE_VISIT_REDDIT_CONFIRMATION` | `["on", "off"]` | `off` | | `HIDE_SCORE` | `["on", "off"]` | `off` | diff --git a/app.json b/app.json index c05b26d1..840ae8c4 100644 --- a/app.json +++ b/app.json @@ -11,7 +11,10 @@ ], "stack": "container", "env": { - "REDLIB_DEFAULT_THEME": { + "REDLIB_DEFAULT_THEME_LIGHT": { + "required": false + }, + "REDLIB_DEFAULT_THEME_DARK": { "required": false }, "REDLIB_DEFAULT_FRONT_PAGE": { diff --git a/src/config.rs b/src/config.rs index 034afc78..351e226b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -24,9 +24,15 @@ pub struct Config { #[serde(alias = "LIBREDDIT_SFW_ONLY")] pub(crate) sfw_only: Option, - #[serde(rename = "REDLIB_DEFAULT_THEME")] + #[serde(rename = "REDLIB_DEFAULT_THEME_LIGHT")] + #[serde(alias = "LIBREDDIT_DEFAULT_THEME_LIGHT")] + #[serde(alias = "REDLIB_DEFAULT_THEME")] #[serde(alias = "LIBREDDIT_DEFAULT_THEME")] - pub(crate) default_theme: Option, + pub(crate) default_theme_light: Option, + + #[serde(rename = "REDLIB_DEFAULT_THEME_DARK")] + #[serde(alias = "LIBREDDIT_DEFAULT_THEME_DARK")] + pub(crate) default_theme_dark: Option, #[serde(rename = "REDLIB_DEFAULT_FRONT_PAGE")] #[serde(alias = "LIBREDDIT_DEFAULT_FRONT_PAGE")] @@ -134,7 +140,8 @@ impl Config { }; Self { sfw_only: parse("REDLIB_SFW_ONLY"), - default_theme: parse("REDLIB_DEFAULT_THEME"), + default_theme_light: parse("REDLIB_DEFAULT_THEME_LIGHT"), + default_theme_dark: parse("REDLIB_DEFAULT_THEME_DARK"), default_front_page: parse("REDLIB_DEFAULT_FRONT_PAGE"), default_layout: parse("REDLIB_DEFAULT_LAYOUT"), default_post_sort: parse("REDLIB_DEFAULT_POST_SORT"), @@ -163,7 +170,8 @@ impl Config { fn get_setting_from_config(name: &str, config: &Config) -> Option { match name { "REDLIB_SFW_ONLY" => config.sfw_only.clone(), - "REDLIB_DEFAULT_THEME" => config.default_theme.clone(), + "REDLIB_DEFAULT_THEME_LIGHT" => config.default_theme_light.clone(), + "REDLIB_DEFAULT_THEME_DARK" => config.default_theme_dark.clone(), "REDLIB_DEFAULT_FRONT_PAGE" => config.default_front_page.clone(), "REDLIB_DEFAULT_LAYOUT" => config.default_layout.clone(), "REDLIB_DEFAULT_COMMENT_SORT" => config.default_comment_sort.clone(), diff --git a/src/instance_info.rs b/src/instance_info.rs index 5f82ce6d..479285f2 100644 --- a/src/instance_info.rs +++ b/src/instance_info.rs @@ -137,7 +137,8 @@ impl InstanceInfo { Table::from([ ["Hide awards", &convert(&self.config.default_hide_awards)], ["Hide score", &convert(&self.config.default_hide_score)], - ["Theme", &convert(&self.config.default_theme)], + ["Light Theme", &convert(&self.config.default_theme_light)], + ["Dark Theme", &convert(&self.config.default_theme_dark)], ["Front page", &convert(&self.config.default_front_page)], ["Layout", &convert(&self.config.default_layout)], ["Wide", &convert(&self.config.default_wide)], @@ -173,7 +174,8 @@ impl InstanceInfo { Banner: {:?}\n Hide awards: {:?}\n Hide score: {:?}\n - Default theme: {:?}\n + Default light theme: {:?}\n + Default dark theme: {:?}\n Default front page: {:?}\n Default layout: {:?}\n Default wide: {:?}\n @@ -199,7 +201,8 @@ impl InstanceInfo { self.config.banner, self.config.default_hide_awards, self.config.default_hide_score, - self.config.default_theme, + self.config.default_theme_light, + self.config.default_theme_dark, self.config.default_front_page, self.config.default_layout, self.config.default_wide, diff --git a/src/main.rs b/src/main.rs index bcfcd51b..e6fe8cb3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -84,8 +84,28 @@ async fn style() -> Result, String> { let mut res = include_str!("../static/style.css").to_string(); for file in ThemeAssets::iter() { res.push('\n'); - let theme = ThemeAssets::get(file.as_ref()).unwrap(); - res.push_str(std::str::from_utf8(theme.data.as_ref()).unwrap()); + let theme: Vec<&str> = file.as_ref().split(".css").collect(); + let theme = ".".to_owned() + theme[0]; + let style = ThemeAssets::get(file.as_ref()).unwrap(); + let style = std::str::from_utf8(style.data.as_ref()).unwrap(); + let style_light = &style.replace(&theme, &(theme.clone() + "_light")); + let style_light = &format!( + " + @media (prefers-color-scheme: light) {{ + {style_light} + }} + " + ); + let style_dark = &style.replace(&theme, &(theme.clone() + "_dark")); + let style_dark = &format!( + " + @media (prefers-color-scheme: dark) {{ + {style_dark} + }} + " + ); + res.push_str(style_light); + res.push_str(style_dark); } Ok( Response::builder() diff --git a/src/settings.rs b/src/settings.rs index 6649f694..3029b556 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -23,8 +23,9 @@ struct SettingsTemplate { // CONSTANTS -const PREFS: [&str; 19] = [ - "theme", +const PREFS: [&str; 20] = [ + "theme_light", + "theme_dark", "front_page", "layout", "wide", diff --git a/src/utils.rs b/src/utils.rs index f5046cb3..28f5e37f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -12,7 +12,7 @@ use libflate::deflate::{Decoder, Encoder}; use log::error; use once_cell::sync::Lazy; use regex::Regex; -use revision::revisioned; +use revision::{revisioned, Error}; use rinja::Template; use rust_embed::RustEmbed; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -621,13 +621,17 @@ pub struct Params { } #[derive(Default, Serialize, Deserialize, Debug, PartialEq, Eq)] -#[revisioned(revision = 1)] +#[revisioned(revision = 2)] pub struct Preferences { #[revision(start = 1)] #[serde(skip_serializing, skip_deserializing)] pub available_themes: Vec, - #[revision(start = 1)] + #[revision(start = 1, end = 2, convert_fn="convert_theme")] pub theme: String, + #[revision(start = 2)] + pub theme_light: String, + #[revision(start = 2)] + pub theme_dark: String, #[revision(start = 1)] pub front_page: String, #[revision(start = 1)] @@ -699,15 +703,15 @@ impl Preferences { // Build preferences from cookies pub fn new(req: &Request) -> Self { // Read available theme names from embedded css files. - // Always make the default "system" theme available. - let mut themes = vec!["system".to_string()]; + let mut themes = Vec::new(); for file in ThemeAssets::iter() { let chunks: Vec<&str> = file.as_ref().split(".css").collect(); themes.push(chunks[0].to_owned()); } Self { available_themes: themes, - theme: setting(req, "theme"), + theme_light: setting(req, "theme_light"), + theme_dark: setting(req, "theme_dark"), front_page: setting(req, "front_page"), layout: setting(req, "layout"), wide: setting(req, "wide"), @@ -744,6 +748,11 @@ impl Preferences { pub fn to_bincode_str(&self) -> Result { Ok(base2048::encode(&self.to_compressed_bincode()?)) } + fn convert_theme(&mut self, _revision: u16, value:String) -> Result<(), Error> { + self.theme_light = value.clone(); + self.theme_dark = value.clone(); + Ok(()) + } } pub fn deflate_compress(i: Vec) -> Result, String> { @@ -1526,7 +1535,8 @@ mod tests { fn serialize_prefs() { let prefs = Preferences { available_themes: vec![], - theme: "laserwave".to_owned(), + theme_light: "laserwave".to_owned(), + theme_dark: "laserwave".to_owned(), front_page: "default".to_owned(), layout: "compact".to_owned(), wide: "on".to_owned(), diff --git a/static/style.css b/static/style.css index 545567e1..a6278dd9 100644 --- a/static/style.css +++ b/static/style.css @@ -37,66 +37,6 @@ font-weight: 100 900; } -/* Automatic theme selection */ -:root, -.dark { - /* Default & fallback theme (dark) */ - --accent: #d54455; - --green: #5cff85; - --text: white; - --foreground: #222; - --background: #0f0f0f; - --outside: #1f1f1f; - --post: #161616; - --panel-border: 1px solid #333; - --highlighted: #333; - --visited: #aaa; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.5); - --popup: #b80a27; - --spoiler: #ddd; - - /* Hint color theme to browser for scrollbar */ - color-scheme: dark; -} - -/* Browser-defined light theme */ -@media (prefers-color-scheme: light) { - :root { - --accent: #bb2b3b; - --green: #00a229; - --text: black; - --foreground: #f5f5f5; - --background: #ddd; - --outside: #ececec; - --post: #eee; - --panel-border: 1px solid #ccc; - --highlighted: white; - --visited: #555; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - --spoiler: #0f0f0f; - - /* Hint color theme to browser for scrollbar */ - color-scheme: light; - } -} - -/* Other themes are located in the "themes" folder */ - -/* Tokyo Night theme setting */ -.tokyoNight { - --accent: #565f89; - --green: #73daca; - --text: #a9b1d6; - --foreground: #24283b; - --background: #1a1b26; - --outside: #24283b; - --post: #1a1b26; - --panel-border: 1px solid #a9b1d6; - --highlighted: #414868; - --visited: #414868; - --shadow: 0 1px 3px rgba(0, 0, 0, 0.5); -} - /* General */ ::selection { diff --git a/templates/base.html b/templates/base.html index a1c141bc..b70ebb03 100644 --- a/templates/base.html +++ b/templates/base.html @@ -34,7 +34,8 @@