mirror of
https://github.com/talwat/lowfi
synced 2025-12-07 23:47:46 +00:00
feat: make loading indicator have optional progress
This commit is contained in:
parent
1f3a751a90
commit
f8b39da92f
@ -2,39 +2,35 @@ use std::{sync::Arc, thread::sleep, time::Duration};
|
||||
|
||||
use rodio::Sink;
|
||||
use tokio::{
|
||||
sync::{broadcast, mpsc},
|
||||
sync::{mpsc, Notify},
|
||||
task::{self, JoinHandle},
|
||||
};
|
||||
|
||||
use crate::ui::{self, Update};
|
||||
|
||||
pub struct Handle {
|
||||
_task: JoinHandle<()>,
|
||||
notify: Arc<Notify>,
|
||||
}
|
||||
|
||||
impl Handle {
|
||||
pub fn new(
|
||||
sink: Arc<Sink>,
|
||||
tx: mpsc::Sender<crate::Message>,
|
||||
rx: broadcast::Receiver<ui::Update>,
|
||||
) -> Self {
|
||||
pub fn new(sink: Arc<Sink>, tx: mpsc::Sender<crate::Message>) -> Self {
|
||||
let notify = Arc::new(Notify::new());
|
||||
|
||||
Self {
|
||||
_task: task::spawn_blocking(|| Self::waiter(sink, tx, rx)),
|
||||
_task: task::spawn(Self::waiter(sink, tx, notify.clone())),
|
||||
notify,
|
||||
}
|
||||
}
|
||||
|
||||
fn waiter(
|
||||
sink: Arc<Sink>,
|
||||
tx: mpsc::Sender<crate::Message>,
|
||||
mut rx: broadcast::Receiver<ui::Update>,
|
||||
) {
|
||||
pub fn notify(&self) {
|
||||
self.notify.notify_one();
|
||||
}
|
||||
|
||||
async fn waiter(sink: Arc<Sink>, tx: mpsc::Sender<crate::Message>, notify: Arc<Notify>) {
|
||||
'main: loop {
|
||||
if !matches!(rx.blocking_recv(), Ok(Update::Track(_))) {
|
||||
continue;
|
||||
}
|
||||
notify.notified().await;
|
||||
|
||||
while !sink.empty() {
|
||||
if matches!(rx.try_recv(), Ok(Update::Quit)) {
|
||||
if Arc::strong_count(¬ify) <= 1 {
|
||||
break 'main;
|
||||
}
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ pub struct Handle {
|
||||
}
|
||||
|
||||
pub enum Output {
|
||||
Loading(Progress),
|
||||
Loading(Option<Progress>),
|
||||
Queued(tracks::Queued),
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ impl Handle {
|
||||
Ok(queued) => Output::Queued(queued),
|
||||
Err(_) => {
|
||||
PROGRESS.store(0, atomic::Ordering::Relaxed);
|
||||
Output::Loading(progress())
|
||||
Output::Loading(Some(progress()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,10 +17,16 @@ use crate::{
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Current {
|
||||
Loading(download::Progress),
|
||||
Loading(Option<download::Progress>),
|
||||
Track(tracks::Info),
|
||||
}
|
||||
|
||||
impl Default for Current {
|
||||
fn default() -> Self {
|
||||
Current::Loading(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl Current {
|
||||
pub fn loading(&self) -> bool {
|
||||
return matches!(self, Current::Loading(_));
|
||||
@ -35,15 +41,14 @@ pub struct Player {
|
||||
broadcast: broadcast::Sender<ui::Update>,
|
||||
current: Current,
|
||||
ui: ui::Handle,
|
||||
waiter: waiter::Handle,
|
||||
_tx: Sender<crate::Message>,
|
||||
_waiter: waiter::Handle,
|
||||
_stream: rodio::OutputStream,
|
||||
}
|
||||
|
||||
impl Drop for Player {
|
||||
fn drop(&mut self) {
|
||||
self.sink.stop();
|
||||
self.broadcast.send(ui::Update::Quit).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +87,7 @@ impl Player {
|
||||
let (tx, rx) = mpsc::channel(8);
|
||||
tx.send(Message::Init).await?;
|
||||
let (utx, urx) = broadcast::channel(8);
|
||||
let current = Current::Loading(download::progress());
|
||||
let current = Current::Loading(None);
|
||||
|
||||
let list = List::load(args.track_list.as_ref()).await?;
|
||||
let state = ui::State::initial(sink.clone(), &args, current.clone(), list.name.clone());
|
||||
@ -92,8 +97,8 @@ impl Player {
|
||||
|
||||
Ok(Self {
|
||||
downloader: Downloader::init(args.buffer_size, list, tx.clone()).await,
|
||||
ui: ui::Handle::init(tx.clone(), urx.resubscribe(), state.clone(), &args).await?,
|
||||
_waiter: waiter::Handle::new(sink.clone(), tx.clone(), urx),
|
||||
ui: ui::Handle::init(tx.clone(), urx, state, &args).await?,
|
||||
waiter: waiter::Handle::new(sink.clone(), tx.clone()),
|
||||
bookmarks: Bookmarks::load().await?,
|
||||
current,
|
||||
broadcast: utx,
|
||||
@ -115,6 +120,7 @@ impl Player {
|
||||
let decoded = queued.decode()?;
|
||||
self.sink.append(decoded.data);
|
||||
self.set_current(Current::Track(decoded.info)).await?;
|
||||
self.waiter.notify();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ enum ActionBar {
|
||||
Playing(tracks::Info),
|
||||
|
||||
/// When the app is loading.
|
||||
Loading(u8),
|
||||
Loading(Option<u8>),
|
||||
|
||||
/// When the app is muted.
|
||||
Muted,
|
||||
@ -80,9 +80,9 @@ impl ActionBar {
|
||||
Self::Playing(x) => ("playing", Some((x.display.clone(), x.width))),
|
||||
Self::Paused(x) => ("paused", Some((x.display.clone(), x.width))),
|
||||
Self::Loading(progress) => {
|
||||
let progress = format!("{: <2.0}%", progress.min(&99));
|
||||
let progress = progress.map(|progress| (format!("{: <2.0}%", progress.min(99)), 3));
|
||||
|
||||
("loading", Some((progress, 3)))
|
||||
("loading", progress)
|
||||
}
|
||||
Self::Muted => {
|
||||
let msg = "+ to increase volume";
|
||||
@ -108,7 +108,7 @@ impl ActionBar {
|
||||
pub fn action(state: &ui::State, width: usize) -> String {
|
||||
let action = match state.current.clone() {
|
||||
Current::Loading(progress) => {
|
||||
ActionBar::Loading(progress.load(std::sync::atomic::Ordering::Relaxed))
|
||||
ActionBar::Loading(progress.map(|x| x.load(std::sync::atomic::Ordering::Relaxed)))
|
||||
}
|
||||
Current::Track(info) => {
|
||||
if state.sink.volume() < 0.01 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user