use cushy::{value::{Destination, Dynamic, IntoDynamic, IntoValue, Source, Value}, widget::{MakeWidget, WidgetList}, widgets::{button::{ButtonBackground, ButtonHoverBackground}, grid::Orientation, Image, Stack}}; use rspotify::model::SimplifiedPlaylist; use cushy::kludgine::Color; use crate::{theme::{LIBRARY_BG, LIBRARY_BG_HOVER, LIBRARY_BG_SELECTED, LIBRARY_BG_SELECTED_HOVER}, widgets::{image::ImageExt, ActivePage, SelectedPage}}; fn playlist_entry(playlist: impl IntoValue, selected_page: SelectedPage) -> impl MakeWidget { let playlist: Value = playlist.into_value(); let id = playlist.map(|p| p.id.clone()); let is_active = selected_page.map_each(move |page| matches!(page, ActivePage::Playlist(p) if p.id == id) ); let (background, background_hover) = get_colors(is_active); Image::new_empty() .with_url( playlist .map_each(|playlist| playlist.images.first().map(|image| image.url.clone())) .into_dynamic() ) .and( playlist .map_each(|p| p.name.clone()) .align_left() .expand() ) .into_columns() .into_button() .on_click(move |_| { selected_page.set(ActivePage::Playlist(playlist.get())); }) .with(&ButtonBackground, background) .with(&ButtonHoverBackground, background_hover) } pub fn playlists_widget(playlists: impl IntoValue>, selected_page: SelectedPage) -> impl MakeWidget { let playlists: Value> = playlists.into_value(); Stack::new( Orientation::Row, playlists .map_each(move |t| { let mut list = t.clone().into_iter().map(|playlist| playlist_entry(playlist, selected_page.clone())).collect::(); list.insert(0, liked_songs_entry(selected_page.clone())); list }) ) .vertical_scroll() .expand() } pub fn liked_songs_entry(selected_page: SelectedPage) -> impl MakeWidget { let is_active = selected_page.map_each(|page| matches!(page, ActivePage::LikedSongs)); let (background, background_hover) = get_colors(is_active); Image::new_empty() .with_url( Dynamic::new(Some("https://misc.scdn.co/liked-songs/liked-songs-300.png".to_string())) ) .and( "Liked Songs" .align_left() .expand() ) .into_columns() .into_button() .on_click(move |_| { selected_page.set(ActivePage::LikedSongs); }) .with(&ButtonBackground, background) .with(&ButtonHoverBackground, background_hover) } /// Returns `background` and `background_hover` colors for a library entry. fn get_colors(is_active: impl IntoValue) -> (Value, Value) { let is_active= is_active.into_value(); let background = is_active.map_each(|active| { if *active { LIBRARY_BG_SELECTED } else { LIBRARY_BG } }); let background_hover = is_active.map_each(|active| { if *active { LIBRARY_BG_SELECTED_HOVER } else { LIBRARY_BG_HOVER } }); (background, background_hover) }