2022-04-15 14:24:30 +00:00
|
|
|
<template>
|
2022-07-08 14:53:04 +00:00
|
|
|
<div
|
|
|
|
class="track-list-item"
|
2022-06-10 10:47:46 +00:00
|
|
|
:class="{ active, available: matchedSong }"
|
|
|
|
:title="tooltip"
|
|
|
|
tabindex="0"
|
|
|
|
@click="play"
|
|
|
|
>
|
2022-04-15 14:24:30 +00:00
|
|
|
<span class="title">{{ track.title }}</span>
|
2022-06-10 10:47:46 +00:00
|
|
|
<AppleMusicButton v-if="useAppleMusic && !matchedSong" :url="iTunesUrl"/>
|
|
|
|
<span class="length">{{ fmtLength }}</span>
|
2022-07-08 14:53:04 +00:00
|
|
|
</div>
|
2022-04-15 14:24:30 +00:00
|
|
|
</template>
|
|
|
|
|
2022-04-15 17:00:08 +00:00
|
|
|
<script lang="ts" setup>
|
2022-09-30 06:56:29 +00:00
|
|
|
import { computed, defineAsyncComponent, Ref, toRefs } from 'vue'
|
2022-04-30 14:05:02 +00:00
|
|
|
import { queueStore, songStore } from '@/stores'
|
2022-04-24 08:50:45 +00:00
|
|
|
import { authService, playbackService } from '@/services'
|
2022-04-30 14:05:02 +00:00
|
|
|
import { useThirdPartyServices } from '@/composables'
|
2022-07-20 08:00:02 +00:00
|
|
|
import { requireInjection, secondsToHis } from '@/utils'
|
2022-06-10 10:47:46 +00:00
|
|
|
import { SongsKey } from '@/symbols'
|
2022-04-15 14:24:30 +00:00
|
|
|
|
2022-05-06 08:44:10 +00:00
|
|
|
const AppleMusicButton = defineAsyncComponent(() => import('@/components/ui/AppleMusicButton.vue'))
|
|
|
|
|
2022-07-08 14:53:04 +00:00
|
|
|
const props = defineProps<{ album: Album, track: AlbumTrack }>()
|
|
|
|
const { album, track } = toRefs(props)
|
2022-04-15 14:24:30 +00:00
|
|
|
|
2022-05-06 08:44:10 +00:00
|
|
|
const { useAppleMusic } = useThirdPartyServices()
|
2022-04-15 14:24:30 +00:00
|
|
|
|
2022-09-30 06:56:29 +00:00
|
|
|
const songsToMatchAgainst = requireInjection<Ref<Song[]>>(SongsKey)
|
2022-06-10 10:47:46 +00:00
|
|
|
|
|
|
|
const matchedSong = computed(() => songStore.match(track.value.title, songsToMatchAgainst.value))
|
|
|
|
const tooltip = computed(() => matchedSong.value ? 'Click to play' : '')
|
|
|
|
const fmtLength = computed(() => secondsToHis(track.value.length))
|
|
|
|
|
|
|
|
const active = computed(() => matchedSong.value && matchedSong.value.playback_state !== 'Stopped')
|
2022-04-15 14:24:30 +00:00
|
|
|
|
2022-04-15 17:00:08 +00:00
|
|
|
const iTunesUrl = computed(() => {
|
2022-04-24 08:50:45 +00:00
|
|
|
return `${window.BASE_URL}itunes/song/${album.value.id}?q=${encodeURIComponent(track.value.title)}&api_token=${authService.getToken()}`
|
2022-04-15 17:00:08 +00:00
|
|
|
})
|
2022-04-15 14:24:30 +00:00
|
|
|
|
2022-04-15 17:00:08 +00:00
|
|
|
const play = () => {
|
2022-06-10 10:47:46 +00:00
|
|
|
if (matchedSong.value) {
|
|
|
|
queueStore.queueIfNotQueued(matchedSong.value)
|
|
|
|
playbackService.play(matchedSong.value)
|
2022-04-15 14:24:30 +00:00
|
|
|
}
|
2022-04-15 17:00:08 +00:00
|
|
|
}
|
2022-04-15 14:24:30 +00:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
2022-07-08 14:53:04 +00:00
|
|
|
.track-list-item {
|
|
|
|
display: flex;
|
|
|
|
flex: 1;
|
|
|
|
gap: 4px;
|
2022-05-06 08:44:10 +00:00
|
|
|
|
2022-06-10 10:47:46 +00:00
|
|
|
&:focus, &.active {
|
2022-04-15 14:24:30 +00:00
|
|
|
span.title {
|
|
|
|
color: var(--color-highlight);
|
|
|
|
}
|
|
|
|
}
|
2022-07-08 14:53:04 +00:00
|
|
|
|
|
|
|
.title {
|
|
|
|
flex: 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
.length {
|
|
|
|
flex: 0 0 44px;
|
|
|
|
text-align: right;
|
|
|
|
opacity: .5;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.available {
|
|
|
|
color: var(--color-text-primary);
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
color: var(--color-highlight);
|
|
|
|
}
|
|
|
|
}
|
2022-04-15 14:24:30 +00:00
|
|
|
}
|
|
|
|
</style>
|