I **think** I've at least 99% fixed the top songs mismatch
This commit is contained in:
@@ -21,6 +21,11 @@ pub fn artist_page(props: &Props) -> Html {
|
||||
let message = use_state(|| None::<String>);
|
||||
let active_tab = use_state(|| "discography".to_string());
|
||||
let top_songs_limit = use_state(|| 25usize);
|
||||
// Track top song status overrides — use Rc<RefCell> so async callbacks always see latest state
|
||||
let top_song_overrides: Rc<std::cell::RefCell<std::collections::HashMap<usize, Option<String>>>> =
|
||||
use_mut_ref(std::collections::HashMap::new);
|
||||
// Counter to force re-renders when overrides change
|
||||
let overrides_version = use_state(|| 0u32);
|
||||
let id = props.id.clone();
|
||||
|
||||
// Flag to prevent the background enrichment from overwriting a user-triggered refresh
|
||||
@@ -314,50 +319,65 @@ pub fn artist_page(props: &Props) -> Html {
|
||||
<tbody>
|
||||
{ for visible.iter().enumerate().map(|(i, song)| {
|
||||
let rank = i + 1;
|
||||
let has_status = song.status.is_some();
|
||||
// Use override status if set, otherwise use the original
|
||||
let effective_status = top_song_overrides
|
||||
.borrow()
|
||||
.get(&i)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| song.status.clone());
|
||||
let has_status = effective_status.is_some();
|
||||
// Check if this song is in-flight (override set to exactly "pending")
|
||||
let is_pending = top_song_overrides
|
||||
.borrow()
|
||||
.get(&i)
|
||||
.map(|s| s.as_deref() == Some("pending"))
|
||||
.unwrap_or(false);
|
||||
|
||||
let on_watch = {
|
||||
let detail = detail.clone();
|
||||
let overrides = top_song_overrides.clone();
|
||||
let version = overrides_version.clone();
|
||||
let name = song.name.clone();
|
||||
let mbid = song.mbid.clone();
|
||||
let artist = artist_name.clone();
|
||||
Callback::from(move |_: MouseEvent| {
|
||||
let detail = detail.clone();
|
||||
// Immediately mark as pending
|
||||
overrides.borrow_mut().insert(i, Some("pending".to_string()));
|
||||
version.set(*version + 1);
|
||||
|
||||
let overrides = overrides.clone();
|
||||
let version = version.clone();
|
||||
let name = name.clone();
|
||||
let mbid = mbid.clone();
|
||||
let artist = artist.clone();
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
if let Ok(resp) = api::watch_track(Some(&artist), &name, mbid.as_deref().unwrap_or("")).await {
|
||||
if let Some(ref d) = *detail {
|
||||
let mut updated = d.clone();
|
||||
if let Some(s) = updated.top_songs.get_mut(i) {
|
||||
s.status = Some(resp.status);
|
||||
}
|
||||
detail.set(Some(updated));
|
||||
}
|
||||
}
|
||||
let status = match api::watch_track(Some(&artist), &name, mbid.as_deref().unwrap_or("")).await {
|
||||
Ok(resp) => resp.status,
|
||||
Err(_) => "wanted".to_string(),
|
||||
};
|
||||
overrides.borrow_mut().insert(i, Some(status));
|
||||
version.set(*version + 1);
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
let on_unwatch = {
|
||||
let detail = detail.clone();
|
||||
let overrides = top_song_overrides.clone();
|
||||
let version = overrides_version.clone();
|
||||
let mbid = song.mbid.clone();
|
||||
Callback::from(move |_: MouseEvent| {
|
||||
let detail = detail.clone();
|
||||
// Immediately mark as pending
|
||||
overrides.borrow_mut().insert(i, Some("pending".to_string()));
|
||||
version.set(*version + 1);
|
||||
|
||||
let overrides = overrides.clone();
|
||||
let version = version.clone();
|
||||
let mbid = mbid.clone();
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
if let Some(ref m) = mbid {
|
||||
if api::unwatch_track(m).await.is_ok() {
|
||||
if let Some(ref d) = *detail {
|
||||
let mut updated = d.clone();
|
||||
if let Some(s) = updated.top_songs.get_mut(i) {
|
||||
s.status = None;
|
||||
}
|
||||
detail.set(Some(updated));
|
||||
}
|
||||
}
|
||||
let _ = api::unwatch_track(m).await;
|
||||
}
|
||||
overrides.borrow_mut().insert(i, None);
|
||||
version.set(*version + 1);
|
||||
});
|
||||
})
|
||||
};
|
||||
@@ -376,12 +396,16 @@ pub fn artist_page(props: &Props) -> Html {
|
||||
<td>{ &song.name }</td>
|
||||
<td class="text-muted text-sm">{ plays }</td>
|
||||
<td>
|
||||
if let Some(ref status) = song.status {
|
||||
<StatusBadge status={status.clone()} />
|
||||
if let Some(ref status) = effective_status {
|
||||
if status != "pending" {
|
||||
<StatusBadge status={status.clone()} />
|
||||
}
|
||||
}
|
||||
</td>
|
||||
<td class="actions">
|
||||
if !has_status {
|
||||
if is_pending {
|
||||
<button class="btn btn-sm" disabled={true}>{ "..." }</button>
|
||||
} else if !has_status {
|
||||
<button class="btn btn-sm" onclick={on_watch}>
|
||||
{ "Watch" }
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user