This commit is contained in:
An Phan 2015-12-14 12:25:42 +08:00
parent 73802d4584
commit 957505e4a4
10 changed files with 97 additions and 20 deletions

12
browserconfig.xml Normal file
View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Please read: https://msdn.microsoft.com/en-us/library/ie/dn455106.aspx -->
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="public/img/tile.png"/>
<square150x150logo src="public/img/tile.png"/>
<wide310x150logo src="public/img/tile-wide.png"/>
<square310x310logo src="public/img/tile.png"/>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
resources/assets/img/tile.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View file

@ -13,14 +13,17 @@
<div class="buttons" v-show="!isPhone || showingControls"> <div class="buttons" v-show="!isPhone || showingControls">
<button class="play-shuffle" <button class="play-shuffle"
@click.prevent="shuffle" @click.prevent="shuffle"
v-if="state.songs.length" v-if="state.songs.length && selectedSongs.length < 2"
> >
<i class="fa fa-random"></i> All <i class="fa fa-random"></i> All
</button> </button>
<button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1">
<i class="fa fa-random"></i> Selected
</button>
</div> </div>
</h1> </h1>
<song-list :items="state.songs" type="favorites"></song-list> <song-list :items="state.songs" :selected-songs.sync="selectedSongs" type="favorites"></song-list>
</section> </section>
</template> </template>
@ -30,8 +33,11 @@
import songList from '../../shared/song-list.vue'; import songList from '../../shared/song-list.vue';
import favoriteStore from '../../../stores/favorite'; import favoriteStore from '../../../stores/favorite';
import playback from '../../../services/playback'; import playback from '../../../services/playback';
import shuffleSelectedMixin from '../../../mixins/shuffle-selected';
export default { export default {
mixins: [shuffleSelectedMixin],
components: { songList }, components: { songList },
data () { data () {

View file

@ -13,10 +13,13 @@
<div class="buttons" v-show="!isPhone || showingControls"> <div class="buttons" v-show="!isPhone || showingControls">
<button class="play-shuffle" <button class="play-shuffle"
@click.prevent="shuffle" @click.prevent="shuffle"
v-if="playlist.songs.length" v-if="playlist.songs.length && selectedSongs.length < 2"
> >
<i class="fa fa-random"></i> All <i class="fa fa-random"></i> All
</button> </button>
<button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1">
<i class="fa fa-random"></i> Selected
</button>
<button class="del" <button class="del"
title="Delete this playlist" title="Delete this playlist"
@click.prevent="del"> @click.prevent="del">
@ -25,7 +28,11 @@
</div> </div>
</h1> </h1>
<song-list :items="playlist.songs" type="playlist" :playlist="playlist"></song-list> <song-list :items="playlist.songs"
:selected-songs.sync="selectedSongs"
type="playlist"
:playlist="playlist">
</song-list>
</section> </section>
</template> </template>
@ -35,8 +42,11 @@
import songList from '../../shared/song-list.vue'; import songList from '../../shared/song-list.vue';
import playlistStore from '../../../stores/playlist'; import playlistStore from '../../../stores/playlist';
import playback from '../../../services/playback'; import playback from '../../../services/playback';
import shuffleSelectedMixin from '../../../mixins/shuffle-selected';
export default { export default {
mixins: [shuffleSelectedMixin],
components: { songList }, components: { songList },
data() { data() {

View file

@ -11,9 +11,16 @@
</span> </span>
<div class="buttons" v-show="!isPhone || showingControls"> <div class="buttons" v-show="!isPhone || showingControls">
<button class="play-shuffle" @click.prevent="shuffle" v-if="state.songs.length > 1"> <button
class="play-shuffle"
@click.prevent="shuffle"
v-if="state.songs.length > 1 && selectedSongs.length < 2"
>
<i class="fa fa-random"></i> All <i class="fa fa-random"></i> All
</button> </button>
<button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1">
<i class="fa fa-random"></i> Selected
</button>
<button class="save" @click.prevent="saving = !saving" v-if="state.songs.length > 1"> <button class="save" @click.prevent="saving = !saving" v-if="state.songs.length > 1">
{{ saving ? 'Cancel' : 'Save' }} {{ saving ? 'Cancel' : 'Save' }}
</button> </button>
@ -31,7 +38,7 @@
</div> </div>
</h1> </h1>
<song-list :items="state.songs" type="queue"></song-list> <song-list :items="state.songs" :selected-songs.sync="selectedSongs" type="queue"></song-list>
</div> </div>
</template> </template>
@ -43,8 +50,11 @@
import playlistStore from '../../../stores/playlist'; import playlistStore from '../../../stores/playlist';
import queueStore from '../../../stores/queue'; import queueStore from '../../../stores/queue';
import playback from '../../../services/playback'; import playback from '../../../services/playback';
import shuffleSelectedMixin from '../../../mixins/shuffle-selected';
export default { export default {
mixins: [shuffleSelectedMixin],
components: { songList }, components: { songList },
data() { data() {

View file

@ -11,13 +11,20 @@
</span> </span>
<div class="buttons" v-show="!isPhone || showingControls"> <div class="buttons" v-show="!isPhone || showingControls">
<button class="play-shuffle" @click.prevent="shuffle" v-if="state.songs.length"> <button
class="play-shuffle"
@click.prevent="shuffle"
v-if="state.songs.length && selectedSongs.length < 2"
>
<i class="fa fa-random"></i> All <i class="fa fa-random"></i> All
</button> </button>
<button class="play-shuffle" @click.prevent="shuffleSelected" v-if="selectedSongs.length > 1">
<i class="fa fa-random"></i> Selected
</button>
</div> </div>
</h1> </h1>
<song-list :items="state.songs"></song-list> <song-list :items="state.songs" :selected-songs.sync="selectedSongs"></song-list>
</section> </section>
</template> </template>
@ -27,8 +34,11 @@
import songList from '../../shared/song-list.vue'; import songList from '../../shared/song-list.vue';
import songStore from '../../../stores/song'; import songStore from '../../../stores/song';
import playback from '../../../services/playback'; import playback from '../../../services/playback';
import shuffleSelectedMixin from '../../../mixins/shuffle-selected';
export default { export default {
mixins: [shuffleSelectedMixin],
components: { songList }, components: { songList },
data() { data() {

View file

@ -76,7 +76,7 @@
import playback from '../../services/playback'; import playback from '../../services/playback';
export default { export default {
props: ['items', 'type', 'playlist'], props: ['items', 'type', 'playlist', 'selectedSongs'],
mixins: [infiniteScroll], mixins: [infiniteScroll],
components: { songItem }, components: { songItem },
@ -140,7 +140,7 @@
* Execute the corresponding reaction(s) when the user presses Delete. * Execute the corresponding reaction(s) when the user presses Delete.
*/ */
handleDelete() { handleDelete() {
var songs = this.getSelectedSongs(); var songs = this.selectedSongs;
if (!songs.length) { if (!songs.length) {
return; return;
@ -167,7 +167,7 @@
* Execute the corresponding reaction(s) when the user presses Enter. * Execute the corresponding reaction(s) when the user presses Enter.
*/ */
handleEnter(e) { handleEnter(e) {
var songs = this.getSelectedSongs(); var songs = this.selectedSongs;
if (!songs.length) { if (!songs.length) {
return; return;
@ -229,21 +229,20 @@
} }
$(this.$els.wrapper).find('.song-item').addClass('selected'); $(this.$els.wrapper).find('.song-item').addClass('selected');
this.gatherSelected();
}, },
/** /**
* Get the currerntly selected songs. * Gather all selected songs
* *
* @return array An array of Song objects. * @return array An array of Song object
*/ */
getSelectedSongs() { gatherSelected() {
var songs = []; var ids = _.map($(this.$els.wrapper).find('.song-item.selected'), row => {
return $(row).data('song-id');
_.each($(this.$els.wrapper).find('.song-item.selected'), row => {
songs.push(songStore.byId($(row).data('song-id')));
}); });
return songs; this.selectedSongs = songStore.byIds(ids);
}, },
@ -280,6 +279,8 @@
this.selectRowsBetweenIndexes([this.lastSelectedRow.rowIndex, row.rowIndex]) this.selectRowsBetweenIndexes([this.lastSelectedRow.rowIndex, row.rowIndex])
} }
} }
this.gatherSelected();
}, },
toggleRow(row) { toggleRow(row) {
@ -312,7 +313,7 @@
// We can opt for something like application/x-koel.text+plain here to sound fancy, // We can opt for something like application/x-koel.text+plain here to sound fancy,
// but forget it. // but forget it.
e.dataTransfer.setData('text/plain', _.pluck(this.getSelectedSongs(), 'id')); e.dataTransfer.setData('text/plain', _.pluck(this.selectedSongs, 'id'));
e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.effectAllowed = 'move';
// Set a fancy icon // Set a fancy icon

View file

@ -0,0 +1,28 @@
import $ from 'jquery';
import playback from '../services/playback';
/**
* Add a "shuffle selected" functionality to any component containing a song-list component using this mixin.
* Such a component should:
* - pass "selectedSongs" SYNC prop into the song-list component, e.g.
* <song-list :items="state.songs" :selected-songs.sync="selectedSongs" type="queue"></song-list>
* - trigger shuffling with shuffleSelected() method
*/
export default {
data() {
return {
selectedSongs: [],
};
},
methods: {
shuffleSelected() {
if (this.selectedSongs.length < 2) {
return;
}
playback.queueAndPlay(this.selectedSongs, true);
},
},
};