music.mpd vue.js refactoring WIP: Implemented playlist track move feature
This commit is contained in:
parent
d3ecb7b871
commit
611a137ff6
7 changed files with 74 additions and 24 deletions
|
@ -132,6 +132,13 @@
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
@include animation(active-track 5s infinite);
|
@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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,3 +23,6 @@ $playlist-controls-border: $default-border-2;
|
||||||
$active-track-bg-1: #d4ffe3;
|
$active-track-bg-1: #d4ffe3;
|
||||||
$active-track-bg-2: #9cdfb0;
|
$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);
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,11 @@ Vue.component('music-mpd', {
|
||||||
browser: false,
|
browser: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
moveMode: {
|
||||||
|
playlist: false,
|
||||||
|
editor: false,
|
||||||
|
},
|
||||||
|
|
||||||
selectedPlaylistItems: {},
|
selectedPlaylistItems: {},
|
||||||
selectedBrowserItems: {},
|
selectedBrowserItems: {},
|
||||||
|
|
||||||
|
@ -45,24 +50,29 @@ Vue.component('music-mpd', {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
items.push(
|
items.push({
|
||||||
{
|
text: 'Add to playlist',
|
||||||
text: 'Add to playlist',
|
icon: 'list',
|
||||||
icon: 'list',
|
});
|
||||||
},
|
|
||||||
{
|
if (Object.keys(this.selectedPlaylistItems).length < this.playlist.length) {
|
||||||
|
items.push({
|
||||||
text: 'Move',
|
text: 'Move',
|
||||||
icon: 'retweet',
|
icon: 'retweet',
|
||||||
},
|
click: function() {
|
||||||
{
|
self.moveMode.playlist = true;
|
||||||
text: 'Remove from queue',
|
|
||||||
icon: 'trash',
|
|
||||||
click: async function() {
|
|
||||||
await self.del();
|
|
||||||
self.selectedPlaylistItems = {};
|
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
items.push({
|
||||||
|
text: 'Remove from queue',
|
||||||
|
icon: 'trash',
|
||||||
|
click: async function() {
|
||||||
|
await self.del();
|
||||||
|
self.selectedPlaylistItems = {};
|
||||||
},
|
},
|
||||||
);
|
});
|
||||||
|
|
||||||
if (Object.keys(this.selectedPlaylistItems).length === 1) {
|
if (Object.keys(this.selectedPlaylistItems).length === 1) {
|
||||||
items.push({
|
items.push({
|
||||||
|
@ -473,10 +483,8 @@ Vue.component('music-mpd', {
|
||||||
this._parsePlaylist(playlist);
|
this._parsePlaylist(playlist);
|
||||||
},
|
},
|
||||||
|
|
||||||
load: async function(item) {
|
load: async function(item, play=false) {
|
||||||
let status = await request('music.mpd.load', {playlist:item});
|
await request('music.mpd.load', {playlist:item, play:play});
|
||||||
this._parseStatus(status);
|
|
||||||
|
|
||||||
let playlist = await request('music.mpd.playlistinfo');
|
let playlist = await request('music.mpd.playlistinfo');
|
||||||
this._parsePlaylist(playlist);
|
this._parsePlaylist(playlist);
|
||||||
},
|
},
|
||||||
|
@ -511,6 +519,16 @@ Vue.component('music-mpd', {
|
||||||
this._parseBrowserItems(items);
|
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() {
|
swap: async function() {
|
||||||
if (Object.keys(this.selectedPlaylistItems).length !== 2) {
|
if (Object.keys(this.selectedPlaylistItems).length !== 2) {
|
||||||
return;
|
return;
|
||||||
|
@ -693,13 +711,24 @@ Vue.component('music-mpd', {
|
||||||
this.browserFilter.toLocaleLowerCase().split(' ').filter(_ => _.length > 0).join(' ')) >= 0;
|
this.browserFilter.toLocaleLowerCase().split(' ').filter(_ => _.length > 0).join(' ')) >= 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
onPlaylistItemClick: function(track) {
|
onPlaylistItemClick: async function(track) {
|
||||||
if (this.selectionMode.playlist) {
|
if (this.selectionMode.playlist) {
|
||||||
if (track.pos in this.selectedPlaylistItems) {
|
if (track.pos in this.selectedPlaylistItems) {
|
||||||
Vue.delete(this.selectedPlaylistItems, track.pos);
|
Vue.delete(this.selectedPlaylistItems, track.pos);
|
||||||
} else {
|
} else {
|
||||||
Vue.set(this.selectedPlaylistItems, track.pos, track);
|
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) {
|
} else if (track.pos in this.selectedPlaylistItems) {
|
||||||
Vue.delete(this.selectedPlaylistItems, track.pos);
|
Vue.delete(this.selectedPlaylistItems, track.pos);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,6 +15,11 @@ Vue.component('music-mpd-playlist-item', {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
move: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,7 @@
|
||||||
:track="item"
|
:track="item"
|
||||||
:active="track.file && status.state !== 'stop' && item.file === track.file"
|
:active="track.file && status.state !== 'stop' && item.file === track.file"
|
||||||
:selected="item.pos in selectedPlaylistItems"
|
:selected="item.pos in selectedPlaylistItems"
|
||||||
|
:move="moveMode.playlist"
|
||||||
:ref="track.file && status.state !== 'stop' && item.file === track.file ? 'activePlaylistTrack' : undefined"
|
:ref="track.file && status.state !== 'stop' && item.file === track.file ? 'activePlaylistTrack' : undefined"
|
||||||
@input="onPlaylistItemClick">
|
@input="onPlaylistItemClick">
|
||||||
</music-mpd-playlist-item>
|
</music-mpd-playlist-item>
|
||||||
|
@ -167,7 +168,7 @@
|
||||||
<div class="col-3 pull-right">
|
<div class="col-3 pull-right">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<button @click="single" :class="{enabled: status.single}" title="Toggle single mode">
|
<button @click="single" :class="{enabled: status.single}" title="Toggle single mode">
|
||||||
<i class="fa fa-chess-pawn"></i>
|
<i class="fa fa-bullseye"></i>
|
||||||
</button>
|
</button>
|
||||||
<button @click="consume" :class="{enabled: status.consume}" title="Toggle consume mode">
|
<button @click="consume" :class="{enabled: status.consume}" title="Toggle consume mode">
|
||||||
<i class="fa fa-utensils"></i>
|
<i class="fa fa-utensils"></i>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<script type="text/x-template" id="tmpl-music-mpd-playlist-item">
|
<script type="text/x-template" id="tmpl-music-mpd-playlist-item">
|
||||||
<div class="row item playlist-item"
|
<div class="row item playlist-item"
|
||||||
:class="{selected: selected, active: active}"
|
:class="{selected: selected, active: active, move: move}"
|
||||||
@click="$emit('input', track)">
|
@click="$emit('input', track)">
|
||||||
<div class="col-5 artist" v-text="track.artist"></div>
|
<div class="col-5 artist" v-text="track.artist"></div>
|
||||||
<div class="col-5 title" v-text="track.title"></div>
|
<div class="col-5 title" v-text="track.title"></div>
|
||||||
|
|
|
@ -379,16 +379,21 @@ class MusicMpdPlugin(MusicPlugin):
|
||||||
return resource
|
return resource
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def load(self, playlist):
|
def load(self, playlist, play=True):
|
||||||
"""
|
"""
|
||||||
Load and play a playlist by name
|
Load and play a playlist by name
|
||||||
|
|
||||||
:param playlist: Playlist name
|
:param playlist: Playlist name
|
||||||
:type playlist: str
|
:type playlist: str
|
||||||
|
|
||||||
|
:param play: Start playback after loading the playlist (default: True)
|
||||||
|
:type play: bool
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._exec('load', playlist)
|
ret = self._exec('load', playlist)
|
||||||
return self.play()
|
if play:
|
||||||
|
self.play()
|
||||||
|
return ret
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def clear(self):
|
def clear(self):
|
||||||
|
|
Loading…
Reference in a new issue