mirror of
https://github.com/koel/koel
synced 2024-11-10 14:44:13 +00:00
feat: decouple YouTube from Song
This commit is contained in:
parent
1e6358fd11
commit
2b09e1e855
9 changed files with 26 additions and 37 deletions
|
@ -11,12 +11,7 @@ let song: Song
|
|||
|
||||
new class extends UnitTestCase {
|
||||
private renderComponent () {
|
||||
song = factory<Song>('song', {
|
||||
youtube: {
|
||||
items: factory<YouTubeVideo>('video', 5),
|
||||
nextPageToken: 'f00'
|
||||
}
|
||||
})
|
||||
song = factory<Song>('song')
|
||||
|
||||
return this.render(YouTubeVideoList, {
|
||||
props: {
|
||||
|
@ -37,7 +32,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('loads more videos', async () => {
|
||||
const mock = this.mock(youTubeService, 'searchVideosRelatedToSong').mockResolvedValue({
|
||||
const mock = this.mock(youTubeService, 'searchVideosBySong').mockResolvedValue({
|
||||
nextPageToken: 'b4r',
|
||||
items: factory<YouTubeVideo>('video', 5)
|
||||
})
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defineAsyncComponent, ref, toRefs, watchEffect } from 'vue'
|
||||
import { defineAsyncComponent, ref, toRefs, watch } from 'vue'
|
||||
import { youTubeService } from '@/services'
|
||||
|
||||
const Btn = defineAsyncComponent(() => import('@/components/ui/Btn.vue'))
|
||||
|
@ -26,17 +26,15 @@ const { song } = toRefs(props)
|
|||
const loading = ref(false)
|
||||
const videos = ref<YouTubeVideo[]>([])
|
||||
|
||||
let nextPageToken = ''
|
||||
|
||||
const loadMore = async () => {
|
||||
loading.value = true
|
||||
|
||||
try {
|
||||
song.value.youtube = song.value.youtube || { nextPageToken: '', items: [] }
|
||||
|
||||
const result = await youTubeService.searchVideosRelatedToSong(song.value, song.value.youtube.nextPageToken!)
|
||||
song.value.youtube.nextPageToken = result.nextPageToken
|
||||
song.value.youtube.items.push(...result.items as YouTubeVideo[])
|
||||
|
||||
videos.value = song.value.youtube.items
|
||||
const result = await youTubeService.searchVideosBySong(song.value, nextPageToken)
|
||||
nextPageToken = result.nextPageToken
|
||||
videos.value.push(...result.items)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
} finally {
|
||||
|
@ -44,13 +42,11 @@ const loadMore = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
videos.value = song.value.youtube?.items || []
|
||||
|
||||
if (videos.value.length === 0) {
|
||||
loadMore()
|
||||
}
|
||||
})
|
||||
watch(song, () => {
|
||||
videos.value = []
|
||||
nextPageToken = ''
|
||||
loadMore()
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -7,3 +7,4 @@ export * from './socketService'
|
|||
export * from './audioService'
|
||||
export * from './uploadService'
|
||||
export * from './authService'
|
||||
export * from './Cache'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { httpService } from '@/services'
|
||||
import { Cache, httpService } from '@/services'
|
||||
import { eventBus } from '@/utils'
|
||||
import router from '@/router'
|
||||
|
||||
|
@ -8,8 +8,13 @@ interface YouTubeSearchResult {
|
|||
}
|
||||
|
||||
export const youTubeService = {
|
||||
searchVideosRelatedToSong: async (song: Song, nextPageToken: string) => {
|
||||
return await httpService.get<YouTubeSearchResult>(`youtube/search/song/${song.id}?pageToken=${nextPageToken}`)
|
||||
searchVideosBySong: async (song: Song, nextPageToken: string) => {
|
||||
return await Cache.resolve<YouTubeSearchResult>(
|
||||
['youtube.search', song.id, nextPageToken],
|
||||
async () => await httpService.get<YouTubeSearchResult>(
|
||||
`youtube/search/song/${song.id}?pageToken=${nextPageToken}`
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
play: (video: YouTubeVideo): void => {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { reactive } from 'vue'
|
||||
import { difference, orderBy, take, union } from 'lodash'
|
||||
import { httpService } from '@/services'
|
||||
import { Cache, httpService } from '@/services'
|
||||
import { arrayify } from '@/utils'
|
||||
import { songStore } from '@/stores'
|
||||
import { Cache } from '@/services/cache'
|
||||
|
||||
const UNKNOWN_ALBUM_ID = 1
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { reactive } from 'vue'
|
||||
import { difference, orderBy, take, union } from 'lodash'
|
||||
import { httpService } from '@/services'
|
||||
import { Cache, httpService } from '@/services'
|
||||
import { arrayify } from '@/utils'
|
||||
import { Cache } from '@/services/cache'
|
||||
|
||||
const UNKNOWN_ARTIST_ID = 1
|
||||
const VARIOUS_ARTISTS_ID = 2
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { difference, orderBy, union } from 'lodash'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
import { httpService } from '@/services'
|
||||
import { Cache, httpService } from '@/services'
|
||||
import models from '@/config/smart-playlist/models'
|
||||
import operators from '@/config/smart-playlist/operators'
|
||||
import { Cache } from '@/services/cache'
|
||||
|
||||
export const playlistStore = {
|
||||
state: reactive({
|
||||
|
|
|
@ -3,9 +3,8 @@ import slugify from 'slugify'
|
|||
import { orderBy, take, union } from 'lodash'
|
||||
import { reactive, watch } from 'vue'
|
||||
import { arrayify, eventBus, secondsToHis, use } from '@/utils'
|
||||
import { authService, httpService } from '@/services'
|
||||
import { authService, Cache, httpService } from '@/services'
|
||||
import { albumStore, artistStore, commonStore, overviewStore, preferenceStore } from '@/stores'
|
||||
import { Cache } from '@/services/cache'
|
||||
|
||||
interface BroadcastSongData {
|
||||
song: {
|
||||
|
|
4
resources/assets/js/types.d.ts
vendored
4
resources/assets/js/types.d.ts
vendored
|
@ -185,10 +185,6 @@ interface Song {
|
|||
track: number | null
|
||||
disc: number | null
|
||||
lyrics: string
|
||||
youtube?: {
|
||||
items: YouTubeVideo[]
|
||||
nextPageToken: string
|
||||
},
|
||||
play_count_registered?: boolean
|
||||
preloaded?: boolean
|
||||
playback_state?: PlaybackState
|
||||
|
|
Loading…
Reference in a new issue