Use GlobalState instead of passing play_status/logged_in_user everywhere

This commit is contained in:
Ethan Girouard 2024-11-15 18:49:19 -05:00
parent d42737f856
commit f0f34d4abe
Signed by: eta357
GPG Key ID: 7BCDC36DFD11C146
6 changed files with 85 additions and 89 deletions

View File

@ -1,40 +1,23 @@
use crate::playbar::PlayBar; use crate::playbar::PlayBar;
use crate::playbar::CustomTitle; use crate::playbar::CustomTitle;
use crate::playstatus::PlayStatus;
use crate::queue::Queue; use crate::queue::Queue;
use leptos::*; use leptos::*;
use leptos::logging::*;
use leptos_meta::*; use leptos_meta::*;
use leptos_router::*; use leptos_router::*;
use crate::pages::login::*; use crate::pages::login::*;
use crate::pages::signup::*; use crate::pages::signup::*;
use crate::pages::profile::*; use crate::pages::profile::*;
use crate::error_template::{AppError, ErrorTemplate}; use crate::error_template::{AppError, ErrorTemplate};
use crate::auth::get_logged_in_user; use crate::util::state::GlobalState;
use crate::models::User;
pub type LoggedInUserResource = Resource<(), Option<User>>;
#[component] #[component]
pub fn App() -> impl IntoView { pub fn App() -> impl IntoView {
// Provides context that manages stylesheets, titles, meta tags, etc. // Provides context that manages stylesheets, titles, meta tags, etc.
provide_meta_context(); provide_meta_context();
let play_status = PlayStatus::default(); provide_context(GlobalState::new());
let play_status = create_rw_signal(play_status);
let upload_open = create_rw_signal(false);
// A resource that fetches the logged in user let upload_open = create_rw_signal(false);
// This will not automatically refetch, so any login/logout related code
// should call `refetch` on this resource
let logged_in_user: LoggedInUserResource = create_resource(|| (), |_| async {
get_logged_in_user().await
.inspect_err(|e| {
error!("Error getting logged in user: {:?}", e);
})
.ok()
.flatten()
});
view! { view! {
// injects a stylesheet into the document <head> // injects a stylesheet into the document <head>
@ -42,7 +25,7 @@ pub fn App() -> impl IntoView {
<Stylesheet id="leptos" href="/pkg/libretunes.css"/> <Stylesheet id="leptos" href="/pkg/libretunes.css"/>
// sets the document title // sets the document title
<CustomTitle play_status=play_status/> <CustomTitle />
// content for this welcome page // content for this welcome page
<Router fallback=|| { <Router fallback=|| {
@ -55,15 +38,15 @@ pub fn App() -> impl IntoView {
}> }>
<main> <main>
<Routes> <Routes>
<Route path="" view=move || view! { <HomePage play_status=play_status upload_open=upload_open/> }> <Route path="" view=move || view! { <HomePage upload_open=upload_open/> }>
<Route path="" view=Dashboard /> <Route path="" view=Dashboard />
<Route path="dashboard" view=Dashboard /> <Route path="dashboard" view=Dashboard />
<Route path="search" view=Search /> <Route path="search" view=Search />
<Route path="user/:id" view=move || view!{ <Profile logged_in_user /> } /> <Route path="user/:id" view=Profile />
<Route path="user" view=move || view!{ <Profile logged_in_user /> } /> <Route path="user" view=Profile />
</Route> </Route>
<Route path="/login" view=move || view!{ <Login user=logged_in_user /> } /> <Route path="/login" view=Login />
<Route path="/signup" view=move || view!{ <Signup user=logged_in_user /> } /> <Route path="/signup" view=Signup />
</Routes> </Routes>
</main> </main>
</Router> </Router>
@ -78,7 +61,7 @@ use crate::components::upload::*;
/// Renders the home page of your application. /// Renders the home page of your application.
#[component] #[component]
fn HomePage(play_status: RwSignal<PlayStatus>, upload_open: RwSignal<bool>) -> impl IntoView { fn HomePage(upload_open: RwSignal<bool>) -> impl IntoView {
view! { view! {
<div class="home-container"> <div class="home-container">
<Upload open=upload_open/> <Upload open=upload_open/>
@ -86,8 +69,8 @@ fn HomePage(play_status: RwSignal<PlayStatus>, upload_open: RwSignal<bool>) -> i
// This <Outlet /> will render the child route components // This <Outlet /> will render the child route components
<Outlet /> <Outlet />
<Personal /> <Personal />
<PlayBar status=play_status/> <PlayBar />
<Queue status=play_status/> <Queue />
</div> </div>
} }
} }

View File

@ -1,12 +1,12 @@
use crate::auth::login; use crate::auth::login;
use crate::util::state::GlobalState;
use leptos::leptos_dom::*; use leptos::leptos_dom::*;
use leptos::*; use leptos::*;
use leptos_icons::*; use leptos_icons::*;
use crate::users::UserCredentials; use crate::users::UserCredentials;
use crate::app::LoggedInUserResource;
#[component] #[component]
pub fn Login(user: LoggedInUserResource) -> impl IntoView { pub fn Login() -> impl IntoView {
let (username_or_email, set_username_or_email) = create_signal("".to_string()); let (username_or_email, set_username_or_email) = create_signal("".to_string());
let (password, set_password) = create_signal("".to_string()); let (password, set_password) = create_signal("".to_string());
@ -29,6 +29,8 @@ pub fn Login(user: LoggedInUserResource) -> impl IntoView {
password: password1 password: password1
}; };
let user = GlobalState::logged_in_user();
let login_result = login(user_credentials).await; let login_result = login(user_credentials).await;
if let Err(err) = login_result { if let Err(err) = login_result {
// Handle the error here, e.g., log it or display to the user // Handle the error here, e.g., log it or display to the user

View File

@ -11,9 +11,9 @@ use crate::components::error::*;
use crate::api::profile::*; use crate::api::profile::*;
use crate::app::LoggedInUserResource;
use crate::models::User; use crate::models::User;
use crate::users::get_user_by_id; use crate::users::get_user_by_id;
use crate::util::state::GlobalState;
/// Duration in seconds backwards from now to aggregate history data for /// Duration in seconds backwards from now to aggregate history data for
const HISTORY_SECS: i64 = 60 * 60 * 24 * 30; const HISTORY_SECS: i64 = 60 * 60 * 24 * 30;
@ -29,7 +29,7 @@ const TOP_ARTISTS_COUNT: i64 = 10;
/// Profile page /// Profile page
/// Shows the current user's profile if no id is specified, or a user's profile if an id is specified in the path /// Shows the current user's profile if no id is specified, or a user's profile if an id is specified in the path
#[component] #[component]
pub fn Profile(logged_in_user: LoggedInUserResource) -> impl IntoView { pub fn Profile() -> impl IntoView {
let params = use_params_map(); let params = use_params_map();
view! { view! {
@ -38,7 +38,7 @@ pub fn Profile(logged_in_user: LoggedInUserResource) -> impl IntoView {
match params.get("id").map(|id| id.parse::<i32>()) { match params.get("id").map(|id| id.parse::<i32>()) {
None => { None => {
// No id specified, show the current user's profile // No id specified, show the current user's profile
view! { <OwnProfile logged_in_user /> }.into_view() view! { <OwnProfile /> }.into_view()
}, },
Some(Ok(id)) => { Some(Ok(id)) => {
// Id specified, get the user and show their profile // Id specified, get the user and show their profile
@ -61,12 +61,12 @@ pub fn Profile(logged_in_user: LoggedInUserResource) -> impl IntoView {
/// Show the logged in user's profile /// Show the logged in user's profile
#[component] #[component]
fn OwnProfile(logged_in_user: LoggedInUserResource) -> impl IntoView { fn OwnProfile() -> impl IntoView {
view! { view! {
<Transition <Transition
fallback=move || view! { <LoadingPage /> } fallback=move || view! { <LoadingPage /> }
> >
{move || logged_in_user.get().map(|user| { {move || GlobalState::logged_in_user().get().map(|user| {
match user { match user {
Some(user) => { Some(user) => {
let user_id = user.id.unwrap(); let user_id = user.id.unwrap();

View File

@ -1,12 +1,12 @@
use crate::auth::signup; use crate::auth::signup;
use crate::models::User; use crate::models::User;
use crate::util::state::GlobalState;
use leptos::leptos_dom::*; use leptos::leptos_dom::*;
use leptos::*; use leptos::*;
use leptos_icons::*; use leptos_icons::*;
use crate::app::LoggedInUserResource;
#[component] #[component]
pub fn Signup(user: LoggedInUserResource) -> impl IntoView { pub fn Signup() -> impl IntoView {
let (username, set_username) = create_signal("".to_string()); let (username, set_username) = create_signal("".to_string());
let (email, set_email) = create_signal("".to_string()); let (email, set_email) = create_signal("".to_string());
let (password, set_password) = create_signal("".to_string()); let (password, set_password) = create_signal("".to_string());
@ -30,6 +30,8 @@ pub fn Signup(user: LoggedInUserResource) -> impl IntoView {
}; };
log!("new user: {:?}", new_user); log!("new user: {:?}", new_user);
let user = GlobalState::logged_in_user();
spawn_local(async move { spawn_local(async move {
if let Err(err) = signup(new_user.clone()).await { if let Err(err) = signup(new_user.clone()).await {
// Handle the error here, e.g., log it or display to the user // Handle the error here, e.g., log it or display to the user

View File

@ -1,7 +1,7 @@
use crate::models::Artist; use crate::models::Artist;
use crate::playstatus::PlayStatus;
use crate::songdata::SongData; use crate::songdata::SongData;
use crate::api::songs; use crate::api::songs;
use crate::util::state::GlobalState;
use leptos::ev::MouseEvent; use leptos::ev::MouseEvent;
use leptos::html::{Audio, Div}; use leptos::html::{Audio, Div};
use leptos::leptos_dom::*; use leptos::leptos_dom::*;
@ -40,8 +40,8 @@ const HISTORY_LISTEN_THRESHOLD: u64 = MIN_SKIP_BACK_TIME as u64;
/// * `None` if the audio element is not available /// * `None` if the audio element is not available
/// * `Some((current_time, duration))` if the audio element is available /// * `Some((current_time, duration))` if the audio element is available
/// ///
pub fn get_song_time_duration(status: impl SignalWithUntracked<Value = PlayStatus>) -> Option<(f64, f64)> { pub fn get_song_time_duration() -> Option<(f64, f64)> {
status.with_untracked(|status| { GlobalState::play_status().with_untracked(|status| {
if let Some(audio) = status.get_audio() { if let Some(audio) = status.get_audio() {
Some((audio.current_time(), audio.duration())) Some((audio.current_time(), audio.duration()))
} else { } else {
@ -61,13 +61,13 @@ pub fn get_song_time_duration(status: impl SignalWithUntracked<Value = PlayStatu
/// * `status` - The `PlayStatus` to get the audio element from, as a signal /// * `status` - The `PlayStatus` to get the audio element from, as a signal
/// * `time` - The time to skip to, in seconds /// * `time` - The time to skip to, in seconds
/// ///
pub fn skip_to(status: impl SignalUpdate<Value = PlayStatus>, time: f64) { pub fn skip_to(time: f64) {
if time.is_infinite() || time.is_nan() { if time.is_infinite() || time.is_nan() {
error!("Unable to skip to non-finite time: {}", time); error!("Unable to skip to non-finite time: {}", time);
return return
} }
status.update(|status| { GlobalState::play_status().update(|status| {
if let Some(audio) = status.get_audio() { if let Some(audio) = status.get_audio() {
audio.set_current_time(time); audio.set_current_time(time);
log!("Player skipped to time: {}", time); log!("Player skipped to time: {}", time);
@ -85,8 +85,8 @@ pub fn skip_to(status: impl SignalUpdate<Value = PlayStatus>, time: f64) {
/// * `status` - The `PlayStatus` to get the audio element from, as a signal /// * `status` - The `PlayStatus` to get the audio element from, as a signal
/// * `play` - `true` to play the song, `false` to pause it /// * `play` - `true` to play the song, `false` to pause it
/// ///
pub fn set_playing(status: impl SignalUpdate<Value = PlayStatus>, play: bool) { pub fn set_playing(play: bool) {
status.update(|status| { GlobalState::play_status().update(|status| {
if let Some(audio) = status.get_audio() { if let Some(audio) = status.get_audio() {
if play { if play {
if let Err(e) = audio.play() { if let Err(e) = audio.play() {
@ -109,8 +109,8 @@ pub fn set_playing(status: impl SignalUpdate<Value = PlayStatus>, play: bool) {
}); });
} }
fn toggle_queue(status: impl SignalUpdate<Value = PlayStatus>) { fn toggle_queue() {
status.update(|status| { GlobalState::play_status().update(|status| {
status.queue_open = !status.queue_open; status.queue_open = !status.queue_open;
}); });
@ -126,8 +126,8 @@ fn toggle_queue(status: impl SignalUpdate<Value = PlayStatus>) {
/// * `status` - The `PlayStatus` to get the audio element from, as a signal /// * `status` - The `PlayStatus` to get the audio element from, as a signal
/// * `src` - The source to set the audio player to /// * `src` - The source to set the audio player to
/// ///
fn set_play_src(status: impl SignalUpdate<Value = PlayStatus>, src: String) { fn set_play_src(src: String) {
status.update(|status| { GlobalState::play_status().update(|status| {
if let Some(audio) = status.get_audio() { if let Some(audio) = status.get_audio() {
audio.set_src(&src); audio.set_src(&src);
log!("Player set src to: {}", src); log!("Player set src to: {}", src);
@ -139,11 +139,13 @@ fn set_play_src(status: impl SignalUpdate<Value = PlayStatus>, src: String) {
/// The play, pause, and skip buttons /// The play, pause, and skip buttons
#[component] #[component]
fn PlayControls(status: RwSignal<PlayStatus>) -> impl IntoView { fn PlayControls() -> impl IntoView {
let status = GlobalState::play_status();
// On click handlers for the skip and play/pause buttons // On click handlers for the skip and play/pause buttons
let skip_back = move |_| { let skip_back = move |_| {
if let Some(duration) = get_song_time_duration(status) { if let Some(duration) = get_song_time_duration() {
// Skip to previous song if the current song is near the start // Skip to previous song if the current song is near the start
// Also skip to the previous song if we're at the end of the current song // Also skip to the previous song if we're at the end of the current song
// This is because after running out of songs in the queue, the current song will be at the end // This is because after running out of songs in the queue, the current song will be at the end
@ -160,8 +162,8 @@ fn PlayControls(status: RwSignal<PlayStatus>) -> impl IntoView {
// Push the popped song to the front of the queue, and play it // Push the popped song to the front of the queue, and play it
let next_src = last_played_song.song_path.clone(); let next_src = last_played_song.song_path.clone();
status.update(|status| status.queue.push_front(last_played_song)); status.update(|status| status.queue.push_front(last_played_song));
set_play_src(status, next_src); set_play_src(next_src);
set_playing(status, true); set_playing(true);
} else { } else {
warn!("Unable to skip back: No previous song"); warn!("Unable to skip back: No previous song");
} }
@ -170,14 +172,14 @@ fn PlayControls(status: RwSignal<PlayStatus>) -> impl IntoView {
// Default to skipping to start of current song, and playing // Default to skipping to start of current song, and playing
log!("Skipping to start of current song"); log!("Skipping to start of current song");
skip_to(status, 0.0); skip_to(0.0);
set_playing(status, true); set_playing(true);
}; };
let skip_forward = move |_| { let skip_forward = move |_| {
if let Some(duration) = get_song_time_duration(status) { if let Some(duration) = get_song_time_duration() {
skip_to(status, duration.1); skip_to(duration.1);
set_playing(status, true); set_playing(true);
} else { } else {
error!("Unable to skip forward: Unable to get current duration"); error!("Unable to skip forward: Unable to get current duration");
} }
@ -185,7 +187,7 @@ fn PlayControls(status: RwSignal<PlayStatus>) -> impl IntoView {
let toggle_play = move |_| { let toggle_play = move |_| {
let playing = status.with_untracked(|status| { status.playing }); let playing = status.with_untracked(|status| { status.playing });
set_playing(status, !playing); set_playing(!playing);
}; };
// We use this to prevent the buttons from being focused when clicked // We use this to prevent the buttons from being focused when clicked
@ -248,7 +250,9 @@ fn PlayDuration(elapsed_secs: MaybeSignal<i64>, total_secs: MaybeSignal<i64>) ->
/// The name, artist, and album of the current song /// The name, artist, and album of the current song
#[component] #[component]
fn MediaInfo(status: RwSignal<PlayStatus>) -> impl IntoView { fn MediaInfo() -> impl IntoView {
let status = GlobalState::play_status();
let name = Signal::derive(move || { let name = Signal::derive(move || {
status.with(|status| { status.with(|status| {
status.queue.front().map_or("No media playing".into(), |song| song.title.clone()) status.queue.front().map_or("No media playing".into(), |song| song.title.clone())
@ -287,7 +291,9 @@ fn MediaInfo(status: RwSignal<PlayStatus>) -> impl IntoView {
/// The like and dislike buttons /// The like and dislike buttons
#[component] #[component]
fn LikeDislike(status: RwSignal<PlayStatus>) -> impl IntoView { fn LikeDislike() -> impl IntoView {
let status = GlobalState::play_status();
let like_icon = Signal::derive(move || { let like_icon = Signal::derive(move || {
status.with(|status| { status.with(|status| {
match status.queue.front() { match status.queue.front() {
@ -400,7 +406,7 @@ fn LikeDislike(status: RwSignal<PlayStatus>) -> impl IntoView {
/// The play progress bar, and click handler for skipping to a certain time in the song /// The play progress bar, and click handler for skipping to a certain time in the song
#[component] #[component]
fn ProgressBar(percentage: MaybeSignal<f64>, status: RwSignal<PlayStatus>) -> impl IntoView { fn ProgressBar(percentage: MaybeSignal<f64>) -> impl IntoView {
// Keep a reference to the progress bar div so we can get its width and calculate the time to skip to // Keep a reference to the progress bar div so we can get its width and calculate the time to skip to
let progress_bar_ref = create_node_ref::<Div>(); let progress_bar_ref = create_node_ref::<Div>();
@ -412,10 +418,10 @@ fn ProgressBar(percentage: MaybeSignal<f64>, status: RwSignal<PlayStatus>) -> im
let width = progress_bar.offset_width() as f64; let width = progress_bar.offset_width() as f64;
let percentage = x_click_pos / width * 100.0; let percentage = x_click_pos / width * 100.0;
if let Some(duration) = get_song_time_duration(status) { if let Some(duration) = get_song_time_duration() {
let time = duration.1 * percentage / 100.0; let time = duration.1 * percentage / 100.0;
skip_to(status, time); skip_to(time);
set_playing(status, true); set_playing(true);
} else { } else {
error!("Unable to skip to time: Unable to get current duration"); error!("Unable to skip to time: Unable to get current duration");
} }
@ -438,11 +444,11 @@ fn ProgressBar(percentage: MaybeSignal<f64>, status: RwSignal<PlayStatus>) -> im
} }
#[component] #[component]
fn QueueToggle(status: RwSignal<PlayStatus>) -> impl IntoView { fn QueueToggle() -> impl IntoView {
let update_queue = move |_| { let update_queue = move |_| {
toggle_queue(status); toggle_queue();
log!("queue button pressed, queue status: {:?}", status.with_untracked(|status| status.queue_open)); log!("queue button pressed, queue status: {:?}",
GlobalState::play_status().with_untracked(|status| status.queue_open));
}; };
// We use this to prevent the buttons from being focused when clicked // We use this to prevent the buttons from being focused when clicked
@ -463,9 +469,9 @@ fn QueueToggle(status: RwSignal<PlayStatus>) -> impl IntoView {
/// Renders the title of the page based on the currently playing song /// Renders the title of the page based on the currently playing song
#[component] #[component]
pub fn CustomTitle(play_status: RwSignal<PlayStatus>) -> impl IntoView { pub fn CustomTitle() -> impl IntoView {
let title = create_memo(move |_| { let title = create_memo(move |_| {
play_status.with(|play_status| { GlobalState::play_status().with(|play_status| {
play_status.queue.front().map_or("LibreTunes".to_string(), |song_data| { play_status.queue.front().map_or("LibreTunes".to_string(), |song_data| {
format!("{} - {} | {}",song_data.title.clone(),Artist::display_list(&song_data.artists), "LibreTunes") format!("{} - {} | {}",song_data.title.clone(),Artist::display_list(&song_data.artists), "LibreTunes")
}) })
@ -478,18 +484,20 @@ pub fn CustomTitle(play_status: RwSignal<PlayStatus>) -> impl IntoView {
/// The main play bar component, containing the progress bar, media info, play controls, and play duration /// The main play bar component, containing the progress bar, media info, play controls, and play duration
#[component] #[component]
pub fn PlayBar(status: RwSignal<PlayStatus>) -> impl IntoView { pub fn PlayBar() -> impl IntoView {
let status = GlobalState::play_status();
// Listen for key down events -- arrow keys don't seem to trigger key press events // Listen for key down events -- arrow keys don't seem to trigger key press events
let _arrow_key_handle = window_event_listener(ev::keydown, move |e: ev::KeyboardEvent| { let _arrow_key_handle = window_event_listener(ev::keydown, move |e: ev::KeyboardEvent| {
if e.key() == "ArrowRight" { if e.key() == "ArrowRight" {
e.prevent_default(); e.prevent_default();
log!("Right arrow key pressed, skipping forward by {} seconds", ARROW_KEY_SKIP_TIME); log!("Right arrow key pressed, skipping forward by {} seconds", ARROW_KEY_SKIP_TIME);
if let Some(duration) = get_song_time_duration(status) { if let Some(duration) = get_song_time_duration() {
let mut time = duration.0 + ARROW_KEY_SKIP_TIME; let mut time = duration.0 + ARROW_KEY_SKIP_TIME;
time = time.clamp(0.0, duration.1); time = time.clamp(0.0, duration.1);
skip_to(status, time); skip_to(time);
set_playing(status, true); set_playing(true);
} else { } else {
error!("Unable to skip forward: Unable to get current duration"); error!("Unable to skip forward: Unable to get current duration");
} }
@ -498,11 +506,11 @@ pub fn PlayBar(status: RwSignal<PlayStatus>) -> impl IntoView {
e.prevent_default(); e.prevent_default();
log!("Left arrow key pressed, skipping backward by {} seconds", ARROW_KEY_SKIP_TIME); log!("Left arrow key pressed, skipping backward by {} seconds", ARROW_KEY_SKIP_TIME);
if let Some(duration) = get_song_time_duration(status) { if let Some(duration) = get_song_time_duration() {
let mut time = duration.0 - ARROW_KEY_SKIP_TIME; let mut time = duration.0 - ARROW_KEY_SKIP_TIME;
time = time.clamp(0.0, duration.1); time = time.clamp(0.0, duration.1);
skip_to(status, time); skip_to(time);
set_playing(status, true); set_playing(true);
} else { } else {
error!("Unable to skip backward: Unable to get current duration"); error!("Unable to skip backward: Unable to get current duration");
} }
@ -516,7 +524,7 @@ pub fn PlayBar(status: RwSignal<PlayStatus>) -> impl IntoView {
log!("Space bar pressed, toggling play/pause"); log!("Space bar pressed, toggling play/pause");
let playing = status.with_untracked(|status| status.playing); let playing = status.with_untracked(|status| status.playing);
set_playing(status, !playing); set_playing(!playing);
} }
}); });
@ -659,14 +667,14 @@ pub fn PlayBar(status: RwSignal<PlayStatus>) -> impl IntoView {
<audio _ref=audio_ref on:play=on_play on:pause=on_pause <audio _ref=audio_ref on:play=on_play on:pause=on_pause
on:timeupdate=on_time_update on:ended=on_end type="audio/mpeg" /> on:timeupdate=on_time_update on:ended=on_end type="audio/mpeg" />
<div class="playbar"> <div class="playbar">
<ProgressBar percentage=percentage.into() status=status /> <ProgressBar percentage=percentage.into() />
<div class="playbar-left-group"> <div class="playbar-left-group">
<MediaInfo status=status /> <MediaInfo />
<LikeDislike status=status /> <LikeDislike />
</div> </div>
<PlayControls status=status /> <PlayControls />
<PlayDuration elapsed_secs=elapsed_secs.into() total_secs=total_secs.into() /> <PlayDuration elapsed_secs=elapsed_secs.into() total_secs=total_secs.into() />
<QueueToggle status=status /> <QueueToggle />
</div> </div>
} }
} }

View File

@ -1,6 +1,6 @@
use crate::models::Artist; use crate::models::Artist;
use crate::playstatus::PlayStatus;
use crate::song::Song; use crate::song::Song;
use crate::util::state::GlobalState;
use leptos::ev::MouseEvent; use leptos::ev::MouseEvent;
use leptos::leptos_dom::*; use leptos::leptos_dom::*;
use leptos::*; use leptos::*;
@ -9,22 +9,23 @@ use leptos::ev::DragEvent;
const RM_BTN_SIZE: &str = "2.5rem"; const RM_BTN_SIZE: &str = "2.5rem";
fn remove_song_fn(index: usize, status: RwSignal<PlayStatus>) { fn remove_song_fn(index: usize) {
if index == 0 { if index == 0 {
log!("Error: Trying to remove currently playing song (index 0) from queue"); log!("Error: Trying to remove currently playing song (index 0) from queue");
} else { } else {
log!("Remove Song from Queue: Song is not currently playing, deleting song from queue and not adding to history"); log!("Remove Song from Queue: Song is not currently playing, deleting song from queue and not adding to history");
status.update(|status| { GlobalState::play_status().update(|status| {
status.queue.remove(index); status.queue.remove(index);
}); });
} }
} }
#[component] #[component]
pub fn Queue(status: RwSignal<PlayStatus>) -> impl IntoView { pub fn Queue() -> impl IntoView {
let status = GlobalState::play_status();
let remove_song = move |index: usize| { let remove_song = move |index: usize| {
remove_song_fn(index, status); remove_song_fn(index);
log!("Removed song {}", index + 1); log!("Removed song {}", index + 1);
}; };