Skip to content
Snippets Groups Projects
Verified Commit f1f9f935 authored by rrrnld's avatar rrrnld Committed by Georg Krause
Browse files

Make playing tracks in their playlist the default

parent 5d745fea
Branches
No related tags found
No related merge requests found
Make "play in list" the default when interacting with individual tracks (#1274)
<template> <template>
<div class="album-entries"> <div class="album-entries">
<div :class="[{active: currentTrack && isPlaying && track.id === currentTrack.id}, 'album-entry']" v-for="track in tracks" :key="track.id"> <div :class="[{active: currentTrack && isPlaying && track.id === currentTrack.id}, 'album-entry']" @click.prevent="replacePlay(tracks, index)" v-for="(track, index) in tracks" :key="track.id">
<div class="actions"> <div class="actions">
<play-button class="basic circular icon" :button-classes="['circular inverted vibrant icon button']" :discrete="true" :icon-only="true" :track="track"></play-button> <play-button class="basic circular icon" :button-classes="['circular inverted vibrant icon button']" :discrete="true" :icon-only="true" :track="track" :tracks="tracks"></play-button>
</div> </div>
<div class="position">{{ prettyPosition(track.position) }}</div> <div class="position">{{ prettyPosition(track.position) }}</div>
<div class="content ellipsis"> <div class="content ellipsis">
<router-link :to="{name: 'library.tracks.detail', params: {id: track.id}}" class="discrete link">
<strong>{{ track.title }}</strong><br> <strong>{{ track.title }}</strong><br>
</router-link>
</div> </div>
<div class="meta"> <div class="meta">
<template v-if="$store.state.auth.authenticated && $store.getters['favorites/isFavorite'](track.id)"> <template v-if="$store.state.auth.authenticated && $store.getters['favorites/isFavorite'](track.id)">
...@@ -54,7 +52,13 @@ export default { ...@@ -54,7 +52,13 @@ export default {
var s = String(position); var s = String(position);
while (s.length < (size || 2)) {s = "0" + s;} while (s.length < (size || 2)) {s = "0" + s;}
return s; return s;
} },
replacePlay (tracks, trackIndex) {
this.$store.dispatch('queue/clean')
this.$store.dispatch('queue/appendMany', {tracks: tracks}).then(() => {
this.$store.dispatch('queue/currentIndex', trackIndex)
})
},
} }
} }
</script> </script>
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
</button> </button>
<button <button
v-if="!discrete && !iconOnly" v-if="!discrete && !iconOnly"
@click.prevent="clicked = true" @click.stop.prevent="clicked = true"
:class="['ui', {disabled: !playable && !filterableArtist}, 'floating', 'dropdown', {'icon': !dropdownOnly}, {'button': !dropdownOnly}]"> :class="['ui', {disabled: !playable && !filterableArtist}, 'floating', 'dropdown', {'icon': !dropdownOnly}, {'button': !dropdownOnly}]">
<i :class="dropdownIconClasses.concat(['icon'])" :title="title" ></i> <i :class="dropdownIconClasses.concat(['icon'])" :title="title" ></i>
<div class="menu" v-if="clicked"> <div class="menu" v-if="clicked">
...@@ -27,6 +27,9 @@ ...@@ -27,6 +27,9 @@
<button v-if="track" class="item basic" :disabled="!playable" @click.stop.prevent="$store.dispatch('radios/start', {type: 'similar', objectId: track.id})" :title="labels.startRadio"> <button v-if="track" class="item basic" :disabled="!playable" @click.stop.prevent="$store.dispatch('radios/start', {type: 'similar', objectId: track.id})" :title="labels.startRadio">
<i class="feed icon"></i><translate translate-context="*/Queue/Button.Label/Short, Verb">Play radio</translate> <i class="feed icon"></i><translate translate-context="*/Queue/Button.Label/Short, Verb">Play radio</translate>
</button> </button>
<button v-if="track" class="item basic" @click.stop.prevent="$router.push(`/library/tracks/${track.id}/`)">
<i class="info icon"></i><translate translate-context="*/Queue/Dropdown/Button/Label/Short">Track details</translate>
</button>
<div class="divider"></div> <div class="divider"></div>
<button v-if="filterableArtist" ref="filterArtist" data-ref="filterArtist" class="item basic" :disabled="!filterableArtist" @click.stop.prevent="filterArtist" :title="labels.hideArtist"> <button v-if="filterableArtist" ref="filterArtist" data-ref="filterArtist" class="item basic" :disabled="!filterableArtist" @click.stop.prevent="filterArtist" :title="labels.hideArtist">
<i class="eye slash outline icon"></i><translate translate-context="*/Queue/Dropdown/Button/Label/Short">Hide content from this artist</translate> <i class="eye slash outline icon"></i><translate translate-context="*/Queue/Dropdown/Button/Label/Short">Hide content from this artist</translate>
...@@ -143,7 +146,6 @@ export default { ...@@ -143,7 +146,6 @@ export default {
}, },
}, },
methods: { methods: {
filterArtist () { filterArtist () {
this.$store.dispatch('moderation/hide', {type: 'artist', target: this.filterableArtist}) this.$store.dispatch('moderation/hide', {type: 'artist', target: this.filterableArtist})
}, },
...@@ -175,7 +177,9 @@ export default { ...@@ -175,7 +177,9 @@ export default {
let self = this let self = this
this.isLoading = true this.isLoading = true
let getTracks = new Promise((resolve, reject) => { let getTracks = new Promise((resolve, reject) => {
if (self.track) { if (self.tracks) {
resolve(self.tracks)
} else if (self.track) {
if (!self.track.uploads || self.track.uploads.length === 0) { if (!self.track.uploads || self.track.uploads.length === 0) {
// fetch uploads from api // fetch uploads from api
axios.get(`tracks/${self.track.id}/`).then((response) => { axios.get(`tracks/${self.track.id}/`).then((response) => {
...@@ -184,8 +188,6 @@ export default { ...@@ -184,8 +188,6 @@ export default {
} else { } else {
resolve([self.track]) resolve([self.track])
} }
} else if (self.tracks) {
resolve(self.tracks)
} else if (self.playlist) { } else if (self.playlist) {
let url = 'playlists/' + self.playlist.id + '/' let url = 'playlists/' + self.playlist.id + '/'
axios.get(url + 'tracks/').then((response) => { axios.get(url + 'tracks/').then((response) => {
...@@ -236,7 +238,14 @@ export default { ...@@ -236,7 +238,14 @@ export default {
let self = this let self = this
self.$store.dispatch('queue/clean') self.$store.dispatch('queue/clean')
this.getPlayableTracks().then((tracks) => { this.getPlayableTracks().then((tracks) => {
self.$store.dispatch('queue/appendMany', {tracks: tracks}).then(() => self.addMessage(tracks)) self.$store.dispatch('queue/appendMany', {tracks: tracks}).then(() => {
if (self.track) {
// set queue position to selected track
const trackIndex = self.tracks.findIndex(track => track.id === self.track.id)
self.$store.dispatch('queue/currentIndex', trackIndex)
}
self.addMessage(tracks)
})
}) })
jQuery(self.$el).find('.ui.dropdown').dropdown('hide') jQuery(self.$el).find('.ui.dropdown').dropdown('hide')
}, },
......
<template> <template>
<tr> <tr>
<td> <td>
<play-button :class="['basic', {vibrant: currentTrack && isPlaying && track.id === currentTrack.id}, 'icon']" :discrete="true" :is-playable="playable" :track="track"></play-button> <play-button :class="['basic', {vibrant: currentTrack && isPlaying && track.id === currentTrack.id}, 'icon']"
:discrete="true"
:is-playable="playable"
:track="track"
:track-index="trackIndex"
:tracks="tracks"></play-button>
</td> </td>
<td> <td>
<img alt="" class="ui mini image" v-if="track.album && track.album.cover && track.album.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](track.album.cover.urls.medium_square_crop)"> <img alt="" class="ui mini image" v-if="track.album && track.album.cover && track.album.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](track.album.cover.urls.medium_square_crop)">
<img alt="" class="ui mini image" v-else src="../../../assets/audio/default-cover.png"> <img alt="" class="ui mini image" v-else src="../../../assets/audio/default-cover.png">
</td> </td>
<td colspan="6"> <td colspan="6">
<router-link class="track" :to="{name: 'library.tracks.detail', params: {id: track.id }}"> <button class="track" @click.stop="playSong()">
<template v-if="displayPosition && track.position"> <template v-if="displayPosition && track.position">
{{ track.position }}. {{ track.position }}.
</template> </template>
{{ track.title|truncate(40) }} {{ track.title|truncate(40) }}
</router-link> </button>
</td> </td>
<td colspan="4"> <td colspan="4">
<router-link class="artist discrete link" :to="{name: 'library.artists.detail', params: {id: track.artist.id }}"> <router-link class="artist discrete link" :to="{name: 'library.artists.detail', params: {id: track.artist.id }}">
...@@ -56,6 +61,8 @@ import PlayButton from '@/components/audio/PlayButton' ...@@ -56,6 +61,8 @@ import PlayButton from '@/components/audio/PlayButton'
export default { export default {
props: { props: {
track: {type: Object, required: true}, track: {type: Object, required: true},
trackIndex: {type: Number, required: true},
tracks: {type: Array, required: false},
artist: {type: Object, required: false}, artist: {type: Object, required: false},
displayPosition: {type: Boolean, default: false}, displayPosition: {type: Boolean, default: false},
displayActions: {type: Boolean, default: true}, displayActions: {type: Boolean, default: true},
...@@ -80,6 +87,16 @@ export default { ...@@ -80,6 +87,16 @@ export default {
return this.track.album.artist return this.track.album.artist
} }
}, },
},
methods: {
playSong () {
this.$store.dispatch('queue/clean')
this.$store.dispatch('queue/appendMany', {
tracks: this.tracks
}).then(() => {
this.$store.dispatch('queue/currentIndex', this.trackIndex)
})
},
} }
} }
</script> </script>
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
:display-position="displayPosition" :display-position="displayPosition"
:display-actions="displayActions" :display-actions="displayActions"
:track="track" :track="track"
:track-index="index"
:tracks="allTracks"
:artist="artist" :artist="artist"
:key="index + '-' + track.id" :key="index + '-' + track.id"
v-for="(track, index) in allTracks"></track-row> v-for="(track, index) in allTracks"></track-row>
......
...@@ -11,4 +11,9 @@ ...@@ -11,4 +11,9 @@
visibility: hidden; visibility: hidden;
} }
} }
.track {
display: block;
line-height: 2;
}
} }
...@@ -75,6 +75,18 @@ ...@@ -75,6 +75,18 @@
} }
} }
} }
.album-entry:hover {
cursor: pointer;
// explicitly style the button as if it was hovered itself
.ui.inverted.vibrant.button {
background-color: var(--vibrant-hover-color);
color: white;
box-shadow: 0 0 0 2px var(--vibrant-color) inset;
}
}
.album-entry, .channel-entry-card { .album-entry, .channel-entry-card {
border-radius: 5px; border-radius: 5px;
padding: 0.5em; padding: 0.5em;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment