From 821a844fe06f51def3301c5738d0b977da3faf1b Mon Sep 17 00:00:00 2001 From: Christoffer Martinsson Date: Sat, 13 Dec 2025 10:34:55 +0100 Subject: [PATCH] Add dynamic title bar colors based on player state Title bar background color changes: - Gray: Stopped or Paused - Green: Playing - Red: Error (when last_error is set) Main content border remains gray. --- src/state/mod.rs | 2 ++ src/ui/mod.rs | 17 +++++++++++------ src/ui/theme.rs | 8 ++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/state/mod.rs b/src/state/mod.rs index cb14f92..9983353 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -88,6 +88,7 @@ pub struct AppState { pub last_click_is_playlist: bool, pub context_menu: Option, pub play_mode: PlayMode, + pub last_error: Option, } #[derive(Debug, Clone)] @@ -141,6 +142,7 @@ impl AppState { last_click_is_playlist: false, context_menu: None, play_mode: PlayMode::Normal, + last_error: None, } } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 7efa85d..074a470 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -57,7 +57,7 @@ pub fn render(frame: &mut Frame, state: &mut AppState, player: &mut Player) -> ( Span::styled(playlist_text, playlist_style), ]); - // Create one border around the entire content area + // Create one border around the entire content area with fixed gray border let main_block = Block::default() .borders(Borders::ALL) .title(title) @@ -384,12 +384,17 @@ fn render_right_panel(frame: &mut Frame, state: &mut AppState, area: Rect, _tab_ } fn render_title_bar(frame: &mut Frame, state: &AppState, player: &mut Player, area: Rect) { - // Default to stopped if we can't query MPV + // Get player state let player_state = player.get_player_state().unwrap_or(PlayerState::Stopped); - let background_color = match player_state { - PlayerState::Playing => Theme::success(), // Green for playing - PlayerState::Paused => Theme::highlight(), // Blue for paused - PlayerState::Stopped => Theme::dim_foreground(), // Gray for stopped + + // Title bar background color: red for error, gray for stopped/paused, green for playing + let background_color = if state.last_error.is_some() { + Theme::error() + } else { + match player_state { + PlayerState::Playing => Theme::success(), // Green for playing + PlayerState::Paused | PlayerState::Stopped => Theme::border(), // Gray for paused/stopped + } }; // Split the title bar into left and right sections diff --git a/src/ui/theme.rs b/src/ui/theme.rs index 4bd5e79..19f27ff 100644 --- a/src/ui/theme.rs +++ b/src/ui/theme.rs @@ -34,6 +34,10 @@ impl Theme { Color::Rgb(215, 175, 95) // #d7af5f } + pub fn normal_red() -> Color { + Color::Rgb(215, 95, 95) // #d75f5f + } + // Semantic mappings pub fn secondary_text() -> Color { Self::foreground() @@ -59,6 +63,10 @@ impl Theme { Self::normal_yellow() } + pub fn error() -> Color { + Self::normal_red() + } + // Styles pub fn widget_border_style() -> Style { Style::default().fg(Self::border()).bg(Self::background())