diff --git a/frontend/src/api.rs b/frontend/src/api.rs index fbf4982..fcc92e0 100644 --- a/frontend/src/api.rs +++ b/frontend/src/api.rs @@ -85,18 +85,6 @@ pub async fn get_me() -> Result { get_json(&format!("{BASE}/auth/me")).await } -pub async fn list_users() -> Result, ApiError> { - get_json(&format!("{BASE}/auth/users")).await -} - -pub async fn create_user(username: &str, password: &str) -> Result { - let body = serde_json::json!({"username": username, "password": password}).to_string(); - post_json(&format!("{BASE}/auth/users"), &body).await -} - -pub async fn delete_user(id: i32) -> Result<(), ApiError> { - delete(&format!("{BASE}/auth/users/{id}")).await -} // --- Lyrics --- pub async fn get_lyrics(artist: &str, title: &str) -> Result { @@ -142,10 +130,6 @@ pub async fn list_artists(limit: u64, offset: u64) -> Result get_json(&format!("{BASE}/artists?limit={limit}&offset={offset}")).await } -pub async fn get_artist(id: i32) -> Result { - get_json(&format!("{BASE}/artists/{id}")).await -} - pub async fn get_artist_full(id: &str) -> Result { get_json(&format!("{BASE}/artists/{id}/full")).await } @@ -158,9 +142,6 @@ pub async fn get_album(mbid: &str) -> Result { get_json(&format!("{BASE}/albums/{mbid}")).await } -pub async fn list_tracks(limit: u64, offset: u64) -> Result, ApiError> { - get_json(&format!("{BASE}/tracks?limit={limit}&offset={offset}")).await -} // --- Watchlist --- pub async fn add_artist(name: &str, mbid: Option<&str>) -> Result { @@ -183,13 +164,6 @@ pub async fn add_album( post_json(&format!("{BASE}/albums"), &body).await } -pub async fn get_watchlist() -> Result, ApiError> { - get_json(&format!("{BASE}/watchlist")).await -} - -pub async fn remove_watchlist(id: i32) -> Result<(), ApiError> { - delete(&format!("{BASE}/watchlist/{id}")).await -} // --- Downloads --- pub async fn get_downloads(status: Option<&str>) -> Result, ApiError> { @@ -249,9 +223,6 @@ pub async fn trigger_organize() -> Result { post_empty(&format!("{BASE}/organize")).await } -pub async fn get_task(id: &str) -> Result { - get_json(&format!("{BASE}/tasks/{id}")).await -} pub async fn get_config() -> Result { get_json(&format!("{BASE}/config")).await diff --git a/frontend/src/components/mod.rs b/frontend/src/components/mod.rs index a651b7c..9986740 100644 --- a/frontend/src/components/mod.rs +++ b/frontend/src/components/mod.rs @@ -1,3 +1,2 @@ pub mod navbar; pub mod status_badge; -pub mod watch_indicator; diff --git a/frontend/src/components/watch_indicator.rs b/frontend/src/components/watch_indicator.rs deleted file mode 100644 index c3221ac..0000000 --- a/frontend/src/components/watch_indicator.rs +++ /dev/null @@ -1,25 +0,0 @@ -use yew::prelude::*; - -#[derive(Properties, PartialEq)] -pub struct Props { - pub status: String, -} - -#[function_component(WatchIndicator)] -pub fn watch_indicator(props: &Props) -> Html { - let (icon, color, title) = match props.status.as_str() { - "owned" => ("●", "var(--success)", "Owned"), - "partial" => ("◐", "var(--warning)", "Partial"), - "wanted" => ("○", "var(--accent)", "Wanted"), - "downloading" => ("↓", "var(--accent)", "Downloading"), - "fully_watched" => ("●", "var(--accent)", "Fully watched"), - "unwatched" => ("○", "var(--text-muted)", "Not watched"), - _ => ("○", "var(--text-muted)", "Unknown"), - }; - - html! { - - { icon } - - } -} diff --git a/frontend/src/pages/album.rs b/frontend/src/pages/album.rs index d7980fa..a3e9255 100644 --- a/frontend/src/pages/album.rs +++ b/frontend/src/pages/album.rs @@ -82,7 +82,7 @@ pub fn album_page(props: &Props) -> Html { { for d.tracks.iter().map(|t| { let duration = t.duration_ms - .map(|ms| fmt_duration(ms)) + .map(&fmt_duration) .unwrap_or_default(); let track_key = t.recording_mbid.clone(); diff --git a/frontend/src/pages/artist.rs b/frontend/src/pages/artist.rs index 4e61850..8212a93 100644 --- a/frontend/src/pages/artist.rs +++ b/frontend/src/pages/artist.rs @@ -58,14 +58,11 @@ pub fn artist_page(props: &Props) -> Html { // Phase 2: if not enriched, fetch full data in background if needs_enrich && !user_acted.get() { - match api::get_artist_full(&id).await { - Ok(full) => { - // Only apply if user hasn't triggered a refresh - if !user_acted.get() { - detail.set(Some(full)); - } + if let Ok(full) = api::get_artist_full(&id).await { + // Only apply if user hasn't triggered a refresh + if !user_acted.get() { + detail.set(Some(full)); } - Err(_) => {} // quick data is still showing, don't overwrite with error } } } @@ -326,8 +323,7 @@ pub fn artist_page(props: &Props) -> Html { if tc > 0 { = tc { "color: var(--accent);" } - else if album.watched_tracks > 0 { "color: var(--accent);" } + if album.watched_tracks > 0 { "color: var(--accent);" } else { "color: var(--text-muted);" } }> { format!("{}/{}", album.watched_tracks, tc) } diff --git a/frontend/src/pages/downloads.rs b/frontend/src/pages/downloads.rs index b177bfe..69deb48 100644 --- a/frontend/src/pages/downloads.rs +++ b/frontend/src/pages/downloads.rs @@ -10,7 +10,7 @@ pub fn downloads_page() -> Html { let items = use_state(|| None::>); let error = use_state(|| None::); let message = use_state(|| None::); - let dl_query = use_state(|| String::new()); + let dl_query = use_state(String::new); let refresh = { let items = items.clone(); diff --git a/frontend/src/pages/library.rs b/frontend/src/pages/library.rs index 864516a..598d420 100644 --- a/frontend/src/pages/library.rs +++ b/frontend/src/pages/library.rs @@ -2,7 +2,6 @@ use yew::prelude::*; use yew_router::prelude::*; use crate::api; -use crate::components::watch_indicator::WatchIndicator; use crate::pages::Route; use crate::types::ArtistListItem; @@ -73,8 +72,7 @@ pub fn library_page() -> Html { if a.total_items > 0 { = a.total_items { "color: var(--accent);" } - else if a.total_watched > 0 { "color: var(--accent);" } + if a.total_watched > 0 { "color: var(--accent);" } else { "color: var(--text-muted);" } }> { format!("{}/{}", a.total_watched, a.total_items) } diff --git a/frontend/src/pages/search.rs b/frontend/src/pages/search.rs index 066e714..5b74d6c 100644 --- a/frontend/src/pages/search.rs +++ b/frontend/src/pages/search.rs @@ -16,7 +16,7 @@ enum SearchResults { #[function_component(SearchPage)] pub fn search_page() -> Html { - let query = use_state(|| String::new()); + let query = use_state(String::new); let search_type = use_state(|| "artist".to_string()); let results = use_state(|| SearchResults::None); let error = use_state(|| None::); diff --git a/frontend/src/types.rs b/frontend/src/types.rs index 2bb1114..581cd69 100644 --- a/frontend/src/types.rs +++ b/frontend/src/types.rs @@ -97,16 +97,6 @@ pub struct LyricsResult { pub synced_lyrics: Option, } -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub struct Album { - pub id: i32, - pub name: String, - pub album_artist: String, - pub year: Option, - pub genre: Option, - pub musicbrainz_id: Option, -} - #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct Track { pub id: i32, @@ -120,18 +110,6 @@ pub struct Track { pub codec: Option, } -#[derive(Debug, Clone, PartialEq, Deserialize)] -pub struct ArtistDetail { - pub artist: Artist, - pub albums: Vec, -} - -#[derive(Debug, Clone, PartialEq, Deserialize)] -pub struct AlbumDetail { - pub album: Album, - pub tracks: Vec, -} - /// Album detail from MusicBrainz (the primary album view). #[derive(Debug, Clone, PartialEq, Deserialize)] pub struct MbAlbumDetail { @@ -182,17 +160,6 @@ pub struct TrackResult { pub score: u8, } -// --- Watchlist --- - -#[derive(Debug, Clone, PartialEq, Deserialize)] -pub struct WatchListEntry { - pub id: i32, - pub item_type: String, - pub name: String, - pub artist_name: Option, - pub status: String, -} - // --- Downloads --- #[derive(Debug, Clone, PartialEq, Deserialize)] diff --git a/src/routes/artists.rs b/src/routes/artists.rs index e8bae86..b2372f0 100644 --- a/src/routes/artists.rs +++ b/src/routes/artists.rs @@ -623,16 +623,16 @@ async fn fetch_wikipedia_data( let cache_key = format!("artist_wiki:{mbid}"); // Check cache first - if let Ok(Some(json)) = queries::cache::get(state.db.conn(), &cache_key).await { - if let Ok(cached) = serde_json::from_str::(&json) { - return ( - cached - .get("photo_url") - .and_then(|v| v.as_str()) - .map(String::from), - cached.get("bio").and_then(|v| v.as_str()).map(String::from), - ); - } + if let Ok(Some(json)) = queries::cache::get(state.db.conn(), &cache_key).await + && let Ok(cached) = serde_json::from_str::(&json) + { + return ( + cached + .get("photo_url") + .and_then(|v| v.as_str()) + .map(String::from), + cached.get("bio").and_then(|v| v.as_str()).map(String::from), + ); } // Find Wikipedia URL from artist info — try direct link first, then resolve via Wikidata @@ -641,7 +641,7 @@ async fn fetch_wikipedia_data( Some(u.url.clone()) } else if let Some(wd) = info.urls.iter().find(|u| u.link_type == "wikidata") { // Extract Wikidata entity ID and resolve to Wikipedia URL - let entity_id = wd.url.split('/').last().unwrap_or(""); + let entity_id = wd.url.split('/').next_back().unwrap_or(""); resolve_wikidata_to_wikipedia(entity_id).await } else { None