Skip to content

Commit

Permalink
support moving items in a playlist (#224)
Browse files Browse the repository at this point in the history
add commands to move items up and down in the current playlist 🎵

closes #197
  • Loading branch information
cobbinma authored Jul 30, 2023
1 parent eab0359 commit 0dbb01e
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ List of supported commands:
| `SortTrackByDuration` | sort the track table (if any) by track's duration | `s d` |
| `SortTrackByAddedDate` | sort the track table (if any) by track's added date | `s D` |
| `ReverseOrder` | reverse the order of the track table (if any) | `s r` |
| `MovePlaylistItemUp` | move playlist item up one position | `C-k` |
| `MovePlaylistItemDown` | move playlist item down one position | `C-j` |
To add new shortcuts or modify the default shortcuts, please refer to the [keymaps section](docs/config.md#keymaps) in the configuration documentation.
Expand Down
57 changes: 57 additions & 0 deletions spotify_player/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,23 @@ impl Client {
state.player.write().queue = Some(queue);
}
}
ClientRequest::ReorderPlaylistItems {
playlist_id,
insert_index,
range_start,
range_length,
snapshot_id,
} => {
self.reorder_playlist_items(
state,
playlist_id,
insert_index,
range_start,
range_length,
snapshot_id.as_deref(),
)
.await?;
}
};

tracing::info!(
Expand Down Expand Up @@ -866,6 +883,46 @@ impl Client {
Ok(())
}

/// reorder items in a playlist
pub async fn reorder_playlist_items(
&self,
state: &SharedState,
playlist_id: PlaylistId<'_>,
insert_index: usize,
range_start: usize,
range_length: Option<usize>,
snapshot_id: Option<&str>,
) -> Result<()> {
let insert_before = match insert_index > range_start {
true => insert_index + 1,
false => insert_index,
};

self.spotify
.playlist_reorder_items(
playlist_id.clone(),
Some(range_start as i32),
Some(insert_before as i32),
range_length.map(|range_length| range_length as u32),
snapshot_id,
)
.await?;

// After making a reorder request, update the playlist in-memory data stored inside the app caches.
if let Some(Context::Playlist { tracks, .. }) = state
.data
.write()
.caches
.context
.get_mut(&playlist_id.uri())
{
let track = tracks.remove(range_start);
tracks.insert(insert_index, track);
}

Ok(())
}

/// adds a Spotify item to current user's library.
/// Before adding new item, the function checks if that item already exists in the library
/// to avoid adding a duplicated item.
Expand Down
5 changes: 5 additions & 0 deletions spotify_player/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ pub enum Command {
SortTrackByDuration,
SortTrackByAddedDate,
ReverseTrackOrder,

MovePlaylistItemUp,
MovePlaylistItemDown,
}

#[derive(Debug, Copy, Clone)]
Expand Down Expand Up @@ -199,6 +202,8 @@ impl Command {
Self::SortTrackByDuration => "sort the track table (if any) by track's duration",
Self::SortTrackByAddedDate => "sort the track table (if any) by track's added date",
Self::ReverseTrackOrder => "reverse the order of the track table (if any)",
Self::MovePlaylistItemUp => "move playlist item up one position",
Self::MovePlaylistItemDown => "move playlist item down one position",
}
}
}
8 changes: 8 additions & 0 deletions spotify_player/src/config/keymap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,14 @@ impl Default for KeymapConfig {
key_sequence: "s r".into(),
command: Command::ReverseTrackOrder,
},
Keymap {
key_sequence: "C-k".into(),
command: Command::MovePlaylistItemUp,
},
Keymap {
key_sequence: "C-j".into(),
command: Command::MovePlaylistItemDown,
},
],
}
}
Expand Down
7 changes: 7 additions & 0 deletions spotify_player/src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ pub enum ClientRequest {
AddTrackToQueue(TrackId<'static>),
AddTrackToPlaylist(PlaylistId<'static>, TrackId<'static>),
DeleteTrackFromPlaylist(PlaylistId<'static>, TrackId<'static>),
ReorderPlaylistItems {
playlist_id: PlaylistId<'static>,
insert_index: usize,
range_start: usize,
range_length: Option<usize>,
snapshot_id: Option<String>,
},
AddToLibrary(Item),
DeleteFromLibrary(ItemId),
ConnectDevice(Option<String>),
Expand Down
52 changes: 52 additions & 0 deletions spotify_player/src/event/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,58 @@ pub fn handle_command_for_track_table_window(
Command::AddSelectedItemToQueue => {
client_pub.send(ClientRequest::AddTrackToQueue(tracks[id].id.clone()))?;
}
Command::MovePlaylistItemUp => {
if let PageState::Context {
id: Some(ContextId::Playlist(playlist_id)),
..
} = ui.current_page()
{
if id > 0
&& data.user_data.playlists.iter().any(|playlist| {
&playlist.id == playlist_id
&& Some(&playlist.owner.1)
== data.user_data.user.as_ref().map(|user| &user.id)
})
{
let insert_index = id - 1;
client_pub.send(ClientRequest::ReorderPlaylistItems {
playlist_id: playlist_id.clone_static(),
insert_index,
range_start: id,
range_length: None,
snapshot_id: None,
})?;
ui.current_page_mut().select(insert_index);
};
}
ui.popup = None;
}
Command::MovePlaylistItemDown => {
if let PageState::Context {
id: Some(ContextId::Playlist(playlist_id)),
..
} = ui.current_page()
{
let insert_index = id + 1;
if insert_index < tracks.len()
&& data.user_data.playlists.iter().any(|playlist| {
&playlist.id == playlist_id
&& Some(&playlist.owner.1)
== data.user_data.user.as_ref().map(|user| &user.id)
})
{
client_pub.send(ClientRequest::ReorderPlaylistItems {
playlist_id: playlist_id.clone_static(),
insert_index,
range_start: id,
range_length: None,
snapshot_id: None,
})?;
ui.current_page_mut().select(insert_index);
};
}
ui.popup = None;
}
_ => return Ok(false),
}
Ok(true)
Expand Down

0 comments on commit 0dbb01e

Please sign in to comment.