fix: buggy Spotify integration (#1731)

This fixes a bug with Spotify integration that occurs if an installation isn't connected to Last.fm. Closing #1730 and #1653.
This commit is contained in:
Phan An 2023-12-27 12:49:28 +01:00 committed by GitHub
parent 07f3554fe1
commit abb0438c8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 141 additions and 21 deletions

View file

@ -12,6 +12,7 @@ use App\Repositories\SongRepository;
use App\Services\ApplicationInformationService;
use App\Services\ITunesService;
use App\Services\LastfmService;
use App\Services\SpotifyService;
use App\Services\YouTubeService;
use Illuminate\Contracts\Auth\Authenticatable;
@ -35,6 +36,7 @@ class DataController extends Controller
'playlist_folders' => PlaylistFolderResource::collection($this->user->playlist_folders),
'current_user' => UserResource::make($this->user, true),
'use_last_fm' => LastfmService::used(),
'use_spotify' => SpotifyService::enabled(),
'use_you_tube' => YouTubeService::enabled(),
'use_i_tunes' => $this->iTunesService->used(),
'allow_download' => config('koel.download.allow'),

View file

@ -39,6 +39,7 @@ import { mediaInfoService, playbackService } from '@/services'
import { useRouter, useThirdPartyServices } from '@/composables'
import AlbumThumbnail from '@/components/ui/AlbumArtistThumbnail.vue'
import { defaultCover } from '@/utils'
const TrackList = defineAsyncComponent(() => import('@/components/album/AlbumTrackList.vue'))
@ -46,7 +47,7 @@ const props = withDefaults(defineProps<{ album: Album, mode?: MediaInfoDisplayMo
const { album, mode } = toRefs(props)
const { go } = useRouter()
const { useLastfm } = useThirdPartyServices()
const { useLastfm, useSpotify } = useThirdPartyServices()
const info = ref<AlbumInfo | null>(null)
const showingFullWiki = ref(false)
@ -54,7 +55,10 @@ const showingFullWiki = ref(false)
watch(album, async () => {
showingFullWiki.value = false
info.value = null
useLastfm.value && (info.value = await mediaInfoService.fetchForAlbum(album.value))
if (useLastfm.value || useSpotify.value) {
info.value = await mediaInfoService.fetchForAlbum(album.value)
}
}, { immediate: true })
const showSummary = computed(() => mode.value !== 'full' && !showingFullWiki.value)

View file

@ -42,7 +42,7 @@ const props = withDefaults(defineProps<{ artist: Artist, mode?: MediaInfoDisplay
const { artist, mode } = toRefs(props)
const { go } = useRouter()
const { useLastfm } = useThirdPartyServices()
const { useLastfm, useSpotify } = useThirdPartyServices()
const info = ref<ArtistInfo | null>(null)
const showingFullBio = ref(false)
@ -50,7 +50,10 @@ const showingFullBio = ref(false)
watch(artist, async () => {
showingFullBio.value = false
info.value = null
useLastfm.value && (info.value = await mediaInfoService.fetchForArtist(artist.value))
if (useLastfm.value || useSpotify.value) {
info.value = await mediaInfoService.fetchForArtist(artist.value)
}
}, { immediate: true })
const showSummary = computed(() => mode.value !== 'full' && !showingFullBio.value)

View file

@ -1,15 +1,18 @@
<template>
<section class="text-secondary">
<h1>Last.fm Integration</h1>
<h1>
<span class="lastfm-icon">
<Icon :icon="faLastfm" />
</span>
Last.fm Integration
</h1>
<div v-if="useLastfm" data-testid="lastfm-integrated">
<p>
This installation of Koel integrates with Last.fm.
<span v-if="connected">
It appears that you have connected your Last.fm account as well Perfect!
</span>
<span v-else>It appears that you havent connected to your Last.fm account though.</span>
<p>Last.fm integration is enabled. Koel will attempt to retrieve album and artist information from Last.fm.</p>
<p v-if="connected">
It appears that you have connected your Last.fm account as well Perfect!
</p>
<p v-else>You can also connect your Last.fm account here.</p>
<p>
Connecting Koel and your Last.fm account enables such exciting features as
<a
@ -21,7 +24,6 @@
</p>
<div class="buttons">
<Btn class="connect" @click.prevent="connect">
<Icon :icon="faLastfm" />
{{ connected ? 'Reconnect' : 'Connect' }}
</Btn>
@ -31,7 +33,7 @@
<div v-else data-testid="lastfm-not-integrated">
<p>
This installation of Koel has no Last.fm integration.
Last.fm integration is not enabled on this installation of Koel.
<span v-if="isAdmin" data-testid="lastfm-admin-instruction">
Visit
<a href="https://docs.koel.dev/3rd-party.html#last-fm" class="text-highlight" target="_blank">Koels Wiki</a>
@ -77,6 +79,11 @@ const disconnect = async () => {
</script>
<style lang="scss" scoped>
.lastfm-icon {
color: #d31f27; // Last.fm red
margin-right: .4rem;
}
.buttons {
margin-top: 1.25rem;
@ -85,7 +92,7 @@ const disconnect = async () => {
}
.connect {
background: #d31f27; // Last.fm color yo!
background: #d31f27;
}
}
</style>

View file

@ -0,0 +1,23 @@
import { expect, it } from 'vitest'
import UnitTestCase from '@/__tests__/UnitTestCase'
import { commonStore } from '@/stores'
import SpotifyIntegration from './SpotifyIntegration.vue'
new class extends UnitTestCase {
protected test () {
it.each<[boolean, boolean]>([[false, false], [false, true], [true, false], [true, true]])
('renders proper content with Spotify integration status %s, current user admin status %s',
(useSpotify, isAdmin) => {
commonStore.state.use_spotify = useSpotify
if (isAdmin) {
this.actingAsAdmin()
} else {
this.actingAs()
}
expect(this.render(SpotifyIntegration).html()).toMatchSnapshot();
}
)
}
}

View file

@ -0,0 +1,45 @@
<template>
<section class="text-secondary">
<h1>
<span class="spotify-icon">
<Icon :icon="faSpotify" />
</span>
Spotify Integration
</h1>
<div v-if="useSpotify">
<p>
Spotify integration is enabled.
Koel will attempt to retrieve album arts and artist images from Spotify when a song is played, if needed.
</p>
</div>
<div v-else>
<p>
Spotify integration is not enabled.
<span v-if="isAdmin" data-testid="spotify-admin-instruction">
Visit
<a href="https://docs.koel.dev/3rd-party.html#spotify" class="text-highlight" target="_blank">Koels Wiki</a>
for a quick how-to.
</span>
<span v-else data-testid="spotify-user-instruction">
Try politely asking an administrator to enable it.
</span>
</p>
</div>
</section>
</template>
<script lang="ts" setup>
import { faSpotify } from '@fortawesome/free-brands-svg-icons'
import { useAuthorization, useThirdPartyServices } from '@/composables';
const { currentUser, isAdmin } = useAuthorization();
const { useSpotify } = useThirdPartyServices();
</script>
<style scoped lang="scss">
.spotify-icon {
margin-right: .4rem;
color: #1db954; // Spotify green
}
</style>

View file

@ -0,0 +1,37 @@
// Vitest Snapshot v1
exports[`renders proper content with Spotify integration status false, current user admin status false 1`] = `
<section data-v-49dda1f9="" class="text-secondary">
<h1 data-v-49dda1f9=""><span data-v-49dda1f9="" class="spotify-icon"><br data-v-49dda1f9="" data-testid="Icon" icon="[object Object]"></span> Spotify Integration </h1>
<div data-v-49dda1f9="">
<p data-v-49dda1f9=""> Spotify integration is not enabled. <span data-v-49dda1f9="" data-testid="spotify-user-instruction"> Try politely asking an administrator to enable it. </span></p>
</div>
</section>
`;
exports[`renders proper content with Spotify integration status false, current user admin status true 1`] = `
<section data-v-49dda1f9="" class="text-secondary">
<h1 data-v-49dda1f9=""><span data-v-49dda1f9="" class="spotify-icon"><br data-v-49dda1f9="" data-testid="Icon" icon="[object Object]"></span> Spotify Integration </h1>
<div data-v-49dda1f9="">
<p data-v-49dda1f9=""> Spotify integration is not enabled. <span data-v-49dda1f9="" data-testid="spotify-admin-instruction"> Visit <a data-v-49dda1f9="" href="https://docs.koel.dev/3rd-party.html#spotify" class="text-highlight" target="_blank">Koels Wiki</a> for a quick how-to. </span></p>
</div>
</section>
`;
exports[`renders proper content with Spotify integration status true, current user admin status false 1`] = `
<section data-v-49dda1f9="" class="text-secondary">
<h1 data-v-49dda1f9=""><span data-v-49dda1f9="" class="spotify-icon"><br data-v-49dda1f9="" data-testid="Icon" icon="[object Object]"></span> Spotify Integration </h1>
<div data-v-49dda1f9="">
<p data-v-49dda1f9=""> Spotify integration is enabled. Koel will attempt to retrieve album arts and artist images from Spotify when a song is played, if needed. </p>
</div>
</section>
`;
exports[`renders proper content with Spotify integration status true, current user admin status true 1`] = `
<section data-v-49dda1f9="" class="text-secondary">
<h1 data-v-49dda1f9=""><span data-v-49dda1f9="" class="spotify-icon"><br data-v-49dda1f9="" data-testid="Icon" icon="[object Object]"></span> Spotify Integration </h1>
<div data-v-49dda1f9="">
<p data-v-49dda1f9=""> Spotify integration is enabled. Koel will attempt to retrieve album arts and artist images from Spotify when a song is played, if needed. </p>
</div>
</section>
`;

View file

@ -6,6 +6,7 @@
<ProfileForm />
<ThemeList />
<PreferencesForm />
<SpotifyIntegration />
<LastfmIntegration />
</div>
</section>
@ -14,6 +15,7 @@
<script lang="ts" setup>
import ScreenHeader from '@/components/ui/ScreenHeader.vue'
import ProfileForm from '@/components/profile-preferences/ProfileForm.vue'
import SpotifyIntegration from '@/components/profile-preferences/SpotifyIntegration.vue'
import LastfmIntegration from '@/components/profile-preferences/LastfmIntegration.vue'
import PreferencesForm from '@/components/profile-preferences/PreferencesForm.vue'
import ThemeList from '@/components/profile-preferences/ThemeList.vue'

View file

@ -2,13 +2,10 @@ import { toRef } from 'vue'
import { commonStore } from '@/stores'
export const useThirdPartyServices = () => {
const useLastfm = toRef(commonStore.state, 'use_last_fm')
const useYouTube = toRef(commonStore.state, 'use_you_tube')
const useAppleMusic = toRef(commonStore.state, 'use_i_tunes')
return {
useLastfm,
useYouTube,
useAppleMusic
useLastfm: toRef(commonStore.state, 'use_last_fm'),
useYouTube: toRef(commonStore.state, 'use_you_tube'),
useAppleMusic: toRef(commonStore.state, 'use_i_tunes'),
useSpotify: toRef(commonStore.state, 'use_spotify')
}
}