Add nerd font icons and UI polish
All checks were successful
Build and Release / build-and-release (push) Successful in 1m18s
All checks were successful
Build and Release / build-and-release (push) Successful in 1m18s
- 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
This commit is contained in:
parent
f60ff02b2a
commit
ed6765039c
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cm-player"
|
name = "cm-player"
|
||||||
version = "0.1.13"
|
version = "0.1.14"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -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
|
// Only show selection bar when file panel has focus
|
||||||
let is_selected = !state.focus_playlist && idx == state.selected_index;
|
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 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
|
// Bold black icon on selection bar, blue otherwise
|
||||||
if is_selected {
|
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 {
|
} else {
|
||||||
Span::styled("▸ ", Style::default().fg(Theme::highlight()))
|
Span::styled(icon_char, Style::default().fg(Theme::highlight()))
|
||||||
}
|
}
|
||||||
} else {
|
} 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() {
|
let name_spans = if in_search && !search_query.is_empty() {
|
||||||
highlight_search_matches(&item.node.name, &search_query, is_selected)
|
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);
|
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)
|
let list = List::new(items)
|
||||||
.block(
|
.block(
|
||||||
Block::default()
|
Block::default()
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.title("Media Files")
|
.title("files")
|
||||||
.style(Theme::widget_border_style())
|
.style(Theme::widget_border_style())
|
||||||
.title_style(title_style),
|
.title_style(Theme::title_style()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut list_state = ListState::default();
|
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() {
|
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 {
|
} else {
|
||||||
"Playlist (empty)".to_string()
|
"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()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let playlist_widget = List::new(playlist_items)
|
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)
|
.borders(Borders::ALL)
|
||||||
.title(playlist_title)
|
.title(playlist_title)
|
||||||
.style(Theme::widget_border_style())
|
.style(Theme::widget_border_style())
|
||||||
.title_style(playlist_title_style),
|
.title_style(Theme::title_style()),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut playlist_state = ListState::default();
|
let mut playlist_state = ListState::default();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user