added the scroll bar
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use wasm_bindgen::JsCast;
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
|
||||
@@ -17,7 +20,7 @@ pub fn library_page() -> Html {
|
||||
let artists = artists.clone();
|
||||
let error = error.clone();
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
match api::list_artists(200, 0).await {
|
||||
match api::list_artists(0, 0).await {
|
||||
Ok(a) => artists.set(Some(a)),
|
||||
Err(e) => error.set(Some(e.0)),
|
||||
}
|
||||
@@ -40,6 +43,33 @@ pub fn library_page() -> Html {
|
||||
return html! { <p class="loading">{ "Loading..." }</p> };
|
||||
};
|
||||
|
||||
// Pre-compute which artist IDs are first in their letter group (for anchor IDs)
|
||||
let mut seen_letters = HashSet::new();
|
||||
let first_of_letter: HashMap<i32, char> = artists
|
||||
.iter()
|
||||
.filter_map(|a| {
|
||||
let first = a.name.chars().next().unwrap_or('#').to_ascii_uppercase();
|
||||
let letter = if first.is_ascii_alphabetic() {
|
||||
first
|
||||
} else {
|
||||
'#'
|
||||
};
|
||||
if seen_letters.insert(letter) {
|
||||
Some((a.id, letter))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let active_letters: HashSet<char> = first_of_letter.values().copied().collect();
|
||||
|
||||
// Build scroll track letter data
|
||||
let letters: Vec<char> = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ".chars().collect();
|
||||
let scroll_track_items: Vec<(String, bool)> = letters
|
||||
.iter()
|
||||
.map(|&c| (c.to_string(), active_letters.contains(&c)))
|
||||
.collect();
|
||||
|
||||
html! {
|
||||
<div>
|
||||
<div class="page-header">
|
||||
@@ -50,6 +80,28 @@ pub fn library_page() -> Html {
|
||||
if artists.is_empty() {
|
||||
<p class="text-muted">{ "No artists in library. Use Search to add some!" }</p>
|
||||
} else {
|
||||
<div class="scroll-track">
|
||||
{ for scroll_track_items.iter().map(|(letter, active)| {
|
||||
let letter_c = letter.clone();
|
||||
let active = *active;
|
||||
let class = if active { "scroll-track-letter has-artists" } else { "scroll-track-letter" };
|
||||
let onclick = Callback::from(move |_: MouseEvent| {
|
||||
if active {
|
||||
if let Some(window) = web_sys::window() {
|
||||
if let Some(doc) = window.document() {
|
||||
if let Some(el) = doc.get_element_by_id(&format!("letter-{}", letter_c)) {
|
||||
let _ = el.dyn_into::<web_sys::HtmlElement>()
|
||||
.map(|el| el.scroll_into_view());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
html! {
|
||||
<div class={class} onclick={onclick}>{ letter }</div>
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -62,6 +114,7 @@ pub fn library_page() -> Html {
|
||||
</thead>
|
||||
<tbody>
|
||||
{ for artists.iter().map(|a| {
|
||||
let anchor_id = first_of_letter.get(&a.id).map(|c| format!("letter-{c}"));
|
||||
let artist_id = a.id;
|
||||
let artist_name = a.name.clone();
|
||||
let artist_mbid = a.musicbrainz_id.clone();
|
||||
@@ -157,7 +210,7 @@ pub fn library_page() -> Html {
|
||||
let watched_bar_style = format!("width:{watched_pct}%;background:{watched_color};");
|
||||
|
||||
html! {
|
||||
<tr>
|
||||
<tr id={anchor_id}>
|
||||
<td>
|
||||
<Link<Route> to={Route::Artist { id: a.id.to_string() }}>
|
||||
{ &a.name }
|
||||
|
||||
@@ -17,7 +17,7 @@ pub fn playlists_page() -> Html {
|
||||
let all_artists = all_artists.clone();
|
||||
use_effect_with((), move |_| {
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
if let Ok(artists) = api::list_artists(500, 0).await {
|
||||
if let Ok(artists) = api::list_artists(0, 0).await {
|
||||
all_artists.set(artists);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user