fix(themes): make channel mode background optional (#614)

## 📺 PR Description

<!-- summary of the change + which issue is fixed if applicable. -->
Fixes https://github.com/alexpasmantier/television/issues/603.

Regarding the 2nd point of [your
comment](https://github.com/alexpasmantier/television/issues/603#issuecomment-3048772061),
@alexpasmantier:

> - display a custom error message instead of panicking when themes,
**configuration** and **channels** encounter a parsing error

I couldn't find anything specific for other configuration or channels
regarding parsing errors, they're already properly handled it seems.
Although there's a high chance I might've missed something. Please do
let me know if I did.

## Checklist

<!-- a quick pass through the following items to make sure you haven't
forgotten anything -->

- [x] my commits **and PR title** follow the [conventional
commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) format
- [ ] if this is a new feature, I have added tests to consolidate the
feature and prevent regressions
- [x] if this is a bug fix, I have added a test that reproduces the bug
(if applicable)
- [x] I have added a reasonable amount of documentation to the code
where appropriate

Co-authored-by: Kapobajza <kapobajza@gmail.com>
This commit is contained in:
kapobajza 2025-07-10 18:28:23 +02:00 committed by GitHub
parent 20be709ee9
commit e4a6447d75
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -180,7 +180,7 @@ struct Inner {
preview_title_fg: String,
//modes
channel_mode_fg: String,
channel_mode_bg: String,
channel_mode_bg: Option<String>,
remote_control_mode_fg: String,
remote_control_mode_bg: String,
}
@ -190,7 +190,10 @@ impl<'de> Deserialize<'de> for Theme {
where
D: serde::Deserializer<'de>,
{
let inner = Inner::deserialize(deserializer).unwrap();
let inner = Inner::deserialize(deserializer).unwrap_or_else(|err| {
eprintln!("Failed to deserialize theme: {}", err);
std::process::exit(1);
});
Ok(Self {
background: inner
.background
@ -301,13 +304,13 @@ impl<'de> Deserialize<'de> for Theme {
&inner.channel_mode_fg
))
})?,
channel_mode_bg: Color::from_str(&inner.channel_mode_bg)
.ok_or_else(|| {
serde::de::Error::custom(format!(
"invalid color {}",
&inner.channel_mode_bg
))
channel_mode_bg: match inner.channel_mode_bg {
Some(s) => Color::from_str(&s).ok_or_else(|| {
serde::de::Error::custom(format!("invalid color {}", &s))
})?,
// Default to black. Not sure if black is the best choice
None => Color::Ansi(ANSIColor::Black),
},
remote_control_mode_fg: Color::from_str(
&inner.remote_control_mode_fg,
)
@ -558,4 +561,56 @@ mod tests {
Color::Ansi(ANSIColor::BrightWhite)
);
}
#[test]
fn test_theme_deserialization_invalid_color() {
let theme_content = r##"
background = "#000000"
border_fg = "invalid-color"
text_fg = "white"
dimmed_text_fg = "bright-black"
input_text_fg = "bright-white"
result_count_fg = "bright-white"
result_name_fg = "bright-white"
result_line_number_fg = "bright-white"
result_value_fg = "bright-white"
selection_bg = "bright-white"
selection_fg = "bright-white"
match_fg = "bright-white"
preview_title_fg = "bright-white"
channel_mode_fg = "bright-white"
channel_mode_bg = "bright-black"
remote_control_mode_fg = "bright-white"
remote_control_mode_bg = "bright-black"
"##;
let result: Result<Theme, _> = toml::from_str(theme_content);
assert!(result.is_err());
if let Err(e) = result {
assert!(e.to_string().contains("invalid color invalid-color"));
}
}
#[test]
fn test_theme_deserialization_fallback_channel_mode_bg() {
let theme_content = r##"
background = "#000000"
border_fg = "black"
text_fg = "white"
dimmed_text_fg = "bright-black"
input_text_fg = "bright-white"
result_count_fg = "bright-white"
result_name_fg = "bright-white"
result_line_number_fg = "bright-white"
result_value_fg = "bright-white"
selection_bg = "bright-white"
selection_fg = "bright-white"
match_fg = "bright-white"
preview_title_fg = "bright-white"
channel_mode_fg = "bright-white"
remote_control_mode_fg = "bright-white"
remote_control_mode_bg = "bright-black"
"##;
let theme: Theme = toml::from_str(theme_content).unwrap();
assert_eq!(theme.channel_mode_bg, Color::Ansi(ANSIColor::Black));
}
}