Use audio element event handlers instead of running function repeatedly
This commit is contained in:
parent
d01172a40f
commit
a20c165d96
@ -19,9 +19,6 @@ const MIN_SKIP_BACK_TIME: f64 = 5.0;
|
||||
/// How many seconds to skip forward/backward when the user presses the arrow keys
|
||||
const ARROW_KEY_SKIP_TIME: f64 = 5.0;
|
||||
|
||||
/// How often to update the progress bar and song time
|
||||
const PROGRESS_UPDATE_TIME: Duration = Duration::from_millis(200);
|
||||
|
||||
// TODO Handle errors better, when getting audio HTML element and when playing/pausing audio
|
||||
|
||||
/// Get the current time and duration of the current song, if available
|
||||
@ -386,13 +383,21 @@ pub fn PlayBar(status: RwSignal<PlayStatus>) -> impl IntoView {
|
||||
log!("Queue is empty, no first song to play");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// We need this handle to update certain audio things
|
||||
// This is because the audio element doesn't use Leptos' reactive system,
|
||||
// but rather updates transparently without notifying subscribers
|
||||
// TODO Use Audio's `set_on****` methods instead of this -- if possible
|
||||
let progress_update_handle = set_interval_with_handle(move || {
|
||||
if let Some(audio) = audio_ref.get() {
|
||||
let on_play = move |_| {
|
||||
log!("Audio playing");
|
||||
status.update(|status| status.playing = true);
|
||||
};
|
||||
|
||||
let on_pause = move |_| {
|
||||
log!("Audio paused");
|
||||
status.update(|status| status.playing = false);
|
||||
};
|
||||
|
||||
let on_time_update = move |_| {
|
||||
status.update(|status| {
|
||||
if let Some(audio) = status.get_audio() {
|
||||
set_elapsed_secs(audio.current_time() as i64);
|
||||
set_total_secs(audio.duration() as i64);
|
||||
|
||||
@ -401,10 +406,14 @@ pub fn PlayBar(status: RwSignal<PlayStatus>) -> impl IntoView {
|
||||
} else {
|
||||
set_percentage(0.0);
|
||||
}
|
||||
} else {
|
||||
error!("Unable to update time: Audio element not available");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// If the song has ended, move to the next song
|
||||
if elapsed_secs.get_untracked() >= total_secs.get_untracked() && total_secs.get_untracked() > 0 {
|
||||
log!("Song ended, moving to next song");
|
||||
let on_end = move |_| {
|
||||
log!("Song ended");
|
||||
|
||||
// Move the now-finshed song to the history
|
||||
// TODO Somehow make sure next song starts playing before repeatedly jumping to next
|
||||
@ -424,6 +433,7 @@ pub fn PlayBar(status: RwSignal<PlayStatus>) -> impl IntoView {
|
||||
status.queue.front().map(|song| song.song_path.clone())
|
||||
});
|
||||
|
||||
if let Some(audio) = audio_ref.get() {
|
||||
if let Some(next_src) = next_src {
|
||||
log!("Playing next song: {}", next_src);
|
||||
audio.set_src(&next_src);
|
||||
@ -434,21 +444,14 @@ pub fn PlayBar(status: RwSignal<PlayStatus>) -> impl IntoView {
|
||||
log!("Audio playing after song change");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!("Unable to play next song: Audio element not available");
|
||||
}
|
||||
}
|
||||
}, PROGRESS_UPDATE_TIME);
|
||||
|
||||
match progress_update_handle {
|
||||
Ok(handle) => {
|
||||
log!("Progress update interval started");
|
||||
status.update(|status| status.progress_update_handle = Some(handle));
|
||||
}
|
||||
Err(e) => error!("Error starting progress update interval: {:?}", e),
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
view! {
|
||||
<audio _ref=audio_ref type="audio/mpeg" />
|
||||
<audio _ref=audio_ref on:play=on_play on:pause=on_pause
|
||||
on:timeupdate=on_time_update on:ended=on_end type="audio/mpeg" />
|
||||
<div class="playbar">
|
||||
<ProgressBar percentage=percentage.into() status=status />
|
||||
<MediaInfo status=status />
|
||||
|
@ -1,7 +1,6 @@
|
||||
use leptos::HtmlElement;
|
||||
use leptos::NodeRef;
|
||||
use leptos::html::Audio;
|
||||
use leptos::leptos_dom::helpers::IntervalHandle;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use crate::songdata::SongData;
|
||||
@ -12,8 +11,6 @@ pub struct PlayStatus {
|
||||
pub playing: bool,
|
||||
/// A reference to the HTML audio element
|
||||
pub audio_player: Option<NodeRef<Audio>>,
|
||||
/// A handle to the interval that updates the progress bar
|
||||
pub progress_update_handle: Option<IntervalHandle>,
|
||||
/// A queue of songs that have been played, ordered from oldest to newest
|
||||
pub history: VecDeque<SongData>,
|
||||
/// A queue of songs that have yet to be played, ordered from next up to last
|
||||
@ -57,7 +54,6 @@ impl Default for PlayStatus {
|
||||
Self {
|
||||
playing: false,
|
||||
audio_player: None,
|
||||
progress_update_handle: None,
|
||||
history: VecDeque::new(),
|
||||
queue: VecDeque::new(),
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user