mirror of
https://github.com/owntone/owntone-server.git
synced 2025-02-01 08:56:00 -05:00
6a2f85e04f
If a Spotify playlist is containing unplayable tracks (e.g., wrong market), the position of the subsequent tracks in the playlist must be changed accordingly. Moreover, the album property was provided for no reason.
182 lines
4.9 KiB
Vue
182 lines
4.9 KiB
Vue
<template>
|
|
<content-with-heading>
|
|
<template #heading-left>
|
|
<div class="title is-4" v-text="playlist.name" />
|
|
</template>
|
|
<template #heading-right>
|
|
<div class="buttons is-centered">
|
|
<a
|
|
class="button is-small is-light is-rounded"
|
|
@click="show_playlist_details_modal = true"
|
|
>
|
|
<span class="icon"><mdicon name="dots-horizontal" size="16" /></span>
|
|
</a>
|
|
<a class="button is-small is-dark is-rounded" @click="play">
|
|
<span class="icon"><mdicon name="shuffle" size="16" /></span>
|
|
<span v-text="$t('page.spotify.playlist.shuffle')" />
|
|
</a>
|
|
</div>
|
|
</template>
|
|
<template #content>
|
|
<p
|
|
class="heading has-text-centered-mobile"
|
|
v-text="
|
|
$t('page.spotify.playlist.count', { count: playlist.tracks.total })
|
|
"
|
|
/>
|
|
<spotify-list-item-track
|
|
v-for="track in tracks"
|
|
:key="track.id"
|
|
:track="track"
|
|
:position="track.position"
|
|
:context_uri="playlist.uri"
|
|
>
|
|
<template #actions>
|
|
<a @click.prevent.stop="open_track_dialog(track)">
|
|
<span class="icon has-text-dark"
|
|
><mdicon name="dots-vertical" size="16"
|
|
/></span>
|
|
</a>
|
|
</template>
|
|
</spotify-list-item-track>
|
|
<VueEternalLoading v-if="offset < total" :load="load_next">
|
|
<template #no-more> . </template>
|
|
</VueEternalLoading>
|
|
<spotify-modal-dialog-track
|
|
:show="show_track_details_modal"
|
|
:track="selected_track"
|
|
:album="selected_track.album"
|
|
@close="show_track_details_modal = false"
|
|
/>
|
|
<spotify-modal-dialog-playlist
|
|
:show="show_playlist_details_modal"
|
|
:playlist="playlist"
|
|
@close="show_playlist_details_modal = false"
|
|
/>
|
|
</template>
|
|
</content-with-heading>
|
|
</template>
|
|
|
|
<script>
|
|
import ContentWithHeading from '@/templates/ContentWithHeading.vue'
|
|
import SpotifyListItemTrack from '@/components/SpotifyListItemTrack.vue'
|
|
import SpotifyModalDialogTrack from '@/components/SpotifyModalDialogTrack.vue'
|
|
import SpotifyModalDialogPlaylist from '@/components/SpotifyModalDialogPlaylist.vue'
|
|
import store from '@/store'
|
|
import webapi from '@/webapi'
|
|
import SpotifyWebApi from 'spotify-web-api-js'
|
|
import { VueEternalLoading } from '@ts-pro/vue-eternal-loading'
|
|
import { mdiAxe } from '@mdi/js'
|
|
|
|
const PAGE_SIZE = 50
|
|
|
|
const dataObject = {
|
|
load: function (to) {
|
|
const spotifyApi = new SpotifyWebApi()
|
|
spotifyApi.setAccessToken(store.state.spotify.webapi_token)
|
|
return Promise.all([
|
|
spotifyApi.getPlaylist(to.params.playlist_id),
|
|
spotifyApi.getPlaylistTracks(to.params.playlist_id, {
|
|
limit: PAGE_SIZE,
|
|
offset: 0,
|
|
market: store.state.spotify.webapi_country
|
|
})
|
|
])
|
|
},
|
|
|
|
set(vm, response) {
|
|
vm.playlist = response[0]
|
|
vm.tracks = []
|
|
vm.total = 0
|
|
vm.offset = 0
|
|
vm.append_tracks(response[1])
|
|
}
|
|
}
|
|
|
|
export default {
|
|
name: 'SpotifyPagePlaylist',
|
|
components: {
|
|
ContentWithHeading,
|
|
SpotifyListItemTrack,
|
|
SpotifyModalDialogTrack,
|
|
SpotifyModalDialogPlaylist,
|
|
VueEternalLoading
|
|
},
|
|
|
|
beforeRouteEnter(to, from, next) {
|
|
dataObject.load(to).then((response) => {
|
|
next((vm) => dataObject.set(vm, response))
|
|
})
|
|
},
|
|
beforeRouteUpdate(to, from, next) {
|
|
const vm = this
|
|
dataObject.load(to).then((response) => {
|
|
dataObject.set(vm, response)
|
|
next()
|
|
})
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
playlist: { tracks: {} },
|
|
tracks: [],
|
|
total: 0,
|
|
offset: 0,
|
|
|
|
show_track_details_modal: false,
|
|
selected_track: {},
|
|
|
|
show_playlist_details_modal: false
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
load_next({ loaded }) {
|
|
const spotifyApi = new SpotifyWebApi()
|
|
spotifyApi.setAccessToken(this.$store.state.spotify.webapi_token)
|
|
spotifyApi
|
|
.getPlaylistTracks(this.playlist.id, {
|
|
limit: PAGE_SIZE,
|
|
offset: this.offset,
|
|
market: store.state.spotify.webapi_country
|
|
})
|
|
.then((data) => {
|
|
this.append_tracks(data)
|
|
loaded(data.items.length, PAGE_SIZE)
|
|
})
|
|
},
|
|
|
|
append_tracks(data) {
|
|
let position = Math.max(
|
|
-1,
|
|
...this.tracks.map((item) => item.position).filter((item) => item)
|
|
)
|
|
// Filters out null tracks and adds a position to the playable tracks
|
|
data.items.forEach((item) => {
|
|
const track = item.track
|
|
if (track) {
|
|
if (track.is_playable) {
|
|
track.position = ++position
|
|
}
|
|
this.tracks.push(track)
|
|
}
|
|
})
|
|
this.total = data.total
|
|
this.offset += data.limit
|
|
},
|
|
|
|
play() {
|
|
this.show_details_modal = false
|
|
webapi.player_play_uri(this.playlist.uri, true)
|
|
},
|
|
|
|
open_track_dialog(track) {
|
|
this.selected_track = track
|
|
this.show_track_details_modal = true
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style></style>
|