feat: Added the Eldritch theme and updated documentation

This commit is contained in:
2025-03-10 15:49:40 -06:00
parent 0834802481
commit b4ff5f3351
24 changed files with 214 additions and 103 deletions
+8 -1
View File
@@ -207,7 +207,14 @@ Key:
- [ ] Support for Tautulli - [ ] Support for Tautulli
### Themes ### 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 ### The Managarr CLI
Managarr can be used in one of two ways: As a TUI, or as a CLI for managing your Servarrs. Managarr can be used in one of two ways: As a TUI, or as a CLI for managing your Servarrs.
-2
View File
@@ -33,8 +33,6 @@ use crate::ui::{ui, THEME};
use crate::utils::load_theme_config; use crate::utils::load_theme_config;
mod app; mod app;
mod builtin_themes;
mod builtin_themes_tests;
mod cli; mod cli;
mod event; mod event;
mod handlers; mod handlers;
@@ -6,8 +6,8 @@ use std::str::FromStr;
#[path = "builtin_themes_tests.rs"] #[path = "builtin_themes_tests.rs"]
mod builtin_themes_tests; mod builtin_themes_tests;
pub fn get_builtin_themes() -> Vec<ThemeDefinition> { pub(in crate::ui) fn watermelon_dark_theme() -> Theme {
let watermelon_dark = Theme { Theme {
background: Some(Background { background: Some(Background {
enabled: Some(false), enabled: Some(false),
color: Some(Color::from_str("#233237").unwrap()), color: Some(Color::from_str("#233237").unwrap()),
@@ -31,11 +31,14 @@ pub fn get_builtin_themes() -> Vec<ThemeDefinition> {
color: Some(Color::from_str("#8c19ff").unwrap()), color: Some(Color::from_str("#8c19ff").unwrap()),
}), }),
..Theme::default() ..Theme::default()
}; }
let dracula = Theme { }
pub(in crate::ui) fn dracula_theme() -> Theme {
Theme {
background: Some(Background { background: Some(Background {
enabled: Some(false), enabled: Some(true),
color: Some(Color::from_str("#233237").unwrap()), color: Some(Color::from_str("#232326").unwrap()),
}), }),
default: Some(Style { default: Some(Style {
color: Some(Color::from_str("#f8f8f2").unwrap()), color: Some(Color::from_str("#f8f8f2").unwrap()),
@@ -74,7 +77,56 @@ pub fn get_builtin_themes() -> Vec<ThemeDefinition> {
color: Some(Color::from_str("#f8f8f2").unwrap()), color: Some(Color::from_str("#f8f8f2").unwrap()),
}), }),
..Theme::default() ..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<ThemeDefinition> {
vec![ vec![
ThemeDefinition { ThemeDefinition {
name: "default".to_owned(), name: "default".to_owned(),
@@ -82,11 +134,15 @@ pub fn get_builtin_themes() -> Vec<ThemeDefinition> {
}, },
ThemeDefinition { ThemeDefinition {
name: "watermelon-dark".to_owned(), name: "watermelon-dark".to_owned(),
theme: watermelon_dark, theme: watermelon_dark_theme(),
}, },
ThemeDefinition { ThemeDefinition {
name: "dracula".to_owned(), name: "dracula".to_owned(),
theme: dracula, theme: dracula_theme(),
},
ThemeDefinition {
name: "eldritch".to_owned(),
theme: eldritch_theme(),
}, },
] ]
} }
@@ -1,6 +1,6 @@
#[cfg(test)] #[cfg(test)]
mod 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 crate::ui::theme::{Background, Style, Theme, ThemeDefinition};
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use ratatui::prelude::Color; use ratatui::prelude::Color;
@@ -35,8 +35,8 @@ mod test {
}; };
let dracula = Theme { let dracula = Theme {
background: Some(Background { background: Some(Background {
enabled: Some(false), enabled: Some(true),
color: Some(Color::from_str("#233237").unwrap()), color: Some(Color::from_str("#232326").unwrap()),
}), }),
default: Some(Style { default: Some(Style {
color: Some(Color::from_str("#f8f8f2").unwrap()), color: Some(Color::from_str("#f8f8f2").unwrap()),
@@ -76,6 +76,49 @@ mod test {
}), }),
..Theme::default() ..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![ let expected_themes = vec![
ThemeDefinition { ThemeDefinition {
name: "default".to_owned(), name: "default".to_owned(),
@@ -89,6 +132,10 @@ mod test {
name: "dracula".to_owned(), name: "dracula".to_owned(),
theme: dracula, theme: dracula,
}, },
ThemeDefinition {
name: "eldritch".to_owned(),
theme: eldritch,
},
]; ];
assert_eq!(expected_themes, get_builtin_themes()); assert_eq!(expected_themes, get_builtin_themes());
+1
View File
@@ -24,6 +24,7 @@ use crate::ui::utils::{
use crate::ui::widgets::input_box::InputBox; use crate::ui::widgets::input_box::InputBox;
use crate::ui::widgets::popup::Size; use crate::ui::widgets::popup::Size;
mod builtin_themes;
mod radarr_ui; mod radarr_ui;
mod sonarr_ui; mod sonarr_ui;
mod styles; mod styles;
+3 -3
View File
@@ -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(quality.quality.name.to_owned()),
Cell::from(date.to_string()), Cell::from(date.to_string()),
]) ])
.success() .primary()
}; };
let help_footer = app let help_footer = app
.data .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(person_name.to_owned()),
Cell::from(character.clone().unwrap_or_default()), Cell::from(character.clone().unwrap_or_default()),
]) ])
.success() .primary()
}; };
let content = Some(&mut movie_details_modal.movie_cast); let content = Some(&mut movie_details_modal.movie_cast);
let help_footer = app 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(job.clone().unwrap_or_default()),
Cell::from(department.clone().unwrap_or_default()), Cell::from(department.clone().unwrap_or_default()),
]) ])
.success() .primary()
}; };
let content = Some(&mut movie_details_modal.movie_crew); let content = Some(&mut movie_details_modal.movie_crew);
let help_footer = app let help_footer = app
+1 -1
View File
@@ -1,4 +1,4 @@
use crate::builtin_themes::get_builtin_themes; use crate::ui::builtin_themes::get_builtin_themes;
use anyhow::Result; use anyhow::Result;
use derivative::Derivative; use derivative::Derivative;
use ratatui::style::Color; use ratatui::style::Color;
+7 -71
View File
@@ -1,8 +1,8 @@
mod tests { mod tests {
use crate::ui::builtin_themes::{dracula_theme, eldritch_theme, watermelon_dark_theme};
use crate::ui::theme::{Background, Style, Theme, ThemeDefinition, ThemeDefinitionsWrapper}; use crate::ui::theme::{Background, Style, Theme, ThemeDefinition, ThemeDefinitionsWrapper};
use pretty_assertions::{assert_eq, assert_str_eq}; use pretty_assertions::{assert_eq, assert_str_eq};
use ratatui::style::Color; use ratatui::style::Color;
use std::str::FromStr;
#[test] #[test]
fn test_background_default() { fn test_background_default() {
@@ -192,74 +192,6 @@ warning:
#[test] #[test]
fn test_theme_definitions_wrapper_default() { 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 { let theme_definitions_wrapper = ThemeDefinitionsWrapper {
theme_definitions: vec![ theme_definitions: vec![
ThemeDefinition { ThemeDefinition {
@@ -268,11 +200,15 @@ warning:
}, },
ThemeDefinition { ThemeDefinition {
name: "watermelon-dark".to_owned(), name: "watermelon-dark".to_owned(),
theme: watermelon_dark, theme: watermelon_dark_theme(),
}, },
ThemeDefinition { ThemeDefinition {
name: "dracula".to_owned(), name: "dracula".to_owned(),
theme: dracula, theme: dracula_theme(),
},
ThemeDefinition {
name: "eldritch".to_owned(),
theme: eldritch_theme(),
}, },
], ],
}; };
+32 -1
View File
@@ -18,6 +18,9 @@ custom theme off of. The following themes are included by default:
### [Dracula](./dracula/README.md) ### [Dracula](./dracula/README.md)
![sonarr-library](./dracula/sonarr_library.png) ![sonarr-library](./dracula/sonarr_library.png)
### [Eldritch](./eldritch/README.md)
![sonarr-library](./eldritch/sonarr_library.png)
### [Watermelon Dark](./watermelon-dark/README.md) ### [Watermelon Dark](./watermelon-dark/README.md)
![sonarr-library](./watermelon-dark/sonarr_library.png) ![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 - name: my-theme
theme: theme:
background: background:
enabled: true # Disable for transparent backgrounds # Disable for transparent backgrounds
enabled: true
# Color of the full system background
color: "#233237" color: "#233237"
awaiting_import: awaiting_import:
# Color for items awaiting import
color: "#FFAA42" color: "#FFAA42"
indeterminate: indeterminate:
# Color for when item status is unknown
color: "#FFAA42" color: "#FFAA42"
default: default:
# Default color for text and uncolored elements
color: "#FFFFFF" color: "#FFFFFF"
downloaded: downloaded:
# Color for downloaded items (when monitored)
color: "#00FF00" color: "#00FF00"
downloading: downloading:
# Color for items currently downloading
color: "#762671" color: "#762671"
failure: failure:
# Color for errors, no seeders, disabled indexers,
# failed indexer test results, etc.
color: "#DE382B" color: "#DE382B"
help: help:
# Color for help text like hotkeys and tooltips
color: "#00FFFF" color: "#00FFFF"
missing: missing:
# Color for missing items
color: "#DE382B" color: "#DE382B"
primary: 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" color: "#2CB5E9"
secondary: secondary:
# Color for selected tabs, Warn log events, Paragraph headers (e.g. "Name: "),
# and uncolored Message box contents
color: "#FFC706" color: "#FFC706"
success: 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" color: "#39B54A"
system_function: system_function:
# Color for system functions like selected UI elements (e.g. checkboxes, yes/no prompts),
# or loading spinner
color: "#FFC706" color: "#FFC706"
unmonitored: unmonitored:
# Color for unmonitored items
color: "#808080" color: "#808080"
unmonitored_missing: unmonitored_missing:
# Color for unmonitored items that are also missing
color: "#FFC706" color: "#FFC706"
unreleased: unreleased:
# Color for unreleased items
color: "#00FFFF" color: "#00FFFF"
warning: warning:
# Color for fewer seeders than leechers
color: "#FF00FF" 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`: In order to activate your custom theme, you can either update your `config.yml`:
```yaml ```yaml
+1 -2
View File
@@ -1,6 +1,5 @@
# Managarr Default Theme # Managarr Default Theme
The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the default Managarr theme.
default Managarr theme.
## Screenshots ## Screenshots
Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

After

Width:  |  Height:  |  Size: 230 KiB

+1 -2
View File
@@ -1,6 +1,5 @@
# Managarr Dracula Theme # Managarr Dracula Theme
The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the Dracula Managarr theme.
Dracula Managarr theme.
## Screenshots ## Screenshots
Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 KiB

After

Width:  |  Height:  |  Size: 345 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 366 KiB

After

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

After

Width:  |  Height:  |  Size: 232 KiB

+2 -2
View File
@@ -1,8 +1,8 @@
- name: dracula - name: dracula
theme: theme:
background: background:
enabled: false enabled: true
color: "#282a36" color: "#232326"
default: default:
color: "#f8f8f2" color: "#f8f8f2"
downloaded: downloaded:
+8
View File
@@ -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)
Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

+29
View File
@@ -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"
+2 -2
View File
@@ -1,6 +1,6 @@
# Managarr Watermelon Dark Theme # Managarr Watermelon Dark Theme
The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the The [themes.yml](./themes.yml) file in this directory corresponds to the theme configuration for the Watermelon Dark Managarr
Watermelon Dark Managarr theme. theme.
## Screenshots ## Screenshots
Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 KiB

After

Width:  |  Height:  |  Size: 433 KiB