Skip to content

Commit b526de7

Browse files
committed
feat: implement playlist reverse play and display functionality
1 parent 750e8ac commit b526de7

File tree

7 files changed

+49
-1
lines changed

7 files changed

+49
-1
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Changed
11+
12+
- Playlist `reverse` command with keybinding `Shift+R`
13+
814
## [1.3.0]
915

1016
### Added

doc/users.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ playback depending on your desktop environment settings. Have a look at the
102102
| <kbd>[</kbd> | Decrease volume by 5%. |
103103
| <kbd>]</kbd> | Increase volume by 5%. |
104104
| <kbd>R</kbd> | Toggle _Repeat_ mode. |
105+
| <kbd>Shift</kbd>+<kbd>R</kbd> | Reverse the current playlist order. |
105106
| <kbd>Z</kbd> | Toggle _Shuffle_ state. |
106107

107108
### Context Menus
@@ -179,6 +180,7 @@ Note: \<FOO\> - mandatory arg; [BAR] - optional arg
179180
| `share` \<ITEM\> | Copy a shareable URL of the item to the system clipboard. Requires the `share_clipboard` feature.<br/>\* Valid values for ITEM: `selected`, `current` |
180181
| `newplaylist` \<NAME\> | Create a new playlist. |
181182
| `sort` \<SORT_KEY\> [SORT_DIRECTION] | Sort a playlist.<br/>\* Valid values for SORT_KEY: `title`, `album`, `artist`, `duration`, `added`<br/>\* Valid values for SORT_DIRECTION: `ascending` (default; aliases: `a`, `asc`), `descending` (aliases: `d`, `desc`) |
183+
| `reverse` | Reverse the current playlist order and clear any stored sort preferences for that playlist. |
182184
| `exec` \<CMD\> | Execute a command in the system shell.<br/>\* Command output is printed to the terminal, so redirection (`2> /dev/null`) may be necessary. |
183185
| `noop` | Do nothing. Useful for disabling default keybindings. See [custom keybindings](#custom-keybindings). |
184186
| `reload` | Reload the configuration from disk. See [Configuration](#configuration). |

src/command.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ pub enum Command {
159159
Insert(InsertSource),
160160
NewPlaylist(String),
161161
Sort(SortKey, SortDirection),
162+
Reverse,
162163
Logout,
163164
ShowRecommendations(TargetMode),
164165
Redraw,
@@ -226,6 +227,7 @@ impl fmt::Display for Command {
226227
| Self::Help
227228
| Self::ReloadConfig
228229
| Self::Noop
230+
| Self::Reverse
229231
| Self::Logout
230232
| Self::Reconnect
231233
| Self::Redraw => vec![],
@@ -277,6 +279,7 @@ impl Command {
277279
Self::Insert(_) => "insert",
278280
Self::NewPlaylist(_) => "newplaylist",
279281
Self::Sort(_, _) => "sort",
282+
Self::Reverse => "reverse",
280283
Self::Logout => "logout",
281284
Self::ShowRecommendations(_) => "similar",
282285
Self::Redraw => "redraw",
@@ -767,6 +770,7 @@ pub fn parse(input: &str) -> Result<Vec<Command>, CommandParseError> {
767770
}?;
768771
Command::Sort(key, direction)
769772
}
773+
"reverse" => Command::Reverse,
770774
"logout" => Command::Logout,
771775
"similar" => {
772776
let &target_mode_raw = args.first().ok_or(E::InsufficientArgs {

src/commands.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ impl CommandManager {
316316
| Command::Jump(_)
317317
| Command::Insert(_)
318318
| Command::ShowRecommendations(_)
319-
| Command::Sort(_, _) => Err(format!(
319+
| Command::Sort(_, _)
320+
| Command::Reverse => Err(format!(
320321
"The command \"{}\" is unsupported in this view",
321322
cmd.basename()
322323
)),
@@ -459,6 +460,7 @@ impl CommandManager {
459460
kb.insert("[".into(), vec![Command::VolumeDown(5)]);
460461

461462
kb.insert("r".into(), vec![Command::Repeat(None)]);
463+
kb.insert("Shift+r".into(), vec![Command::Reverse]);
462464
kb.insert("z".into(), vec![Command::Shuffle(None)]);
463465

464466
#[cfg(feature = "share_clipboard")]

src/model/playlist.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ impl Playlist {
100100
}
101101
}
102102

103+
pub fn reverse(&mut self) {
104+
if let Some(tracks) = &mut self.tracks {
105+
tracks.reverse();
106+
}
107+
}
108+
103109
pub fn sort(&mut self, key: &SortKey, direction: &SortDirection) {
104110
fn compare_artists(a: &[String], b: &[String]) -> Ordering {
105111
let sanitize_artists_name = |x: &[String]| -> Vec<String> {

src/queue.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,23 @@ impl Queue {
458458
}
459459
}
460460

461+
/// Reverse the current queue order.
462+
pub fn reverse(&self) {
463+
let mut queue = self.queue.write().unwrap();
464+
queue.reverse();
465+
466+
// If we have a current track, update its index to the new position
467+
let mut current = self.current_track.write().unwrap();
468+
if let Some(index) = *current {
469+
let new_index = queue.len().saturating_sub(1).saturating_sub(index);
470+
*current = Some(new_index);
471+
}
472+
473+
// Clear random order since reversing changes the logical order
474+
let mut random_order = self.random_order.write().unwrap();
475+
*random_order = None;
476+
}
477+
461478
/// Handle events that are specific to the queue.
462479
pub fn handle_event(&self, event: QueueEvent) {
463480
match event {

src/ui/playlist.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,17 @@ impl ViewExt for PlaylistView {
113113
return Ok(CommandResult::Consumed(None));
114114
}
115115

116+
if let Command::Reverse = cmd {
117+
self.playlist.reverse();
118+
let tracks = self.playlist.tracks.as_ref().unwrap_or(&Vec::new()).clone();
119+
self.list = ListView::new(
120+
Arc::new(RwLock::new(tracks)),
121+
self.queue.clone(),
122+
self.library.clone(),
123+
);
124+
return Ok(CommandResult::Consumed(None));
125+
}
126+
116127
self.list.on_command(s, cmd)
117128
}
118129
}

0 commit comments

Comments
 (0)