mirror of
https://github.com/koel/koel
synced 2024-11-10 06:34:14 +00:00
feat: only show batch download options if supported
This commit is contained in:
parent
e948782b8b
commit
b79bfb0472
12 changed files with 37 additions and 19 deletions
|
@ -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')),
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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!)
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -35,6 +35,7 @@ class InitialDataTest extends TestCase
|
|||
'customer_email',
|
||||
'product_id',
|
||||
],
|
||||
'supports_batch_downloading',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue