diff --git a/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/index.scss b/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/index.scss index 69705dc80..b24579716 100644 --- a/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/index.scss +++ b/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/index.scss @@ -132,6 +132,13 @@ height: 4rem; @include animation(active-track 5s infinite); } + + &.move:hover { + background: $move-mode-track-bg !important; + border-top: $move-mode-track-border; + border-bottom: $move-mode-track-border; + cursor: move; + } } } } diff --git a/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/vars.scss b/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/vars.scss index a7f1a0262..2ce8bdb48 100644 --- a/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/vars.scss +++ b/platypush/backend/http/static/css/source/webpanel/plugins/music.mpd/vars.scss @@ -23,3 +23,6 @@ $playlist-controls-border: $default-border-2; $active-track-bg-1: #d4ffe3; $active-track-bg-2: #9cdfb0; +$move-mode-track-border: 3px dotted rgb(216,156,136); +$move-mode-track-bg: rgba(216,156,136,0.3); + diff --git a/platypush/backend/http/static/js/plugins/music.mpd/index.js b/platypush/backend/http/static/js/plugins/music.mpd/index.js index b439b6245..8cce55b8c 100644 --- a/platypush/backend/http/static/js/plugins/music.mpd/index.js +++ b/platypush/backend/http/static/js/plugins/music.mpd/index.js @@ -17,6 +17,11 @@ Vue.component('music-mpd', { browser: false, }, + moveMode: { + playlist: false, + editor: false, + }, + selectedPlaylistItems: {}, selectedBrowserItems: {}, @@ -45,24 +50,29 @@ Vue.component('music-mpd', { }); } - items.push( - { - text: 'Add to playlist', - icon: 'list', - }, - { + items.push({ + text: 'Add to playlist', + icon: 'list', + }); + + if (Object.keys(this.selectedPlaylistItems).length < this.playlist.length) { + items.push({ text: 'Move', icon: 'retweet', - }, - { - text: 'Remove from queue', - icon: 'trash', - click: async function() { - await self.del(); - self.selectedPlaylistItems = {}; + click: function() { + self.moveMode.playlist = true; }, + }); + } + + items.push({ + text: 'Remove from queue', + icon: 'trash', + click: async function() { + await self.del(); + self.selectedPlaylistItems = {}; }, - ); + }); if (Object.keys(this.selectedPlaylistItems).length === 1) { items.push({ @@ -473,10 +483,8 @@ Vue.component('music-mpd', { this._parsePlaylist(playlist); }, - load: async function(item) { - let status = await request('music.mpd.load', {playlist:item}); - this._parseStatus(status); - + load: async function(item, play=false) { + await request('music.mpd.load', {playlist:item, play:play}); let playlist = await request('music.mpd.playlistinfo'); this._parsePlaylist(playlist); }, @@ -511,6 +519,16 @@ Vue.component('music-mpd', { this._parseBrowserItems(items); }, + move: async function(fromPos, toPos, updateChanges=true) { + let status = await request('music.mpd.move', {from_pos: fromPos, to_pos: toPos}); + + if (updateChanges) { + this._parseStatus(status); + const playlist = await request('music.mpd.playlistinfo'); + this._parsePlaylist(playlist); + } + }, + swap: async function() { if (Object.keys(this.selectedPlaylistItems).length !== 2) { return; @@ -693,13 +711,24 @@ Vue.component('music-mpd', { this.browserFilter.toLocaleLowerCase().split(' ').filter(_ => _.length > 0).join(' ')) >= 0; }, - onPlaylistItemClick: function(track) { + onPlaylistItemClick: async function(track) { if (this.selectionMode.playlist) { if (track.pos in this.selectedPlaylistItems) { Vue.delete(this.selectedPlaylistItems, track.pos); } else { Vue.set(this.selectedPlaylistItems, track.pos, track); } + } else if (this.moveMode.playlist) { + var fromPos = Object.values(this.selectedPlaylistItems).map(_ => _.pos); + var toPos = track.pos; + this.moveMode.playlist = false; + + const promises = fromPos.map((pos,i) => this.move(pos, toPos+i, false)); + await Promise.all(promises); + this.selectedPlaylistItems = {}; + + const playlist = await request('music.mpd.playlistinfo'); + this._parsePlaylist(playlist); } else if (track.pos in this.selectedPlaylistItems) { Vue.delete(this.selectedPlaylistItems, track.pos); } else { diff --git a/platypush/backend/http/static/js/plugins/music.mpd/playlist.js b/platypush/backend/http/static/js/plugins/music.mpd/playlist.js index b86263838..463381b46 100644 --- a/platypush/backend/http/static/js/plugins/music.mpd/playlist.js +++ b/platypush/backend/http/static/js/plugins/music.mpd/playlist.js @@ -15,6 +15,11 @@ Vue.component('music-mpd-playlist-item', { type: Boolean, default: false, }, + + move: { + type: Boolean, + default: false, + }, }, }); diff --git a/platypush/backend/http/templates/plugins/music.mpd/index.html b/platypush/backend/http/templates/plugins/music.mpd/index.html index 1c8afd536..36b30fd0c 100644 --- a/platypush/backend/http/templates/plugins/music.mpd/index.html +++ b/platypush/backend/http/templates/plugins/music.mpd/index.html @@ -120,6 +120,7 @@ :track="item" :active="track.file && status.state !== 'stop' && item.file === track.file" :selected="item.pos in selectedPlaylistItems" + :move="moveMode.playlist" :ref="track.file && status.state !== 'stop' && item.file === track.file ? 'activePlaylistTrack' : undefined" @input="onPlaylistItemClick"> @@ -167,7 +168,7 @@