feat: split and rename Apple Music button component

This commit is contained in:
Phan An 2022-05-06 10:44:10 +02:00
parent 4ddb6c6a44
commit e51d8de337
No known key found for this signature in database
GPG key ID: A81E4477F0BB6FDC
7 changed files with 83 additions and 63 deletions

View file

@ -3,24 +3,24 @@
<h1 class="name">
<span>{{ album.name }}</span>
<button :title="`Shuffle all songs in ${album.name}`" class="shuffle control" @click.prevent="shuffleAll">
<i class="fa fa-random" />
<i class="fa fa-random"/>
</button>
</h1>
<main>
<AlbumThumbnail :entity="album" />
<AlbumThumbnail :entity="album"/>
<template v-if="album.info">
<div v-if="album.info?.wiki?.summary" class="wiki">
<div v-if="showSummary" class="summary" v-html="album.info?.wiki?.summary" />
<div v-if="showFull" class="full" v-html="album.info?.wiki?.full" />
<div v-if="showSummary" class="summary" v-html="album.info?.wiki?.summary"/>
<div v-if="showFull" class="full" v-html="album.info?.wiki?.full"/>
<button v-if="showSummary" class="more" data-testid="more-btn" @click.prevent="showingFullWiki = true">
Full Wiki
</button>
</div>
<TrackList v-if="album.info?.tracks?.length" :album="album" data-testid="album-info-tracks" />
<TrackList v-if="album.info?.tracks?.length" :album="album" data-testid="album-info-tracks"/>
<footer>Data &copy; <a :href="album.info?.url" rel="noopener" target="_blank">Last.fm</a></footer>
</template>
@ -35,9 +35,9 @@ import { computed, defineAsyncComponent, ref, toRefs, watch } from 'vue'
const TrackList = defineAsyncComponent(() => import('./AlbumTrackList.vue'))
const AlbumThumbnail = defineAsyncComponent(() => import('@/components/ui/AlbumArtistThumbnail.vue'))
type DisplayMode = 'sidebar' | 'full'
type DisplayMode = 'aside' | 'full'
const props = withDefaults(defineProps<{ album: Album, mode?: DisplayMode }>(), { mode: 'sidebar' })
const props = withDefaults(defineProps<{ album: Album, mode?: DisplayMode }>(), { mode: 'aside' })
const { album, mode } = toRefs(props)
const showingFullWiki = ref(false)

View file

@ -1,29 +1,23 @@
<template>
<li :class="{ available: song }" :title="tooltip" tabindex="0" @click="play">
<span class="title">{{ track.title }}</span>
<a
v-if="useiTunes && !song"
:href="iTunesUrl"
class="view-on-itunes"
target="_blank"
title="View on iTunes"
>
iTunes
</a>
<AppleMusicButton v-if="useAppleMusic && !song" :url="iTunesUrl"/>
<span class="length">{{ track.fmtLength }}</span>
</li>
</template>
<script lang="ts" setup>
import { computed, toRefs } from 'vue'
import { computed, defineAsyncComponent, toRefs } from 'vue'
import { queueStore, songStore } from '@/stores'
import { authService, playbackService } from '@/services'
import { useThirdPartyServices } from '@/composables'
const AppleMusicButton = defineAsyncComponent(() => import('@/components/ui/AppleMusicButton.vue'))
const props = defineProps<{ album: Album, track: AlbumTrack }>()
const { album, track } = toRefs(props)
const { useiTunes } = useThirdPartyServices()
const { useAppleMusic } = useThirdPartyServices()
const song = computed(() => songStore.guess(track.value.title, album.value))
const tooltip = computed(() => song.value ? 'Click to play' : '')
@ -42,31 +36,14 @@ const play = () => {
<style lang="scss" scoped>
li {
span.title {
margin-right: 5px;
}
&:focus {
span.title {
color: var(--color-highlight);
}
}
a.view-on-itunes {
display: inline-block;
border-radius: 3px;
font-size: .8rem;
padding: 0 5px;
color: var(--color-text-primary);
background: rgba(255, 255, 255, .1);
height: 20px;
line-height: 20px;
margin-left: 4px;
&:hover, &:focus {
background: linear-gradient(27deg, #fe5c52 0%, #c74bd5 50%, #2daaff 100%);
color: var(--color-text-primary);
}
&:active {
box-shadow: inset 0px 5px 5px -5px #000;
}
}
}
</style>

View file

@ -1,19 +1,19 @@
<template>
<article class="artist-info" :class="mode" data-testid="artist-info">
<article :class="mode" class="artist-info" data-testid="artist-info">
<h1 class="name">
<span>{{ artist.name }}</span>
<button :title="`Shuffle all songs by ${artist.name}`" class="shuffle control" @click.prevent="shuffleAll">
<i class="fa fa-random" />
<i class="fa fa-random"/>
</button>
</h1>
<main v-if="artist.info">
<ArtistThumbnail :entity="artist" />
<ArtistThumbnail :entity="artist"/>
<template v-if="artist.info">
<div v-if="artist.info?.bio?.summary" class="bio">
<div v-if="showSummary" class="summary" v-html="artist.info?.bio?.summary" />
<div v-if="showFull" class="full" v-html="artist.info?.bio?.full" />
<div v-if="showSummary" class="summary" v-html="artist.info?.bio?.summary"/>
<div v-if="showFull" class="full" v-html="artist.info?.bio?.full"/>
<button v-show="showSummary" class="more" data-testid="more-btn" @click.prevent="showingFullBio = true">
Full Bio
@ -33,11 +33,11 @@
import { computed, defineAsyncComponent, ref, toRefs, watch } from 'vue'
import { playbackService } from '@/services'
type DisplayMode = 'sidebar' | 'full'
type DisplayMode = 'aside' | 'full'
const ArtistThumbnail = defineAsyncComponent(() => import('@/components/ui/AlbumArtistThumbnail.vue'))
const props = withDefaults(defineProps<{ artist: Artist, mode?: DisplayMode }>(), { mode: 'sidebar' })
const props = withDefaults(defineProps<{ artist: Artist, mode?: DisplayMode }>(), { mode: 'aside' })
const { artist, mode } = toRefs(props)
const showingFullBio = ref(false)

View file

@ -50,7 +50,7 @@
role="tabpanel"
tabindex="0"
>
<lyrics-pane :song="song"/>
<LyricsPane :song="song"/>
</div>
<div
@ -60,7 +60,7 @@
role="tabpanel"
tabindex="0"
>
<ArtistInfo v-if="artist" :artist="artist" mode="sidebar"/>
<ArtistInfo v-if="artist" :artist="artist" mode="aside"/>
</div>
<div
@ -70,7 +70,7 @@
role="tabpanel"
tabindex="0"
>
<AlbumInfo v-if="album" :album="album" mode="sidebar"/>
<AlbumInfo v-if="album" :album="album" mode="aside"/>
</div>
<div
@ -91,7 +91,7 @@
import isMobile from 'ismobilejs'
import { computed, defineAsyncComponent, ref, toRef, watch } from 'vue'
import { $, eventBus } from '@/utils'
import { preferenceStore as preferences, songStore } from '@/stores'
import { preferenceStore as preferences } from '@/stores'
import { songInfo } from '@/services'
import { useThirdPartyServices } from '@/composables'
@ -120,11 +120,6 @@ watch(showing, (showingExtraPanel) => {
}
})
const resetState = () => {
currentTab.value = defaultTab
song.value = songStore.stub
}
const fetchSongInfo = async (_song: Song) => {
try {
song.value = await songInfo.fetch(_song)

View file

@ -0,0 +1,48 @@
<template>
<a :href="url" target="_blank" title="Preview and buy this song on Apple Music">
<svg
class="web-navigation__logo-vector"
height="10"
role="presentation"
viewBox="0 0 83 20"
width="41" xmlns="http://www.w3.org/2000/svg"
>
<path
d="M34.752 19.746V6.243h-.088l-5.433 13.503h-2.074L21.711 6.243h-.087v13.503h-2.548V1.399h3.235l5.833 14.621h.1L34.064 1.4h3.248v18.347h-2.56zm16.649 0h-2.586v-2.263h-.062c-.725 1.602-2.061 2.504-4.072 2.504-2.86 0-4.61-1.894-4.61-4.958V6.37h2.698v8.125c0 2.034.95 3.127 2.81 3.127 1.95 0 3.124-1.373 3.124-3.458V6.37H51.4v13.376zm7.394-13.618c3.06 0 5.046 1.73 5.134 4.196h-2.536c-.15-1.296-1.087-2.11-2.598-2.11-1.462 0-2.436.724-2.436 1.793 0 .839.6 1.41 2.023 1.741l2.136.496c2.686.636 3.71 1.704 3.71 3.636 0 2.442-2.236 4.12-5.333 4.12-3.285 0-5.26-1.64-5.509-4.183h2.673c.25 1.398 1.187 2.085 2.836 2.085 1.623 0 2.623-.687 2.623-1.78 0-.865-.487-1.373-1.924-1.704l-2.136-.508c-2.498-.585-3.735-1.806-3.735-3.75 0-2.391 2.049-4.032 5.072-4.032zM66.1 2.836c0-.878.7-1.577 1.561-1.577.862 0 1.55.7 1.55 1.577 0 .864-.688 1.576-1.55 1.576a1.573 1.573 0 0 1-1.56-1.576zm.212 3.534h2.698v13.376h-2.698V6.37zm14.089 4.603c-.275-1.424-1.324-2.556-3.085-2.556-2.086 0-3.46 1.767-3.46 4.64 0 2.938 1.386 4.642 3.485 4.642 1.66 0 2.748-.928 3.06-2.48H83C82.713 18.067 80.477 20 77.317 20c-3.76 0-6.208-2.62-6.208-6.942 0-4.247 2.448-6.93 6.183-6.93 3.385 0 5.446 2.213 5.683 4.845h-2.573zM10.824 3.189c-.698.834-1.805 1.496-2.913 1.398-.145-1.128.41-2.33 1.036-3.065C9.644.662 10.848.05 11.835 0c.121 1.178-.336 2.33-1.01 3.19zm.999 1.619c.624.049 2.425.244 3.578 1.98-.096.074-2.137 1.272-2.113 3.79.024 3.01 2.593 4.012 2.617 4.037-.024.074-.407 1.419-1.344 2.812-.817 1.224-1.657 2.422-3.002 2.447-1.297.024-1.73-.783-3.218-.783-1.489 0-1.97.758-3.194.807-1.297.048-2.28-1.297-3.097-2.52C.368 14.908-.904 10.408.825 7.375c.84-1.516 2.377-2.47 4.034-2.495 1.273-.023 2.45.857 3.218.857.769 0 2.137-1.027 3.746-.93z"
fill-rule="nonzero"
stroke="none"
stroke-width="1"
></path>
</svg>
</a>
</template>
<script lang="ts" setup>
import { toRefs } from 'vue'
const props = defineProps({ url: String })
const { url } = toRefs(props)
</script>
<style lang="scss" scoped>
a {
display: inline-block;
border-radius: 3px;
padding: 0 5px;
background: rgba(255, 255, 255, .1);
height: 20px;
line-height: 20px;
svg {
fill: var(--color-text-primary)
}
&:hover, &:focus {
background: linear-gradient(27deg, #fe5c52 0%, #c74bd5 50%, #2daaff 100%);
}
&:active {
box-shadow: inset 0px 5px 5px -5px #000;
}
}
</style>

View file

@ -4,11 +4,11 @@ import { commonStore } from '@/stores'
export const useThirdPartyServices = () => {
const useLastfm = toRef(commonStore.state, 'useLastfm')
const useYouTube = toRef(commonStore.state, 'useYouTube')
const useiTunes = toRef(commonStore.state, 'useiTunes')
const useAppleMusic = toRef(commonStore.state, 'useiTunes')
return {
useLastfm,
useYouTube,
useiTunes
useAppleMusic
}
}

View file

@ -3,16 +3,16 @@ import { reactive } from 'vue'
import { httpService } from '@/services'
import {
userStore,
preferenceStore,
artistStore,
albumStore,
songStore,
artistStore,
playlistStore,
recentlyPlayedStore,
preferenceStore,
queueStore,
recentlyPlayedStore,
settingStore,
themeStore
songStore,
themeStore,
userStore
} from '.'
interface CommonStoreState {