owntone-server/web-src/src/pages/SpotifyPagePlaylist.vue
Alain Nussbaumer 0bc13e7c63 [web] Fix for Spotify playlists with incorrect count of tracks and missing market data
Some Spotify playlists contain null tracks, thus provoking an incorrect count of track.
Moreover, the market data was missing in the API request.
2023-06-10 13:46:33 +02:00

174 lines
4.6 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, index) in tracks"
:key="track.id"
:track="track"
:album="track.album"
:position="index"
: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'
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) {
this.tracks = data.items.reduce((tracks, item) => {
if (item.track) {
tracks.push(item.track)
}
return tracks
}, this.tracks)
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>