[web] Refactor the Spotify track item page

This commit is contained in:
Alain Nussbaumer 2024-03-25 14:00:42 +01:00
parent aa5ae7993a
commit 0f3f8d5a36
6 changed files with 53 additions and 124 deletions

View File

@ -14,13 +14,14 @@
v-text="item.name" v-text="item.name"
/> />
<h2 <h2
class="subtitle is-7" class="subtitle is-7 has-text-weight-bold"
:class="{ :class="{
'has-text-grey': item.is_playable, 'has-text-grey': item.is_playable,
'has-text-grey-light': !item.is_playable 'has-text-grey-light': !item.is_playable
}" }"
v-text="item.artists[0].name" v-text="item.artists[0].name"
/> />
<h2 class="subtitle is-7 has-text-grey" v-text="item.album.name" />
<h2 v-if="!item.is_playable" class="subtitle is-7"> <h2 v-if="!item.is_playable" class="subtitle is-7">
(<span v-text="$t('list.spotify.not-playable-track')" /> (<span v-text="$t('list.spotify.not-playable-track')" />
<span <span
@ -34,21 +35,35 @@
</h2> </h2>
</div> </div>
<div class="media-right"> <div class="media-right">
<slot name="actions" /> <a @click.prevent.stop="show_details_modal = true">
<mdicon class="icon has-text-dark" name="dots-vertical" size="16" />
</a>
</div> </div>
</div> </div>
<teleport to="#app">
<modal-dialog-track-spotify
:show="show_details_modal"
:track="item"
@close="show_details_modal = false"
/>
</teleport>
</template> </template>
<script> <script>
import ModalDialogTrackSpotify from '@/components/ModalDialogTrackSpotify.vue'
import webapi from '@/webapi' import webapi from '@/webapi'
export default { export default {
name: 'ListItemTrackSpotify', name: 'ListItemTrackSpotify',
components: { ModalDialogTrackSpotify },
props: { props: {
context_uri: { required: true, type: String }, context_uri: { required: true, type: String },
item: { required: true, type: Object }, item: { required: true, type: Object },
position: { required: true, type: Number } position: { required: true, type: Number }
}, },
data() {
return { show_details_modal: false }
},
methods: { methods: {
play() { play() {
if (this.item.is_playable) { if (this.item.is_playable) {

View File

@ -16,7 +16,7 @@
<a <a
class="title is-6 has-text-link" class="title is-6 has-text-link"
@click="open_album" @click="open_album"
v-text="album.name" v-text="track.album.name"
/> />
</p> </p>
<p> <p>
@ -27,7 +27,7 @@
<a <a
class="title is-6 has-text-link" class="title is-6 has-text-link"
@click="open_artist" @click="open_artist"
v-text="album.artists[0].name" v-text="track.artists[0].name"
/> />
</p> </p>
<p> <p>
@ -37,7 +37,7 @@
/> />
<span <span
class="title is-6" class="title is-6"
v-text="$filters.date(album.release_date)" v-text="$filters.date(track.album.release_date)"
/> />
</p> </p>
<p> <p>
@ -106,47 +106,37 @@ import webapi from '@/webapi'
export default { export default {
name: 'ModalDialogTrackSpotify', name: 'ModalDialogTrackSpotify',
props: { props: {
album: {
default() {
return {}
},
type: Object
},
show: Boolean, show: Boolean,
track: { required: true, type: Object } track: { required: true, type: Object }
}, },
emits: ['close'], emits: ['close'],
methods: { methods: {
play() {
this.$emit('close')
webapi.player_play_uri(this.track.uri, false)
},
queue_add() {
this.$emit('close')
webapi.queue_add(this.track.uri)
},
queue_add_next() {
this.$emit('close')
webapi.queue_add_next(this.track.uri)
},
open_album() { open_album() {
this.$emit('close') this.$emit('close')
this.$router.push({ this.$router.push({
name: 'music-spotify-album', name: 'music-spotify-album',
params: { id: this.album.id } params: { id: this.track.album.id }
}) })
}, },
open_artist() { open_artist() {
this.$emit('close') this.$emit('close')
this.$router.push({ this.$router.push({
name: 'music-spotify-artist', name: 'music-spotify-artist',
params: { id: this.album.artists[0].id } params: { id: this.track.artists[0].id }
}) })
},
play() {
this.$emit('close')
webapi.player_play_uri(this.track.uri, false)
},
queue_add() {
this.$emit('close')
webapi.queue_add(this.track.uri)
},
queue_add_next() {
this.$emit('close')
webapi.queue_add_next(this.track.uri)
} }
} }
} }

View File

@ -40,33 +40,17 @@
" "
/> />
<list-item-track-spotify <list-item-track-spotify
v-for="(track, index) in album.tracks.items" v-for="(track, index) in tracks"
:key="track.id" :key="track.id"
:item="track" :item="track"
:position="index" :position="index"
:context_uri="album.uri" :context_uri="album.uri"
>
<template #actions>
<a @click.prevent.stop="open_track_dialog(track)">
<mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/> />
</a>
</template>
</list-item-track-spotify>
<modal-dialog-album-spotify <modal-dialog-album-spotify
:show="show_details_modal" :show="show_details_modal"
:album="album" :album="album"
@close="show_details_modal = false" @close="show_details_modal = false"
/> />
<modal-dialog-track-spotify
:show="show_track_details_modal"
:track="selected_track"
:album="album"
@close="show_track_details_modal = false"
/>
</template> </template>
</content-with-hero> </content-with-hero>
</div> </div>
@ -77,7 +61,6 @@ import ContentWithHero from '@/templates/ContentWithHero.vue'
import CoverArtwork from '@/components/CoverArtwork.vue' import CoverArtwork from '@/components/CoverArtwork.vue'
import ListItemTrackSpotify from '@/components/ListItemTrackSpotify.vue' import ListItemTrackSpotify from '@/components/ListItemTrackSpotify.vue'
import ModalDialogAlbumSpotify from '@/components/ModalDialogAlbumSpotify.vue' import ModalDialogAlbumSpotify from '@/components/ModalDialogAlbumSpotify.vue'
import ModalDialogTrackSpotify from '@/components/ModalDialogTrackSpotify.vue'
import SpotifyWebApi from 'spotify-web-api-js' import SpotifyWebApi from 'spotify-web-api-js'
import store from '@/store' import store from '@/store'
import webapi from '@/webapi' import webapi from '@/webapi'
@ -102,8 +85,7 @@ export default {
ContentWithHero, ContentWithHero,
CoverArtwork, CoverArtwork,
ListItemTrackSpotify, ListItemTrackSpotify,
ModalDialogAlbumSpotify, ModalDialogAlbumSpotify
ModalDialogTrackSpotify
}, },
beforeRouteEnter(to, from, next) { beforeRouteEnter(to, from, next) {
@ -122,12 +104,19 @@ export default {
data() { data() {
return { return {
album: { artists: [{}], tracks: {} }, album: { artists: [{}], tracks: {} },
selected_track: {}, show_details_modal: false
show_details_modal: false,
show_track_details_modal: false
} }
}, },
computed: {
tracks() {
const { album } = this
if (album.tracks.total) {
return album.tracks.items.map((track) => ({ ...track, album }))
}
return {}
}
},
methods: { methods: {
artwork_url(album) { artwork_url(album) {
return album.images?.[0]?.url ?? '' return album.images?.[0]?.url ?? ''
@ -138,10 +127,6 @@ export default {
params: { id: this.album.artists[0].id } params: { id: this.album.artists[0].id }
}) })
}, },
open_track_dialog(track) {
this.selected_track = track
this.show_track_details_modal = true
},
play() { play() {
this.show_details_modal = false this.show_details_modal = false
webapi.player_play_uri(this.album.uri, true) webapi.player_play_uri(this.album.uri, true)

View File

@ -10,17 +10,7 @@
v-for="album in new_releases" v-for="album in new_releases"
:key="album.id" :key="album.id"
:item="album" :item="album"
>
<template #actions>
<a @click.prevent.stop="open_album_dialog(album)">
<mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/> />
</a>
</template>
</list-item-album-spotify>
</template> </template>
</content-with-heading> </content-with-heading>
</div> </div>

View File

@ -31,17 +31,7 @@
:item="track" :item="track"
:position="track.position" :position="track.position"
:context_uri="playlist.uri" :context_uri="playlist.uri"
>
<template #actions>
<a @click.prevent.stop="open_track_dialog(track)">
<mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/> />
</a>
</template>
</list-item-track-spotify>
<VueEternalLoading v-if="offset < total" :load="load_next"> <VueEternalLoading v-if="offset < total" :load="load_next">
<template #loading> <template #loading>
<div class="columns is-centered"> <div class="columns is-centered">
@ -52,12 +42,6 @@
</template> </template>
<template #no-more>&nbsp;</template> <template #no-more>&nbsp;</template>
</VueEternalLoading> </VueEternalLoading>
<modal-dialog-track-spotify
:show="show_track_details_modal"
:track="selected_track"
:album="selected_track.album"
@close="show_track_details_modal = false"
/>
<modal-dialog-playlist-spotify <modal-dialog-playlist-spotify
:show="show_playlist_details_modal" :show="show_playlist_details_modal"
:playlist="playlist" :playlist="playlist"
@ -72,7 +56,6 @@
import ContentWithHeading from '@/templates/ContentWithHeading.vue' import ContentWithHeading from '@/templates/ContentWithHeading.vue'
import ListItemTrackSpotify from '@/components/ListItemTrackSpotify.vue' import ListItemTrackSpotify from '@/components/ListItemTrackSpotify.vue'
import ModalDialogPlaylistSpotify from '@/components/ModalDialogPlaylistSpotify.vue' import ModalDialogPlaylistSpotify from '@/components/ModalDialogPlaylistSpotify.vue'
import ModalDialogTrackSpotify from '@/components/ModalDialogTrackSpotify.vue'
import SpotifyWebApi from 'spotify-web-api-js' import SpotifyWebApi from 'spotify-web-api-js'
import { VueEternalLoading } from '@ts-pro/vue-eternal-loading' import { VueEternalLoading } from '@ts-pro/vue-eternal-loading'
import store from '@/store' import store from '@/store'
@ -109,7 +92,6 @@ export default {
ContentWithHeading, ContentWithHeading,
ListItemTrackSpotify, ListItemTrackSpotify,
ModalDialogPlaylistSpotify, ModalDialogPlaylistSpotify,
ModalDialogTrackSpotify,
VueEternalLoading VueEternalLoading
}, },
@ -130,9 +112,7 @@ export default {
return { return {
offset: 0, offset: 0,
playlist: { tracks: {} }, playlist: { tracks: {} },
selected_track: {},
show_playlist_details_modal: false, show_playlist_details_modal: false,
show_track_details_modal: false,
total: 0, total: 0,
tracks: [] tracks: []
} }
@ -171,10 +151,6 @@ export default {
loaded(data.items.length, PAGE_SIZE) loaded(data.items.length, PAGE_SIZE)
}) })
}, },
open_track_dialog(track) {
this.selected_track = track
this.show_track_details_modal = true
},
play() { play() {
this.show_details_modal = false this.show_details_modal = false
webapi.player_play_uri(this.playlist.uri, true) webapi.player_play_uri(this.playlist.uri, true)

View File

@ -46,17 +46,7 @@
:item="track" :item="track"
:position="0" :position="0"
:context_uri="track.uri" :context_uri="track.uri"
>
<template #actions>
<a @click.prevent.stop="open_track_dialog(track)">
<mdicon
class="icon has-text-dark"
name="dots-vertical"
size="16"
/> />
</a>
</template>
</list-item-track-spotify>
<VueEternalLoading <VueEternalLoading
v-if="query.type === 'track'" v-if="query.type === 'track'"
:load="search_tracks_next" :load="search_tracks_next"
@ -70,12 +60,6 @@
</template> </template>
<template #no-more>&nbsp;</template> <template #no-more>&nbsp;</template>
</VueEternalLoading> </VueEternalLoading>
<modal-dialog-track-spotify
:show="show_track_details_modal"
:track="selected_track"
:album="selected_track.album"
@close="show_track_details_modal = false"
/>
</template> </template>
<template #footer> <template #footer>
<nav v-if="show_all_button(tracks)" class="level"> <nav v-if="show_all_button(tracks)" class="level">
@ -108,8 +92,7 @@
v-for="artist in artists.items" v-for="artist in artists.items"
:key="artist.id" :key="artist.id"
:item="artist" :item="artist"
> />
</list-item-artist-spotify>
<VueEternalLoading <VueEternalLoading
v-if="query.type === 'artist'" v-if="query.type === 'artist'"
:load="search_artists_next" :load="search_artists_next"
@ -155,8 +138,7 @@
v-for="album in albums.items" v-for="album in albums.items"
:key="album.id" :key="album.id"
:item="album" :item="album"
> />
</list-item-album-spotify>
<VueEternalLoading <VueEternalLoading
v-if="query.type === 'album'" v-if="query.type === 'album'"
:load="search_albums_next" :load="search_albums_next"
@ -202,8 +184,7 @@
v-for="playlist in playlists.items" v-for="playlist in playlists.items"
:key="playlist.id" :key="playlist.id"
:item="playlist" :item="playlist"
> />
</list-item-playlist-spotify>
<VueEternalLoading <VueEternalLoading
v-if="query.type === 'playlist'" v-if="query.type === 'playlist'"
:load="search_playlists_next" :load="search_playlists_next"
@ -249,7 +230,6 @@ import ListItemAlbumSpotify from '@/components/ListItemAlbumSpotify.vue'
import ListItemArtistSpotify from '@/components/ListItemArtistSpotify.vue' import ListItemArtistSpotify from '@/components/ListItemArtistSpotify.vue'
import ListItemPlaylistSpotify from '@/components/ListItemPlaylistSpotify.vue' import ListItemPlaylistSpotify from '@/components/ListItemPlaylistSpotify.vue'
import ListItemTrackSpotify from '@/components/ListItemTrackSpotify.vue' import ListItemTrackSpotify from '@/components/ListItemTrackSpotify.vue'
import ModalDialogTrackSpotify from '@/components/ModalDialogTrackSpotify.vue'
import SpotifyWebApi from 'spotify-web-api-js' import SpotifyWebApi from 'spotify-web-api-js'
import TabsSearch from '@/components/TabsSearch.vue' import TabsSearch from '@/components/TabsSearch.vue'
import { VueEternalLoading } from '@ts-pro/vue-eternal-loading' import { VueEternalLoading } from '@ts-pro/vue-eternal-loading'
@ -266,7 +246,6 @@ export default {
ListItemArtistSpotify, ListItemArtistSpotify,
ListItemPlaylistSpotify, ListItemPlaylistSpotify,
ListItemTrackSpotify, ListItemTrackSpotify,
ModalDialogTrackSpotify,
TabsSearch, TabsSearch,
VueEternalLoading VueEternalLoading
}, },
@ -279,8 +258,6 @@ export default {
query: {}, query: {},
search_param: {}, search_param: {},
search_query: '', search_query: '',
selected_track: {},
show_track_details_modal: false,
tracks: { items: [], total: 0 }, tracks: { items: [], total: 0 },
validSearchTypes: ['track', 'artist', 'album', 'playlist'] validSearchTypes: ['track', 'artist', 'album', 'playlist']
} }
@ -335,10 +312,6 @@ export default {
} }
}) })
}, },
open_track_dialog(track) {
this.selected_track = track
this.show_track_details_modal = true
},
reset() { reset() {
this.tracks = { items: [], total: 0 } this.tracks = { items: [], total: 0 }
this.artists = { items: [], total: 0 } this.artists = { items: [], total: 0 }