Make playing tracks in their playlist the default

album-sliders
heyarne 2021-02-24 09:03:14 +01:00 zatwierdzone przez Georg Krause
rodzic 5d745fea6f
commit f1f9f935cf
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: FD479B9A4D48E632
7 zmienionych plików z 68 dodań i 18 usunięć

Wyświetl plik

@ -0,0 +1 @@
Make "play in list" the default when interacting with individual tracks (#1274)

Wyświetl plik

@ -1,14 +1,12 @@
<template>
<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">
<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 class="position">{{ prettyPosition(track.position) }}</div>
<div class="content ellipsis">
<router-link :to="{name: 'library.tracks.detail', params: {id: track.id}}" class="discrete link">
<strong>{{ track.title }}</strong><br>
</router-link>
<strong>{{ track.title }}</strong><br>
</div>
<div class="meta">
<template v-if="$store.state.auth.authenticated && $store.getters['favorites/isFavorite'](track.id)">
@ -17,7 +15,7 @@
<human-duration v-if="track.uploads[0] && track.uploads[0].duration" :duration="track.uploads[0].duration"></human-duration>
</div>
<div class="actions">
<play-button class="play-button basic icon" :dropdown-only="true" :is-playable="track.is_playable" :dropdown-icon-classes="['ellipsis', 'vertical', 'large really discrete']" :track="track"></play-button>
<play-button class="play-button basic icon" :dropdown-only="true" :is-playable="track.is_playable" :dropdown-icon-classes="['ellipsis', 'vertical', 'large really discrete']" :track="track"></play-button>
</div>
</div>
</div>
@ -54,7 +52,13 @@ export default {
var s = String(position);
while (s.length < (size || 2)) {s = "0" + 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>

Wyświetl plik

@ -11,7 +11,7 @@
</button>
<button
v-if="!discrete && !iconOnly"
@click.prevent="clicked = true"
@click.stop.prevent="clicked = true"
:class="['ui', {disabled: !playable && !filterableArtist}, 'floating', 'dropdown', {'icon': !dropdownOnly}, {'button': !dropdownOnly}]">
<i :class="dropdownIconClasses.concat(['icon'])" :title="title" ></i>
<div class="menu" v-if="clicked">
@ -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">
<i class="feed icon"></i><translate translate-context="*/Queue/Button.Label/Short, Verb">Play radio</translate>
</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>
<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>
@ -35,7 +38,7 @@
v-for="obj in getReportableObjs({track, album, artist, playlist, account, channel})"
:key="obj.target.type + obj.target.id"
class="item basic"
:ref="`report${obj.target.type}${obj.target.id}`" :data-ref="`report${obj.target.type}${obj.target.id}`"
:ref="`report${obj.target.type}${obj.target.id}`" :data-ref="`report${obj.target.type}${obj.target.id}`"
@click.stop.prevent="$store.dispatch('moderation/report', obj.target)">
<i class="share icon" /> {{ obj.label }}
</button>
@ -90,7 +93,7 @@ export default {
} else {
replacePlay = this.$pgettext('*/Queue/Dropdown/Button/Title', 'Play tracks')
}
return {
playNow: this.$pgettext('*/Queue/Dropdown/Button/Title', 'Play now'),
addToQueue: this.$pgettext('*/Queue/Dropdown/Button/Title', 'Add to current queue'),
@ -143,7 +146,6 @@ export default {
},
},
methods: {
filterArtist () {
this.$store.dispatch('moderation/hide', {type: 'artist', target: this.filterableArtist})
},
@ -175,7 +177,9 @@ export default {
let self = this
this.isLoading = true
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) {
// fetch uploads from api
axios.get(`tracks/${self.track.id}/`).then((response) => {
@ -184,8 +188,6 @@ export default {
} else {
resolve([self.track])
}
} else if (self.tracks) {
resolve(self.tracks)
} else if (self.playlist) {
let url = 'playlists/' + self.playlist.id + '/'
axios.get(url + 'tracks/').then((response) => {
@ -236,7 +238,14 @@ export default {
let self = this
self.$store.dispatch('queue/clean')
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')
},

Wyświetl plik

@ -1,19 +1,24 @@
<template>
<tr>
<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>
<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">
</td>
<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">
{{ track.position }}.
</template>
{{ track.title|truncate(40) }}
</router-link>
</button>
</td>
<td colspan="4">
<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'
export default {
props: {
track: {type: Object, required: true},
trackIndex: {type: Number, required: true},
tracks: {type: Array, required: false},
artist: {type: Object, required: false},
displayPosition: {type: Boolean, default: false},
displayActions: {type: Boolean, default: true},
@ -80,6 +87,16 @@ export default {
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>

Wyświetl plik

@ -22,6 +22,8 @@
:display-position="displayPosition"
:display-actions="displayActions"
:track="track"
:track-index="index"
:tracks="allTracks"
:artist="artist"
:key="index + '-' + track.id"
v-for="(track, index) in allTracks"></track-row>

Wyświetl plik

@ -11,4 +11,9 @@
visibility: hidden;
}
}
.track {
display: block;
line-height: 2;
}
}

Wyświetl plik

@ -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 {
border-radius: 5px;
padding: 0.5em;