working liked but slow

This commit is contained in:
Daniel Bulant 2024-11-17 21:44:30 +01:00
parent edcb40559f
commit dc71fefc24
No known key found for this signature in database
2 changed files with 94 additions and 14 deletions

View file

@ -1,4 +1,7 @@
use cushy::figures::units::Lp;
use cushy::figures::Size;
use cushy::kludgine::Color; use cushy::kludgine::Color;
use cushy::styles::{Dimension, DimensionRange};
use cushy::{ use cushy::{
value::{Destination, Dynamic, IntoDynamic, IntoValue, Source, Value}, value::{Destination, Dynamic, IntoDynamic, IntoValue, Source, Value},
widget::{MakeWidget, WidgetList}, widget::{MakeWidget, WidgetList},
@ -53,7 +56,10 @@ pub fn playlists_widget(
}), }),
) )
.vertical_scroll() .vertical_scroll()
.expand_horizontally() .size(Size {
width: Dimension::Lp(Lp::points(200)).into(),
height: DimensionRange::default(),
})
} }
fn liked_songs_entry(selected_page: SelectedPage) -> impl MakeWidget { fn liked_songs_entry(selected_page: SelectedPage) -> impl MakeWidget {
@ -82,7 +88,7 @@ where
let (background, background_hover) = get_colors(is_active); let (background, background_hover) = get_colors(is_active);
Image::new_empty() Image::new_empty()
.with_url(url) .with_url(url)
.and(text.into_value().align_left().expand()) .and(text.into_value().align_left())
.into_columns() .into_columns()
.into_button() .into_button()
.on_click(callback) .on_click(callback)

View file

@ -1,6 +1,5 @@
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
ops::Range,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
@ -8,13 +7,16 @@ use cushy::{
figures::{units::Lp, Size}, figures::{units::Lp, Size},
styles::{Dimension, DimensionRange}, styles::{Dimension, DimensionRange},
value::{Destination, Dynamic, Source}, value::{Destination, Dynamic, Source},
widget::MakeWidget, widget::{MakeWidget, WidgetInstance},
widgets::VirtualList, widgets::{label::LabelOverflow, Image, Label, Space, VirtualList},
}; };
use futures_util::lock::Mutex; use itertools::Itertools;
use rspotify::model::SavedTrack; use rspotify::model::SavedTrack;
use std::sync::Mutex;
use crate::{api::SpotifyContextRef, nodebug::NoDebug, rt::tokio_runtime}; use crate::{
api::SpotifyContextRef, nodebug::NoDebug, rt::tokio_runtime, widgets::image::ImageExt,
};
const PER_PAGE: usize = 50; const PER_PAGE: usize = 50;
@ -23,10 +25,27 @@ pub struct LikedSongsPage {
tracks: Dynamic<HashMap<usize, SavedTrack>>, tracks: Dynamic<HashMap<usize, SavedTrack>>,
total_tracks: Dynamic<usize>, total_tracks: Dynamic<usize>,
track_images: Arc<Mutex<HashMap<usize, WidgetInstance>>>,
context: NoDebug<SpotifyContextRef>, context: NoDebug<SpotifyContextRef>,
pages_loading: Arc<RwLock<HashSet<usize>>>, pages_loading: Arc<RwLock<HashSet<usize>>>,
} }
fn get_or_create_track_image(
track_images: &Arc<Mutex<HashMap<usize, WidgetInstance>>>,
idx: usize,
create: impl FnOnce() -> WidgetInstance,
) -> WidgetInstance {
println!("Getting image");
let mut locked = track_images.lock().unwrap();
if let Some(image) = locked.get(&idx) {
image.clone()
} else {
let image = create();
locked.insert(idx, image.clone());
image
}
}
impl LikedSongsPage { impl LikedSongsPage {
pub fn new(context: SpotifyContextRef) -> Self { pub fn new(context: SpotifyContextRef) -> Self {
Self { Self {
@ -35,6 +54,7 @@ impl LikedSongsPage {
tracks: Default::default(), tracks: Default::default(),
total_tracks: Default::default(), total_tracks: Default::default(),
pages_loading: Default::default(), pages_loading: Default::default(),
track_images: Default::default(),
} }
} }
@ -43,6 +63,14 @@ impl LikedSongsPage {
let pages_loading = self.pages_loading; let pages_loading = self.pages_loading;
let context = self.context; let context = self.context;
let total_tracks = self.total_tracks.clone(); let total_tracks = self.total_tracks.clone();
let track_images = self.track_images;
tracks
.for_each(|tracks| {
println!("Tracks: {}", tracks.len());
})
.persist();
VirtualList::new( VirtualList::new(
total_tracks.clone().map_each(|total| (*total).max(1)), total_tracks.clone().map_each(|total| (*total).max(1)),
move |index| { move |index| {
@ -81,14 +109,60 @@ impl LikedSongsPage {
} }
} }
}); });
tracks let track = tracks.map_each(move |tracks| tracks.get(&index).cloned());
.map_each(move |tracks| { index
if let Some(track) = tracks.get(&index) { .to_string()
format!("{} - {}", track.track.name, track.track.artists[0].name) .and({
} else { get_or_create_track_image(&track_images, index, || {
format!("Loading...") Image::new_empty()
} .with_url(track.map_each(|track| {
track
.as_ref()
.map(|track| track.track.album.images[0].url.clone())
}))
.size(Size::squared(Dimension::Lp(Lp::points(40))))
.make_widget()
}) })
})
.and(track.map_each(|track| {
track
.as_ref()
.map(|track| {
Label::new(track.track.name.clone())
.overflow(LabelOverflow::Clip)
.and(
Label::new(
(track.track.artists)
.iter()
.map(|artist| artist.name.clone())
.join(", "),
)
.overflow(LabelOverflow::Clip),
)
.into_rows()
.make_widget()
})
.unwrap_or(Space::primary().make_widget())
}))
.and(track.map_each(|track| {
track
.as_ref()
.map(|track| track.track.album.name.clone().make_widget())
.unwrap_or(Space::primary().make_widget())
}))
.and(track.map_each(|track| {
track
.as_ref()
.map(|track| track.added_at.to_string().make_widget())
.unwrap_or(Space::primary().make_widget())
}))
.and(track.map_each(|track| {
track
.as_ref()
.map(|track| track.track.duration.to_string().make_widget())
.unwrap_or(Space::primary().make_widget())
}))
.into_columns()
.size(Size { .size(Size {
width: DimensionRange::default(), width: DimensionRange::default(),
height: Dimension::Lp(Lp::points(60)).into(), height: Dimension::Lp(Lp::points(60)).into(),