(
#[prop()] song: Song,
#[prop()] is_selected: Box<dyn Fn() -> bool + Send + Sync>,
#[prop()] on_context_menu: impl Fn((MouseEvent, bool)) + 'static + Send + Sync,
#[prop()] on_click:
| 57 | #[tracing::instrument(level = "debug", skip(song, is_selected, on_context_menu, on_click))] |
| 58 | #[component()] |
| 59 | pub fn SongListItem( |
| 60 | #[prop()] song: Song, |
| 61 | #[prop()] is_selected: Box<dyn Fn() -> bool + Send + Sync>, |
| 62 | #[prop()] on_context_menu: impl Fn((MouseEvent, bool)) + 'static + Send + Sync, |
| 63 | #[prop()] on_click: impl Fn(MouseEvent) + 'static + Send + Sync, |
| 64 | #[prop(optional, default = true)] show_background: bool, |
| 65 | #[prop(optional)] custom_duration: Option<String>, |
| 66 | ) -> impl IntoView { |
| 67 | let player_store = use_context::<RwSignal<PlayerStore>>().unwrap(); |
| 68 | let play_now = create_write_slice(player_store, |store, value| store.play_now(value)); |
| 69 | let add_to_queue = |
| 70 | create_write_slice(player_store, |store, song| store.add_to_queue(vec![song])); |
| 71 | let song_cloned = song.clone(); |
| 72 | let song_cloned1 = song.clone(); |
| 73 | |
| 74 | let on_context_menu = Arc::new(Box::new(on_context_menu)); |
| 75 | let on_context_menu_cl = on_context_menu.clone(); |
| 76 | view! { |
| 77 | <div |
| 78 | class="container-fluid w-100 mb-3" |
| 79 | class:wrapper=show_background |
| 80 | class:selectedItem=is_selected |
| 81 | on:click=on_click |
| 82 | on:contextmenu=move |ev| on_context_menu.as_ref()((ev, false)) |
| 83 | > |
| 84 | <div class="row no-gutters align-content-center w-100"> |
| 85 | <LowImg |
| 86 | show_eq=|| false |
| 87 | eq_playing=|| false |
| 88 | cover_img=get_low_img(&song) |
| 89 | play_now=move || play_now.set(song_cloned.clone()) |
| 90 | /> |
| 91 | |
| 92 | <div class="col-8 col-md-5 align-self-center ml-2"> |
| 93 | <div class="row no-gutters align-items-center"> |
| 94 | <div class="col-auto d-flex"> |
| 95 | <div class="title text-truncate mr-2"> |
| 96 | {song.song.title.clone().unwrap_or_default()} |
| 97 | </div> |
| 98 | {move || { |
| 99 | let extension = song.song.provider_extension.clone(); |
| 100 | if let Some(extension) = extension { |
| 101 | view! { <ProviderIcon extension=extension /> }.into_any() |
| 102 | } else { |
| 103 | ().into_any() |
| 104 | } |
| 105 | }} |
| 106 | </div> |
| 107 | </div> |
| 108 | <div class="row no-gutters flex-nowrap"> |
| 109 | <div class="row no-gutters w-100 flex-nowrap text-truncate"> |
| 110 | <ArtistList artists=song.artists /> |
| 111 | </div> |
| 112 | </div> |
| 113 | </div> |
| 114 | |
| 115 | <div class="col-auto offset-1 align-self-center ml-auto timestamp"> |
| 116 | {if let Some(custom_duration) = custom_duration { |
nothing calls this directly
no test coverage detected