From ed6765039c3acb50c41723fd7ae3cc099dca3653 Mon Sep 17 00:00:00 2001 From: Christoffer Martinsson Date: Mon, 8 Dec 2025 23:07:28 +0100 Subject: [PATCH] Add nerd font icons and UI polish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add nerd font file type icons: - Folder icons: closed/open folders with visual state - Music files: icon in green (mp3, flac, wav, ogg, etc.) - Video files: icon in yellow (mp4, mkv, avi, mov, etc.) - Add spacing after icons for better readability - Add "Refresh" option to title bar right-click menu - Make all context menus more compact (13 chars wide) - Change panel titles to lowercase: - "Media Files" → "files" - "Playlist" → "playlist" - Remove bold styling from focused panel titles - All icons show as bold black on selection bar - Folders show in blue, music in green, video in yellow --- Cargo.toml | 2 +- src/ui/mod.rs | 56 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f68cb07..827b772 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cm-player" -version = "0.1.13" +version = "0.1.14" edition = "2021" [dependencies] diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 60d97fe..a6e8b2b 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -147,16 +147,40 @@ fn render_file_panel(frame: &mut Frame, state: &mut AppState, area: Rect) { // Only show selection bar when file panel has focus let is_selected = !state.focus_playlist && idx == state.selected_index; - // Add folder icon for directories + // Add icon for directories and files let icon = if item.node.is_dir { + let is_expanded = state.expanded_dirs.contains(&item.node.path); + // Nerd font folder icons: \u{eaf7} = open, \u{ea83} = closed + let icon_char = if is_expanded { "\u{eaf7} " } else { "\u{ea83} " }; + // Bold black icon on selection bar, blue otherwise if is_selected { - Span::styled("▸ ", Style::default().fg(Theme::background()).add_modifier(Modifier::BOLD)) + Span::styled(icon_char, Style::default().fg(Theme::background()).add_modifier(Modifier::BOLD)) } else { - Span::styled("▸ ", Style::default().fg(Theme::highlight())) + Span::styled(icon_char, Style::default().fg(Theme::highlight())) } } else { - Span::raw(" ") + // File icons based on extension + let extension = item.node.path.extension() + .and_then(|e| e.to_str()) + .unwrap_or("") + .to_lowercase(); + + let (icon_char, color) = match extension.as_str() { + // Audio files - music note icon + "mp3" | "flac" | "wav" | "ogg" | "m4a" | "aac" | "wma" | "opus" => + ("\u{f0e2a} ", Theme::success()), // + // Video files - film icon + "mp4" | "mkv" | "avi" | "mov" | "webm" | "flv" | "wmv" | "m4v" => + ("\u{f1c8} ", Theme::warning()), // + _ => (" ", Theme::foreground()), + }; + + if is_selected { + Span::styled(icon_char, Style::default().fg(Theme::background()).add_modifier(Modifier::BOLD)) + } else { + Span::styled(icon_char, Style::default().fg(color)) + } }; let name_spans = if in_search && !search_query.is_empty() { highlight_search_matches(&item.node.name, &search_query, is_selected) @@ -201,20 +225,13 @@ fn render_file_panel(frame: &mut Frame, state: &mut AppState, area: Rect) { items.push(more_item); } - let title_style = if !state.focus_playlist { - // File panel has focus - bold title - Theme::title_style().add_modifier(Modifier::BOLD) - } else { - Theme::title_style() - }; - let list = List::new(items) .block( Block::default() .borders(Borders::ALL) - .title("Media Files") + .title("files") .style(Theme::widget_border_style()) - .title_style(title_style), + .title_style(Theme::title_style()), ); let mut list_state = ListState::default(); @@ -311,16 +328,9 @@ fn render_right_panel(frame: &mut Frame, state: &mut AppState, area: Rect) { } let playlist_title = if !state.playlist.is_empty() { - format!("Playlist [{}/{}]", state.playlist_index + 1, state.playlist.len()) + format!("playlist [{}/{}]", state.playlist_index + 1, state.playlist.len()) } else { - "Playlist (empty)".to_string() - }; - - let playlist_title_style = if state.focus_playlist { - // Playlist has focus - bold title - Theme::title_style().add_modifier(Modifier::BOLD) - } else { - Theme::title_style() + "playlist (empty)".to_string() }; let playlist_widget = List::new(playlist_items) @@ -329,7 +339,7 @@ fn render_right_panel(frame: &mut Frame, state: &mut AppState, area: Rect) { .borders(Borders::ALL) .title(playlist_title) .style(Theme::widget_border_style()) - .title_style(playlist_title_style), + .title_style(Theme::title_style()), ); let mut playlist_state = ListState::default();