diff --git a/README.md b/README.md index 59a862a..3ec97d5 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,14 @@ Key: - [ ] Support for Tautulli ### Themes -Managarr ships with a few themes out of the box. See the [Themes README](themes/README.md) page for more information. +Managarr ships with a few themes out of the box. Here's a few examples: + +![default](themes/default/manual_episode_search.png) +![dracula](themes/dracula/manual_episode_search.png) +![watermelon-dark](themes/watermelon-dark/manual_episode_search.png) + +You can also create your own custom themes as well. To learn more about what themes are built-in to Managarr and how +to create your own custom themes, check out the [Themes README](themes/README.md). ### The Managarr CLI Managarr can be used in one of two ways: As a TUI, or as a CLI for managing your Servarrs. diff --git a/proc_macros/validate_theme_derive/src/lib.rs b/proc_macros/validate_theme_derive/src/lib.rs index 6a6ca27..7ed9b0a 100644 --- a/proc_macros/validate_theme_derive/src/lib.rs +++ b/proc_macros/validate_theme_derive/src/lib.rs @@ -24,13 +24,13 @@ use syn::{Data, DeriveInput, Fields, parse_macro_input}; /// } /// /// struct Style { -/// color: String, +/// color: String, /// } /// /// let theme = Theme { -/// good: Some(Style { color: "Green".to_owned() }), -/// bad: Some(Style { color: "Red".to_owned() }), -/// ..Theme::default() +/// good: Some(Style { color: "Green".to_owned() }), +/// bad: Some(Style { color: "Red".to_owned() }), +/// ..Theme::default() /// }; /// /// // Since only `good` and `bad` have the `validate` attribute, the `validate` method will only check those fields. diff --git a/src/main.rs b/src/main.rs index f0be784..bb4d7ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,8 +33,6 @@ use crate::ui::{ui, THEME}; use crate::utils::load_theme_config; mod app; -mod builtin_themes; -mod builtin_themes_tests; mod cli; mod event; mod handlers; diff --git a/src/builtin_themes.rs b/src/ui/builtin_themes.rs similarity index 58% rename from src/builtin_themes.rs rename to src/ui/builtin_themes.rs index 4477539..19c4113 100644 --- a/src/builtin_themes.rs +++ b/src/ui/builtin_themes.rs @@ -6,8 +6,8 @@ use std::str::FromStr; #[path = "builtin_themes_tests.rs"] mod builtin_themes_tests; -pub fn get_builtin_themes() -> Vec { - let watermelon_dark = Theme { +pub(in crate::ui) fn watermelon_dark_theme() -> Theme { + Theme { background: Some(Background { enabled: Some(false), color: Some(Color::from_str("#233237").unwrap()), @@ -31,11 +31,14 @@ pub fn get_builtin_themes() -> Vec { color: Some(Color::from_str("#8c19ff").unwrap()), }), ..Theme::default() - }; - let dracula = Theme { + } +} + +pub(in crate::ui) fn dracula_theme() -> Theme { + Theme { background: Some(Background { - enabled: Some(false), - color: Some(Color::from_str("#233237").unwrap()), + enabled: Some(true), + color: Some(Color::from_str("#232326").unwrap()), }), default: Some(Style { color: Some(Color::from_str("#f8f8f2").unwrap()), @@ -74,7 +77,56 @@ pub fn get_builtin_themes() -> Vec { color: Some(Color::from_str("#f8f8f2").unwrap()), }), ..Theme::default() - }; + } +} + +pub(in crate::ui) fn eldritch_theme() -> Theme { + Theme { + background: Some(Background { + enabled: Some(true), + color: Some(Color::from_str("#212337").unwrap()), + }), + default: Some(Style { + color: Some(Color::from_str("#ebfafa").unwrap()), + }), + downloaded: Some(Style { + color: Some(Color::from_str("#37f499").unwrap()), + }), + downloading: Some(Style { + color: Some(Color::from_str("#f7c67f").unwrap()), + }), + failure: Some(Style { + color: Some(Color::from_str("#f16c75").unwrap()), + }), + missing: Some(Style { + color: Some(Color::from_str("#f7c67f").unwrap()), + }), + unmonitored_missing: Some(Style { + color: Some(Color::from_str("#7081d0").unwrap()), + }), + help: Some(Style { + color: Some(Color::from_str("#7081d0").unwrap()), + }), + primary: Some(Style { + color: Some(Color::from_str("#f265b5").unwrap()), + }), + secondary: Some(Style { + color: Some(Color::from_str("#04d1f9").unwrap()), + }), + success: Some(Style { + color: Some(Color::from_str("#37f499").unwrap()), + }), + warning: Some(Style { + color: Some(Color::from_str("#f1fc79").unwrap()), + }), + unreleased: Some(Style { + color: Some(Color::from_str("#ebfafa").unwrap()), + }), + ..Theme::default() + } +} + +pub fn get_builtin_themes() -> Vec { vec![ ThemeDefinition { name: "default".to_owned(), @@ -82,11 +134,15 @@ pub fn get_builtin_themes() -> Vec { }, ThemeDefinition { name: "watermelon-dark".to_owned(), - theme: watermelon_dark, + theme: watermelon_dark_theme(), }, ThemeDefinition { name: "dracula".to_owned(), - theme: dracula, + theme: dracula_theme(), + }, + ThemeDefinition { + name: "eldritch".to_owned(), + theme: eldritch_theme(), }, ] } diff --git a/src/builtin_themes_tests.rs b/src/ui/builtin_themes_tests.rs similarity index 62% rename from src/builtin_themes_tests.rs rename to src/ui/builtin_themes_tests.rs index fd79bd8..d1decef 100644 --- a/src/builtin_themes_tests.rs +++ b/src/ui/builtin_themes_tests.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod test { - use crate::builtin_themes::get_builtin_themes; + use crate::ui::builtin_themes::get_builtin_themes; use crate::ui::theme::{Background, Style, Theme, ThemeDefinition}; use pretty_assertions::assert_eq; use ratatui::prelude::Color; @@ -35,8 +35,8 @@ mod test { }; let dracula = Theme { background: Some(Background { - enabled: Some(false), - color: Some(Color::from_str("#233237").unwrap()), + enabled: Some(true), + color: Some(Color::from_str("#232326").unwrap()), }), default: Some(Style { color: Some(Color::from_str("#f8f8f2").unwrap()), @@ -76,6 +76,49 @@ mod test { }), ..Theme::default() }; + let eldritch = Theme { + background: Some(Background { + enabled: Some(true), + color: Some(Color::from_str("#212337").unwrap()), + }), + default: Some(Style { + color: Some(Color::from_str("#ebfafa").unwrap()), + }), + downloaded: Some(Style { + color: Some(Color::from_str("#37f499").unwrap()), + }), + downloading: Some(Style { + color: Some(Color::from_str("#f7c67f").unwrap()), + }), + failure: Some(Style { + color: Some(Color::from_str("#f16c75").unwrap()), + }), + missing: Some(Style { + color: Some(Color::from_str("#f7c67f").unwrap()), + }), + unmonitored_missing: Some(Style { + color: Some(Color::from_str("#7081d0").unwrap()), + }), + help: Some(Style { + color: Some(Color::from_str("#7081d0").unwrap()), + }), + primary: Some(Style { + color: Some(Color::from_str("#f265b5").unwrap()), + }), + secondary: Some(Style { + color: Some(Color::from_str("#04d1f9").unwrap()), + }), + success: Some(Style { + color: Some(Color::from_str("#37f499").unwrap()), + }), + warning: Some(Style { + color: Some(Color::from_str("#f1fc79").unwrap()), + }), + unreleased: Some(Style { + color: Some(Color::from_str("#ebfafa").unwrap()), + }), + ..Theme::default() + }; let expected_themes = vec![ ThemeDefinition { name: "default".to_owned(), @@ -89,6 +132,10 @@ mod test { name: "dracula".to_owned(), theme: dracula, }, + ThemeDefinition { + name: "eldritch".to_owned(), + theme: eldritch, + }, ]; assert_eq!(expected_themes, get_builtin_themes()); diff --git a/src/ui/mod.rs b/src/ui/mod.rs index cf85b9d..9d3dd64 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -24,6 +24,7 @@ use crate::ui::utils::{ use crate::ui::widgets::input_box::InputBox; use crate::ui::widgets::popup::Size; +mod builtin_themes; mod radarr_ui; mod sonarr_ui; mod styles; diff --git a/src/ui/radarr_ui/library/movie_details_ui.rs b/src/ui/radarr_ui/library/movie_details_ui.rs index b9dd2af..50a750e 100644 --- a/src/ui/radarr_ui/library/movie_details_ui.rs +++ b/src/ui/radarr_ui/library/movie_details_ui.rs @@ -256,7 +256,7 @@ fn draw_movie_history(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { Cell::from(quality.quality.name.to_owned()), Cell::from(date.to_string()), ]) - .success() + .primary() }; let help_footer = app .data @@ -297,7 +297,7 @@ fn draw_movie_cast(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { Cell::from(person_name.to_owned()), Cell::from(character.clone().unwrap_or_default()), ]) - .success() + .primary() }; let content = Some(&mut movie_details_modal.movie_cast); let help_footer = app @@ -340,7 +340,7 @@ fn draw_movie_crew(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) { Cell::from(job.clone().unwrap_or_default()), Cell::from(department.clone().unwrap_or_default()), ]) - .success() + .primary() }; let content = Some(&mut movie_details_modal.movie_crew); let help_footer = app diff --git a/src/ui/theme.rs b/src/ui/theme.rs index c52f610..154d66d 100644 --- a/src/ui/theme.rs +++ b/src/ui/theme.rs @@ -1,4 +1,4 @@ -use crate::builtin_themes::get_builtin_themes; +use crate::ui::builtin_themes::get_builtin_themes; use anyhow::Result; use derivative::Derivative; use ratatui::style::Color; diff --git a/src/ui/theme_tests.rs b/src/ui/theme_tests.rs index 7103d7f..616d45e 100644 --- a/src/ui/theme_tests.rs +++ b/src/ui/theme_tests.rs @@ -1,8 +1,8 @@ mod tests { + use crate::ui::builtin_themes::{dracula_theme, eldritch_theme, watermelon_dark_theme}; use crate::ui::theme::{Background, Style, Theme, ThemeDefinition, ThemeDefinitionsWrapper}; use pretty_assertions::{assert_eq, assert_str_eq}; use ratatui::style::Color; - use std::str::FromStr; #[test] fn test_background_default() { @@ -192,74 +192,6 @@ warning: #[test] fn test_theme_definitions_wrapper_default() { - let watermelon_dark = Theme { - background: Some(Background { - enabled: Some(false), - color: Some(Color::from_str("#233237").unwrap()), - }), - default: Some(Style { - color: Some(Color::from_str("#00FF00").unwrap()), - }), - downloaded: Some(Style { - color: Some(Color::from_str("#80ffbf").unwrap()), - }), - failure: Some(Style { - color: Some(Color::from_str("#ff8080").unwrap()), - }), - missing: Some(Style { - color: Some(Color::from_str("#ff8080").unwrap()), - }), - primary: Some(Style { - color: Some(Color::from_str("#ff19d9").unwrap()), - }), - secondary: Some(Style { - color: Some(Color::from_str("#8c19ff").unwrap()), - }), - ..Theme::default() - }; - let dracula = Theme { - background: Some(Background { - enabled: Some(false), - color: Some(Color::from_str("#233237").unwrap()), - }), - default: Some(Style { - color: Some(Color::from_str("#f8f8f2").unwrap()), - }), - downloaded: Some(Style { - color: Some(Color::from_str("#50fa7b").unwrap()), - }), - downloading: Some(Style { - color: Some(Color::from_str("#f1fa8c").unwrap()), - }), - failure: Some(Style { - color: Some(Color::from_str("#ff5555").unwrap()), - }), - missing: Some(Style { - color: Some(Color::from_str("#ffb86c").unwrap()), - }), - primary: Some(Style { - color: Some(Color::from_str("#ff79c6").unwrap()), - }), - secondary: Some(Style { - color: Some(Color::from_str("#ff79c6").unwrap()), - }), - unmonitored_missing: Some(Style { - color: Some(Color::from_str("#6272a4").unwrap()), - }), - help: Some(Style { - color: Some(Color::from_str("#6272a4").unwrap()), - }), - success: Some(Style { - color: Some(Color::from_str("#50fa7b").unwrap()), - }), - warning: Some(Style { - color: Some(Color::from_str("#f1fa8c").unwrap()), - }), - unreleased: Some(Style { - color: Some(Color::from_str("#f8f8f2").unwrap()), - }), - ..Theme::default() - }; let theme_definitions_wrapper = ThemeDefinitionsWrapper { theme_definitions: vec![ ThemeDefinition { @@ -268,11 +200,15 @@ warning: }, ThemeDefinition { name: "watermelon-dark".to_owned(), - theme: watermelon_dark, + theme: watermelon_dark_theme(), }, ThemeDefinition { name: "dracula".to_owned(), - theme: dracula, + theme: dracula_theme(), + }, + ThemeDefinition { + name: "eldritch".to_owned(), + theme: eldritch_theme(), }, ], }; diff --git a/themes/README.md b/themes/README.md index 59b1141..b184618 100644 --- a/themes/README.md +++ b/themes/README.md @@ -18,6 +18,9 @@ custom theme off of. The following themes are included by default: ### [Dracula](./dracula/README.md) ![sonarr-library](./dracula/sonarr_library.png) +### [Eldritch](./eldritch/README.md) +![sonarr-library](./eldritch/sonarr_library.png) + ### [Watermelon Dark](./watermelon-dark/README.md) ![sonarr-library](./watermelon-dark/sonarr_library.png) @@ -32,42 +35,70 @@ is an example that shows every available customization option for a custom theme - name: my-theme theme: background: - enabled: true # Disable for transparent backgrounds + # Disable for transparent backgrounds + enabled: true + # Color of the full system background color: "#233237" awaiting_import: + # Color for items awaiting import color: "#FFAA42" indeterminate: + # Color for when item status is unknown color: "#FFAA42" default: + # Default color for text and uncolored elements color: "#FFFFFF" downloaded: + # Color for downloaded items (when monitored) color: "#00FF00" downloading: + # Color for items currently downloading color: "#762671" failure: + # Color for errors, no seeders, disabled indexers, + # failed indexer test results, etc. color: "#DE382B" help: + # Color for help text like hotkeys and tooltips color: "#00FFFF" missing: + # Color for missing items color: "#DE382B" primary: + # Primary color for table/list items (without custom coloring), + # selected UI elements (e.g. table/list items, current tab, etc.), + # gauge bars, etc. color: "#2CB5E9" secondary: + # Color for selected tabs, Warn log events, Paragraph headers (e.g. "Name: "), + # and uncolored Message box contents color: "#FFC706" success: + # Color for downloaded and imported and available items, + # good peer styling (more seeders than leechers), + # passing indexer test results, and enabled indexers color: "#39B54A" system_function: + # Color for system functions like selected UI elements (e.g. checkboxes, yes/no prompts), + # or loading spinner color: "#FFC706" unmonitored: + # Color for unmonitored items color: "#808080" unmonitored_missing: + # Color for unmonitored items that are also missing color: "#FFC706" unreleased: + # Color for unreleased items color: "#00FFFF" warning: + # Color for fewer seeders than leechers color: "#FF00FF" ``` +**Note:** Bear in mind that while some colors may currently affect few UI elements, Managarr is still being built +and thus these colors may affect more elements in the future. + In order to activate your custom theme, you can either update your `config.yml`: ```yaml diff --git a/themes/default/README.md b/themes/default/README.md index 0425f25..7baffaa 100644 --- a/themes/default/README.md +++ b/themes/default/README.md @@ -1,6 +1,5 @@ # Managarr Default Theme -The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the -default Managarr theme. +The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the default Managarr theme. ## Screenshots diff --git a/themes/default/sonarr_library.png b/themes/default/sonarr_library.png index c577d4a..bfb82c3 100644 Binary files a/themes/default/sonarr_library.png and b/themes/default/sonarr_library.png differ diff --git a/themes/dracula/README.md b/themes/dracula/README.md index 80c30e4..3639f89 100644 --- a/themes/dracula/README.md +++ b/themes/dracula/README.md @@ -1,6 +1,5 @@ # Managarr Dracula Theme -The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the -Dracula Managarr theme. +The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the Dracula Managarr theme. ## Screenshots diff --git a/themes/dracula/manual_episode_search.png b/themes/dracula/manual_episode_search.png index 6b5a8cd..37a91c2 100644 Binary files a/themes/dracula/manual_episode_search.png and b/themes/dracula/manual_episode_search.png differ diff --git a/themes/dracula/radarr_system.png b/themes/dracula/radarr_system.png index eed5fc3..7e9c2ee 100644 Binary files a/themes/dracula/radarr_system.png and b/themes/dracula/radarr_system.png differ diff --git a/themes/dracula/sonarr_library.png b/themes/dracula/sonarr_library.png index 485576a..f1b54d4 100644 Binary files a/themes/dracula/sonarr_library.png and b/themes/dracula/sonarr_library.png differ diff --git a/themes/dracula/themes.yml b/themes/dracula/themes.yml index 3ce4d85..8b05f5f 100644 --- a/themes/dracula/themes.yml +++ b/themes/dracula/themes.yml @@ -1,8 +1,8 @@ - name: dracula theme: background: - enabled: false - color: "#282a36" + enabled: true + color: "#232326" default: color: "#f8f8f2" downloaded: diff --git a/themes/eldritch/README.md b/themes/eldritch/README.md new file mode 100644 index 0000000..a008c5f --- /dev/null +++ b/themes/eldritch/README.md @@ -0,0 +1,8 @@ +# Managarr Eldritch Theme +The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the Eldritch Managarr theme. + +## Screenshots + +![sonarr-library](./sonarr_library.png) +![manual-episode-search](./manual_episode_search.png) +![radarr-system](./radarr_system.png) \ No newline at end of file diff --git a/themes/eldritch/manual_episode_search.png b/themes/eldritch/manual_episode_search.png new file mode 100644 index 0000000..3c10dd0 Binary files /dev/null and b/themes/eldritch/manual_episode_search.png differ diff --git a/themes/eldritch/radarr_system.png b/themes/eldritch/radarr_system.png new file mode 100644 index 0000000..2356303 Binary files /dev/null and b/themes/eldritch/radarr_system.png differ diff --git a/themes/eldritch/sonarr_library.png b/themes/eldritch/sonarr_library.png new file mode 100644 index 0000000..dfe8f0d Binary files /dev/null and b/themes/eldritch/sonarr_library.png differ diff --git a/themes/eldritch/themes.yml b/themes/eldritch/themes.yml new file mode 100644 index 0000000..aba639e --- /dev/null +++ b/themes/eldritch/themes.yml @@ -0,0 +1,29 @@ +- name: eldritch + theme: + background: + enabled: true + color: "#212337" + default: + color: "#ebfafa" + downloaded: + color: "#37f499" + downloading: + color: "#f7c67f" + failure: + color: "#f16c75" + missing: + color: "#f7c67f" + unmonitored_missing: + color: "#7081d0" + help: + color: "#7081d0" + primary: + color: "#f265b5" + secondary: + color: "#04d1f9" + success: + color: "#37f499" + warning: + color: "#f1fc79" + unreleased: + color: "#ebfafa" \ No newline at end of file diff --git a/themes/watermelon-dark/README.md b/themes/watermelon-dark/README.md index b4536df..824705e 100644 --- a/themes/watermelon-dark/README.md +++ b/themes/watermelon-dark/README.md @@ -1,6 +1,6 @@ # Managarr Watermelon Dark Theme -The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the -Watermelon Dark Managarr theme. +The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the Watermelon Dark Managarr +theme. ## Screenshots diff --git a/themes/watermelon-dark/sonarr_library.png b/themes/watermelon-dark/sonarr_library.png index 21e6f0e..ec3c3bc 100644 Binary files a/themes/watermelon-dark/sonarr_library.png and b/themes/watermelon-dark/sonarr_library.png differ