use std::collections::HashMap; use yew::prelude::*; use crate::api; use crate::components::status_badge::StatusBadge; use crate::types::{LyricsResult, MbAlbumDetail}; #[derive(Properties, PartialEq)] pub struct Props { pub mbid: String, } #[function_component(AlbumPage)] pub fn album_page(props: &Props) -> Html { let detail = use_state(|| None::); let error = use_state(|| None::); let mbid = props.mbid.clone(); let lyrics_cache: UseStateHandle> = use_state(HashMap::new); let active_lyrics = use_state(|| None::); { let detail = detail.clone(); let error = error.clone(); let mbid = mbid.clone(); use_effect_with(mbid.clone(), move |_| { wasm_bindgen_futures::spawn_local(async move { match api::get_album(&mbid).await { Ok(d) => detail.set(Some(d)), Err(e) => error.set(Some(e.0)), } }); }); } if let Some(ref err) = *error { return html! {
{ format!("Error: {err}") }
}; } let Some(ref d) = *detail else { return html! {

{ "Loading album from MusicBrainz..." }

}; }; let fmt_duration = |ms: u64| -> String { let secs = ms / 1000; let mins = secs / 60; let remaining = secs % 60; format!("{mins}:{remaining:02}") }; let cover_url = format!("https://coverartarchive.org/release/{}/front-250", d.mbid); html! {
() { el.set_attribute("style", "display:none").ok(); } })} />

{ "Album" }

{ format!("MBID: {}", d.mbid) }

{ format!("Tracks ({})", d.tracks.len()) }

if d.tracks.is_empty() {

{ "No tracks found." }

} else { { for d.tracks.iter().map(|t| { let duration = t.duration_ms .map(|ms| fmt_duration(ms)) .unwrap_or_default(); let track_key = t.recording_mbid.clone(); let is_active = active_lyrics.as_ref() == Some(&track_key); let cached = lyrics_cache.get(&track_key).cloned(); let on_lyrics_click = { let active = active_lyrics.clone(); let cache = lyrics_cache.clone(); let title = t.title.clone(); let key = track_key.clone(); Callback::from(move |_: MouseEvent| { let active = active.clone(); let cache = cache.clone(); let title = title.clone(); let key = key.clone(); if active.as_ref() == Some(&key) { active.set(None); return; } active.set(Some(key.clone())); if cache.contains_key(&key) { return; } wasm_bindgen_futures::spawn_local(async move { if let Ok(result) = api::get_lyrics("", &title).await { let mut map = (*cache).clone(); map.insert(key, result); cache.set(map); } }); }) }; html! { <> if is_active { } } })}
{ "#" } { "Title" } { "Duration" } { "Status" }
{ t.track_number.map(|n| n.to_string()).unwrap_or_default() } { &t.title } { duration } if let Some(ref status) = t.status { } else { { "\u{2014}" } }
{ match cached { Some(ref lr) if lr.found => html! {
{ lr.synced_lyrics.as_deref().or(lr.lyrics.as_deref()).unwrap_or("") }
}, Some(_) => html! {

{ "No lyrics found." }

}, None => html! {

{ "Loading lyrics..." }

}, }}
}
} }