175 lines
7.2 KiB
Rust
175 lines
7.2 KiB
Rust
use std::fmt::write;
|
|
|
|
use egui::{Color32, RichText, Sense, Vec2};
|
|
use song_list_nav::SearchType;
|
|
use xmpd_cache::DlStatus;
|
|
use xmpd_manifest::{song::Song, store::BaseStore};
|
|
use super::{CompGetter, CompUi};
|
|
|
|
pub mod song_list_nav;
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct SongList {
|
|
selected_song_id: uuid::Uuid
|
|
}
|
|
|
|
component_register!(SongList);
|
|
|
|
impl CompUi for SongList {
|
|
fn draw(ui: &mut egui::Ui, state: &mut crate::GuiState) -> crate::Result<()> {
|
|
egui::ScrollArea::vertical()
|
|
.id_source("song_list")
|
|
.drag_to_scroll(false)
|
|
.show(ui, |ui| {
|
|
ui.vertical(|ui| {
|
|
ui.add_space(3.0);
|
|
let pid = {handle_error_ui!(super::left_nav::LeftNav::get()).selected_playlist_id.clone()};
|
|
match pid {
|
|
None => {
|
|
let mut songs: Vec<_> = state.manifest.store().get_songs().iter().collect();
|
|
songs.sort_by(|a, b| {
|
|
let a = a.1.name().to_lowercase();
|
|
let b = b.1.name().to_lowercase();
|
|
a.cmp(&b)
|
|
});
|
|
|
|
for (sid, song) in songs {
|
|
let query = {handle_error_ui!(song_list_nav::SongListNav::get()).parse_search()}.clone();
|
|
let should_display = match query {
|
|
SearchType::Source(s) if !s.is_empty() => format!("{:?}", &song.source_type()).to_lowercase().contains(&s),
|
|
SearchType::Author(s) if !s.is_empty() => song.author().to_lowercase().contains(&s),
|
|
SearchType::Name(s) if !s.is_empty() => song.name().to_owned().contains(&s),
|
|
_ => true
|
|
};
|
|
if should_display {
|
|
display_song_tab(ui, sid, song);
|
|
}
|
|
}
|
|
}
|
|
Some(pid) => {
|
|
if let Some(playlist) = state.manifest.store().get_playlist(&pid) {
|
|
let mut songs = Vec::new();
|
|
for sid in playlist.songs() {
|
|
if let Some(song) = state.manifest.store().get_song(&sid) {
|
|
songs.push((sid, song));
|
|
}
|
|
}
|
|
songs.sort_by(|a, b| {
|
|
let a = a.1.name().to_lowercase();
|
|
let b = b.1.name().to_lowercase();
|
|
a.cmp(&b)
|
|
});
|
|
let query = {handle_error_ui!(song_list_nav::SongListNav::get()).parse_search()}.clone();
|
|
for (sid, song) in songs {
|
|
let should_display = match query {
|
|
SearchType::Source(ref s) if !s.is_empty() => format!("{:?}", &song.source_type()).to_lowercase().contains(s),
|
|
SearchType::Author(ref s) if !s.is_empty() => song.author().to_lowercase().contains(s),
|
|
SearchType::Name(ref s) if !s.is_empty() => song.name().to_owned().contains(s),
|
|
_ => true
|
|
};
|
|
if should_display {
|
|
display_song_tab(ui, sid, song);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|
|
});
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn display_song_tab(ui: &mut egui::Ui, sid: &uuid::Uuid, song: &Song) {
|
|
let theme = handle_error_ui!(xmpd_settings::Settings::get()).theme.clone();
|
|
ui.horizontal(|ui| {
|
|
let mut clicked = ui.add(
|
|
egui::Image::new(crate::data::NOTE_ICON)
|
|
.tint(theme.accent_color)
|
|
.sense(Sense::click())
|
|
.fit_to_exact_size(Vec2::new(32.0, 32.0))
|
|
).clicked();
|
|
|
|
ui.vertical(|ui| {
|
|
let selected_song_id = {handle_error_ui!(SongList::get()).selected_song_id};
|
|
let label = if selected_song_id == *sid {
|
|
ui.label(
|
|
RichText::new(song.name())
|
|
.color(theme.accent_color)
|
|
)
|
|
} else {
|
|
ui.label(
|
|
RichText::new(song.name())
|
|
.color(theme.text_color)
|
|
)
|
|
};
|
|
|
|
if label.clicked() {
|
|
clicked = true;
|
|
}
|
|
ui.monospace(
|
|
RichText::new(format!("By {}", song.author()))
|
|
.color(theme.dim_text_color)
|
|
.size(10.0)
|
|
);
|
|
|
|
});
|
|
|
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::RIGHT), |ui| {
|
|
ui.add_space(3.0);
|
|
let status = {
|
|
handle_error_ui!(xmpd_cache::Cache::get()).get_cached_song_status(&sid).clone()
|
|
};
|
|
match status {
|
|
Some(DlStatus::Done(p)) => {
|
|
let img = ui.add(
|
|
egui::Image::new(crate::data::CHECK_ICON)
|
|
.tint(Color32::LIGHT_GREEN)
|
|
.sense(Sense::hover())
|
|
.fit_to_exact_size(Vec2::new(16.0, 16.0))
|
|
);
|
|
|
|
img.on_hover_ui(|ui| {
|
|
ui.label(format!("Path: {p}"));
|
|
});
|
|
}
|
|
Some(DlStatus::Downloading) => {
|
|
ui.add(
|
|
egui::Spinner::new()
|
|
.color(theme.accent_color)
|
|
.size(16.0)
|
|
);
|
|
}
|
|
Some(DlStatus::Error(e)) => {
|
|
let img = ui.add(
|
|
egui::Image::new(crate::data::WARN_ICON)
|
|
.tint(Color32::LIGHT_YELLOW)
|
|
.sense(Sense::hover())
|
|
.fit_to_exact_size(Vec2::new(16.0, 16.0))
|
|
);
|
|
img.on_hover_ui(|ui| {
|
|
ui.label(e);
|
|
});
|
|
}
|
|
None => {
|
|
let img = ui.add(
|
|
egui::Image::new(crate::data::DL_ICON)
|
|
.tint(theme.accent_color)
|
|
.sense(Sense::click())
|
|
.fit_to_exact_size(Vec2::new(16.0, 16.0))
|
|
);
|
|
if img.clicked() {
|
|
handle_error_ui!(xmpd_cache::Cache::get()).download_to_cache(sid.clone(), song.clone())
|
|
}
|
|
}
|
|
}
|
|
});
|
|
if clicked {
|
|
handle_error_ui!(SongList::get()).selected_song_id = sid.clone();
|
|
}
|
|
});
|
|
|
|
ui.separator();
|
|
}
|