From 7cdd2e7694dfe903bd28e8232fec96c72a2a5f54 Mon Sep 17 00:00:00 2001 From: talwat <83217276+talwat@users.noreply.github.com> Date: Wed, 23 Apr 2025 14:14:49 +0200 Subject: [PATCH] feat: add star indicator for bookmarking --- src/player.rs | 18 +++++++++++++++++- src/player/ui/components.rs | 17 +++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/player.rs b/src/player.rs index bd70df1..0ebf4ba 100644 --- a/src/player.rs +++ b/src/player.rs @@ -2,7 +2,14 @@ //! This also has the code for the underlying //! audio server which adds new tracks. -use std::{collections::VecDeque, sync::Arc, time::Duration}; +use std::{ + collections::VecDeque, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + time::Duration, +}; use arc_swap::ArcSwapOption; use downloader::Downloader; @@ -48,6 +55,9 @@ pub struct Player { /// [rodio]'s [`Sink`] which can control playback. pub sink: Sink, + /// Whether the current track has been bookmarked. + bookmarked: AtomicBool, + /// The [`TrackInfo`] of the current track. /// This is [`None`] when lowfi is buffering/loading. current: ArcSwapOption, @@ -174,6 +184,7 @@ impl Player { volume, list, _handle: handle, + bookmarked: AtomicBool::new(false), }; Ok((player, SendableOutputStream(stream))) @@ -383,6 +394,11 @@ impl Player { continue; } Messages::Bookmark => { + if player.bookmarked.load(Ordering::Relaxed) { + continue; + } + + player.bookmarked.swap(true, Ordering::Relaxed); let current = player.current.load(); let current = current.as_ref().unwrap(); diff --git a/src/player/ui/components.rs b/src/player/ui/components.rs index aca2f81..aeac244 100644 --- a/src/player/ui/components.rs +++ b/src/player/ui/components.rs @@ -1,7 +1,11 @@ //! Various different individual components that //! appear in lowfi's UI, like the progress bar. -use std::{ops::Deref as _, sync::Arc, time::Duration}; +use std::{ + ops::Deref as _, + sync::{atomic::Ordering, Arc}, + time::Duration, +}; use crossterm::style::Stylize as _; use unicode_segmentation::UnicodeSegmentation as _; @@ -72,7 +76,7 @@ enum ActionBar { impl ActionBar { /// Formats the action bar to be displayed. /// The second value is the character length of the result. - fn format(&self) -> (String, usize) { + fn format(&self, star: bool) -> (String, usize) { let (word, subject) = match self { Self::Playing(x) => ("playing", Some((x.display_name.clone(), x.width))), Self::Paused(x) => ("paused", Some((x.display_name.clone(), x.width))), @@ -81,7 +85,12 @@ impl ActionBar { subject.map_or_else( || (word.to_owned(), word.len()), - |(subject, len)| (format!("{} {}", word, subject.bold()), word.len() + 1 + len), + |(subject, len)| { + ( + format!("{} {}{}", word, if star { "*" } else { "" }, subject.bold()), + word.len() + 1 + len + if star { 1 } else { 0 }, + ) + }, ) } } @@ -99,7 +108,7 @@ pub fn action(player: &Player, current: Option<&Arc>, width: usize) -> Str ActionBar::Playing(info) } }) - .format(); + .format(player.bookmarked.load(Ordering::Relaxed)); if len > width { let chopped: String = main.graphemes(true).take(width + 1).collect();