feat: only show batch download options if supported

This commit is contained in:
Phan An 2024-08-29 19:54:58 +02:00
parent e948782b8b
commit b79bfb0472
12 changed files with 37 additions and 19 deletions

View file

@ -45,6 +45,7 @@ class FetchInitialDataController extends Controller
'uses_you_tube' => YouTubeService::enabled(),
'uses_i_tunes' => $iTunesService->used(),
'allows_download' => config('koel.download.allow'),
'supports_batch_downloading' => extension_loaded('zip'),
'media_path_set' => (bool) $settingRepository->getByKey('media_path'),
'supports_transcoding' => config('koel.streaming.ffmpeg_path')
&& is_executable(config('koel.streaming.ffmpeg_path')),

View file

@ -55,6 +55,7 @@ export default abstract class UnitTestCase {
commonStore.state.song_length = 10
commonStore.state.allows_download = true
commonStore.state.uses_i_tunes = true
commonStore.state.supports_batch_downloading = true
cb && cb()
})
}

View file

@ -45,6 +45,7 @@ const { startDragging } = useDraggable('album')
const props = withDefaults(defineProps<{ album: Album, layout?: ArtistAlbumCardLayout }>(), { layout: 'full' })
const { album, layout } = toRefs(props)
// We're not checking for supports_batch_downloading here, as the number of songs on the album is not yet known.
const allowDownload = toRef(commonStore.state, 'allows_download')
const isStandardArtist = computed(() => artistStore.isStandard(album.value.artist_id))

View file

@ -37,6 +37,7 @@ const { startDragging } = useDraggable('artist')
const props = withDefaults(defineProps<{ artist: Artist, layout?: ArtistAlbumCardLayout }>(), { layout: 'full' })
const { artist, layout } = toRefs(props)
// We're not checking for supports_batch_downloading here, as the number of songs by the artist is not yet known.
const allowDownload = toRef(commonStore.state, 'allows_download')
const showing = computed(() => artistStore.isStandard(artist.value))

View file

@ -18,7 +18,7 @@
<span>{{ duration }}</span>
<a
v-if="allowDownload"
v-if="downloadable"
class="download"
role="button"
title="Download all songs in album"
@ -125,6 +125,7 @@ const {
songList,
showingControls,
isPhone,
downloadable,
duration,
context,
sort,
@ -138,7 +139,6 @@ const {
const { SongListControls, config } = useSongListControls('Album')
const useLastfm = toRef(commonStore.state, 'uses_last_fm')
const allowDownload = toRef(commonStore.state, 'allows_download')
const isNormalArtist = computed(() => {
if (!album.value) return true

View file

@ -17,7 +17,7 @@
<span>{{ duration }}</span>
<a
v-if="allowDownload"
v-if="downloadable"
class="download"
role="button"
title="Download all songs by this artist"
@ -122,6 +122,7 @@ const {
isPhone,
context,
duration,
downloadable,
onPressEnter,
playAll,
playSelected,
@ -132,7 +133,6 @@ const {
const { SongListControls, config } = useSongListControls('Artist')
const { useLastfm } = useThirdPartyServices()
const allowDownload = toRef(commonStore.state, 'allows_download')
const albumCount = computed(() => {
const albums = new Set()

View file

@ -14,10 +14,10 @@
<span>{{ duration }}</span>
<a
v-if="allowDownload"
v-if="downloadable"
class="download"
role="button"
title="Download all songs in playlist"
title="Download all favorites"
@click.prevent="download"
>
Download All
@ -64,10 +64,10 @@
import { faHeartBroken } from '@fortawesome/free-solid-svg-icons'
import { faHeart } from '@fortawesome/free-regular-svg-icons'
import { pluralize } from '@/utils'
import { commonStore, favoriteStore } from '@/stores'
import { favoriteStore } from '@/stores'
import { downloadService } from '@/services'
import { useRouter, useSongList, useSongListControls } from '@/composables'
import { nextTick, ref, toRef } from 'vue'
import { ref, toRef } from 'vue'
import ScreenHeader from '@/components/ui/ScreenHeader.vue'
import ScreenEmptyState from '@/components/ui/ScreenEmptyState.vue'
@ -82,6 +82,7 @@ const {
songs,
songList,
duration,
downloadable,
thumbnails,
selectedPlayables,
showingControls,
@ -90,13 +91,11 @@ const {
playAll,
playSelected,
applyFilter,
onScrollBreakpoint,
onScrollBreakpoint
} = useSongList(toRef(favoriteStore.state, 'playables'), { type: 'Favorites' })
const { SongListControls, config } = useSongListControls('Favorites')
const allowDownload = toRef(commonStore.state, 'allows_download')
const download = () => downloadService.fromFavorites()
const removeSelected = () => selectedPlayables.value.length && favoriteStore.unlike(selectedPlayables.value)

View file

@ -16,7 +16,7 @@
<span>{{ pluralize(songs, 'item') }}</span>
<span>{{ duration }}</span>
<a
v-if="allowDownload"
v-if="downloadable"
role="button"
title="Download all songs in playlist"
@click.prevent="download"
@ -73,7 +73,7 @@
<script lang="ts" setup>
import { faFile } from '@fortawesome/free-regular-svg-icons'
import { differenceBy } from 'lodash'
import { ref, toRef, watch } from 'vue'
import { computed, ref, watch } from 'vue'
import { eventBus, pluralize } from '@/utils'
import { commonStore, playlistStore, songStore } from '@/stores'
import { downloadService, playlistCollaborationService } from '@/services'
@ -108,6 +108,7 @@ const {
songs,
songList,
duration,
downloadable,
thumbnails,
selectedPlayables,
showingControls,
@ -126,8 +127,6 @@ const {
const { SongListControls, config: controlsConfig } = useSongListControls('Playlist')
const { removeFromPlaylist } = usePlaylistManagement()
const allowDownload = toRef(commonStore.state, 'allows_download')
const destroy = () => eventBus.emit('PLAYLIST_DELETE', playlist.value!)
const download = () => downloadService.fromPlaylist(playlist.value!)
const editPlaylist = () => eventBus.emit('MODAL_SHOW_EDIT_PLAYLIST_FORM', playlist.value!)

View file

@ -55,7 +55,7 @@
</template>
<li v-if="canEditSongs" @click="openEditForm">Edit</li>
<li v-if="allowsDownload" @click="download">Download</li>
<li v-if="downloadable" @click="download">Download</li>
<li v-if="onlyOneSongSelected && canBeShared" @click="copyUrl">Copy Shareable URL</li>
<template v-if="canBeRemovedFromPlaylist">
@ -105,7 +105,14 @@ const {
} = usePlayableMenuMethods(playables, close)
const playlists = toRef(playlistStore.state, 'playlists')
const allowsDownload = toRef(commonStore.state, 'allows_download')
const downloadable = computed(() => {
if (!commonStore.state.allows_download) return false
// If multiple playables are selected, make sure zip extension is available on the server
return playables.value.length === 1 || commonStore.state.supports_batch_downloading
})
const queue = toRef(queueStore.state, 'playables')
const currentSong = toRef(queueStore, 'current')

View file

@ -2,7 +2,7 @@ import { differenceBy, orderBy, sampleSize, take, throttle } from 'lodash'
import isMobile from 'ismobilejs'
import { computed, provide, reactive, Ref, ref } from 'vue'
import { playbackService } from '@/services'
import { queueStore, songStore } from '@/stores'
import { commonStore, queueStore, songStore } from '@/stores'
import { arrayify, eventBus, getPlayableProp, provideReadonly } from '@/utils'
import { useFuzzySearch, useRouter } from '@/composables'
@ -59,6 +59,12 @@ export const useSongList = (
const duration = computed(() => songStore.getFormattedLength(playables.value))
const downloadable = computed(() => {
if (!commonStore.state.allows_download) return false
if (playables.value.length === 0) return false
return playables.value.length === 1 || commonStore.state.supports_batch_downloading
})
const thumbnails = computed(() => {
const playablesWithCover = playables.value.filter(p => getPlayableProp<string>(p, 'album_cover', 'episode_image'))
@ -161,6 +167,7 @@ export const useSongList = (
songs: playables,
config,
context,
downloadable,
headerLayout,
sortField,
sortOrder,

View file

@ -33,7 +33,8 @@ const initialState = {
songs: [],
current_song: null,
playback_position: 0
} as QueueState
} as QueueState,
supports_batch_downloading: false
}
type CommonStoreState = typeof initialState

View file

@ -35,6 +35,7 @@ class InitialDataTest extends TestCase
'customer_email',
'product_id',
],
'supports_batch_downloading',
]);
}
}