This commit is contained in:
Rhys Tyers 2023-01-09 21:48:56 +00:00
parent ebedaeb3b0
commit 51b3f0d465
8 changed files with 157 additions and 200 deletions

View file

@ -15,29 +15,36 @@
</div>
<div class="flex items-center pt-2">
<button class="h-8 px-4 border border-white border-opacity-20 hover:bg-white hover:bg-opacity-10 rounded-full flex items-center justify-center cursor-pointer focus:outline-none" :class="userIsFinished ? 'text-white text-opacity-40' : ''" @click.stop="playClick">
<button v-if="episode.audioTrack" class="h-8 px-4 border border-white border-opacity-20 hover:bg-white hover:bg-opacity-10 rounded-full flex items-center justify-center cursor-pointer focus:outline-none" :class="userIsFinished ? 'text-white text-opacity-40' : ''" @click.stop="playClick">
<span class="material-icons text-2xl" :class="streamIsPlaying ? '' : 'text-success'">{{ streamIsPlaying ? 'pause' : 'play_arrow' }}</span>
<p class="pl-2 pr-1 text-sm font-semibold">{{ timeRemaining }}</p>
</button>
<button v-if="!episode.id && !isDownloading && !isDownloadQueued && userIsAdminOrUp" class="h-8 px-4 border border-white border-opacity-20 hover:bg-white hover:bg-opacity-10 rounded-full flex items-center justify-center cursor-pointer focus:outline-none" :class="userIsFinished ? 'text-white text-opacity-40' : ''" @click.stop="downloadEpisode">
<span class="material-icons text-success">download</span>
<p class="pl-2 pr-1 text-sm font-semibold">Download</p>
</button>
<!-- <button v-if="libraryItemIdStreaming && !isStreamingFromDifferentLibrary" class="h-8 w-8 flex justify-center items-center mx-2" :class="isQueued ? 'text-success' : ''" @click.stop="queueBtnClick">
<span class="material-icons-outlined">{{ isQueued ? 'playlist_add_check' : 'queue' }}</span>
</button> -->
<ui-tooltip v-if="libraryItemIdStreaming && !isStreamingFromDifferentLibrary" :text="isQueued ? $strings.MessageRemoveFromPlayerQueue : $strings.MessageAddToPlayerQueue" :class="isQueued ? 'text-success' : ''" direction="top">
<ui-tooltip v-if="episode.id && libraryItemIdStreaming && !isStreamingFromDifferentLibrary" :text="isQueued ? $strings.MessageRemoveFromPlayerQueue : $strings.MessageAddToPlayerQueue" :class="isQueued ? 'text-success' : ''" direction="top">
<ui-icon-btn :icon="isQueued ? 'playlist_add_check' : 'playlist_play'" borderless @click="queueBtnClick" />
</ui-tooltip>
<ui-tooltip :text="userIsFinished ? $strings.MessageMarkAsNotFinished : $strings.MessageMarkAsFinished" direction="top">
<ui-tooltip v-if="episode.id" :text="userIsFinished ? $strings.MessageMarkAsNotFinished : $strings.MessageMarkAsFinished" direction="top">
<ui-read-icon-btn :disabled="isProcessingReadUpdate" :is-read="userIsFinished" borderless class="mx-1 mt-0.5" @click="toggleFinished" />
</ui-tooltip>
<ui-tooltip :text="$strings.LabelYourPlaylists" direction="top">
<ui-tooltip v-if="episode.id" :text="$strings.LabelYourPlaylists" direction="top">
<ui-icon-btn icon="playlist_add" borderless @click="clickAddToPlaylist" />
</ui-tooltip>
<ui-icon-btn v-if="userCanUpdate" icon="edit" borderless @click="clickEdit" />
<ui-icon-btn v-if="userCanDelete" icon="close" borderless @click="removeClick" />
<ui-icon-btn v-if="episode.id && userCanUpdate" icon="edit" borderless @click="clickEdit" />
<ui-icon-btn v-if="episode.id && userCanDelete" icon="close" borderless @click="removeClick" />
<p v-if="isDownloading">Downloading...</p>
<p v-if="isDownloadQueued">Queued...</p>
</div>
</div>
<div v-if="isHovering || isSelected || selectionMode" class="hidden md:block w-12 min-w-12" />
@ -63,14 +70,16 @@ export default {
type: Object,
default: () => {}
},
selectionMode: Boolean
selectionMode: Boolean,
isDownloading: Boolean,
isDownloadQueued: Boolean
},
data() {
return {
isProcessingReadUpdate: false,
processingRemove: false,
isHovering: false,
isSelected: false
isSelected: false,
}
},
computed: {
@ -80,6 +89,9 @@ export default {
userCanDelete() {
return this.$store.getters['user/getUserCanDelete']
},
userIsAdminOrUp() {
return this.$store.getters['user/getIsAdminOrUp']
},
audioFile() {
return this.episode.audioFile
},
@ -202,7 +214,33 @@ export default {
// Add to queue
this.$emit('addToQueue', this.episode)
}
}
},
downloadEpisode() {
var episodesToDownload = [this.episode]
var payloadSize = JSON.stringify(episodesToDownload).length
var sizeInMb = payloadSize / 1024 / 1024
var sizeInMbPretty = sizeInMb.toFixed(2) + 'MB'
console.log('Request size', sizeInMb)
if (sizeInMb > 4.99) {
return this.$toast.error(`Request is too large (${sizeInMbPretty}) should be < 5Mb`)
}
this.processing = true
this.$axios
.$post(`/api/podcasts/${this.libraryItemId}/download-episodes`, episodesToDownload)
.then(() => {
this.processing = false
this.$toast.success('Started downloading episodes')
this.show = false
})
.catch((error) => {
var errorMsg = error.response && error.response.data ? error.response.data : 'Failed to download episodes'
console.error('Failed to download episodes', error)
this.processing = false
this.$toast.error(errorMsg)
this.selectedEpisodes = {}
this.selectAll = false
})
},
}
}
</script>

View file

@ -1,13 +1,16 @@
<template>
<div class="w-full py-6">
<p class="text-lg mb-2 font-semibold md:hidden">{{ $strings.HeaderEpisodes }}</p>
<p v-if="media.podcastFeedDownloadedAt" class="text-sm text-gray-300">Feed last updated {{ $formatDate(media.podcastFeedDownloadedAt, 'MMM do, yyyy HH:mm') }}</p>
<div class="flex items-center mb-4">
<p class="text-lg mb-0 font-semibold hidden md:block">{{ $strings.HeaderEpisodes }}</p>
<ui-icon-btn icon="refresh" class="mx-0.5" outlined @click.stop="refreshPodcastFeed" />
<div class="flex-grow hidden md:block" />
<template v-if="isSelectionMode">
<ui-tooltip :text="selectedIsFinished ? $strings.MessageMarkAsNotFinished : $strings.MessageMarkAsFinished" direction="bottom">
<ui-read-icon-btn :disabled="processing" :is-read="selectedIsFinished" @click="toggleBatchFinished" class="mx-1.5" />
</ui-tooltip>
<ui-btn color="success" :disabled="processing" small class="h-9 mr-1.5" @click="downloadSelectedEpisodes">Download {{ selectedEpisodes.length }} episode(s)</ui-btn>
<ui-btn color="error" :disabled="processing" small class="h-9" @click="removeSelectedEpisodes">{{ $getString('MessageRemoveEpisodes', [selectedEpisodes.length]) }}</ui-btn>
<ui-btn :disabled="processing" small class="ml-2 h-9" @click="clearSelected">{{ $strings.ButtonCancel }}</ui-btn>
</template>
@ -19,10 +22,9 @@
</template>
</div>
<p v-if="!episodes.length" class="py-4 text-center text-lg">{{ $strings.MessageNoEpisodes }}</p>
<template v-for="episode in episodesSorted">
<tables-podcast-episode-table-row ref="episodeRow" :key="episode.id" :episode="episode" :library-item-id="libraryItem.id" :selection-mode="isSelectionMode" class="item" @play="playEpisode" @remove="removeEpisode" @edit="editEpisode" @view="viewEpisode" @selected="episodeSelected" @addToQueue="addEpisodeToQueue" @addToPlaylist="addToPlaylist" />
<template v-for="episode in this.allEpisodes">
<tables-podcast-episode-table-row ref="episodeRow" :key="episode.id" :episode="episode" :library-item-id="libraryItem.id" :selection-mode="isSelectionMode" :is-downloading="isDownloading(episode)" :is-download-queued="isDownloadQueued(episode)" class="item" @play="playEpisode" @remove="removeEpisode" @edit="editEpisode" @view="viewEpisode" @selected="episodeSelected" @addToQueue="addEpisodeToQueue" @addToPlaylist="addToPlaylist" />
</template>
<modals-podcast-remove-episode v-model="showPodcastRemoveModal" @input="removeEpisodeModalToggled" :library-item="libraryItem" :episodes="episodesToRemove" @clearSelected="clearSelected" />
</div>
</template>
@ -33,6 +35,14 @@ export default {
libraryItem: {
type: Object,
default: () => {}
},
episodesDownloading: {
type: Array,
default: () => []
},
episodesQueued: {
type: Array,
default: () => []
}
},
data() {
@ -54,6 +64,11 @@ export default {
handler() {
this.init()
}
},
episodesDownloading: {
handler() {
console.log(this.episodesDownloading)
}
}
},
computed: {
@ -137,6 +152,17 @@ export default {
return String(a[this.sortKey]).localeCompare(String(b[this.sortKey]), undefined, { numeric: true, sensitivity: 'base' })
})
},
allEpisodes() {
const added = new Set()
const episodes = []
for (const episode of [...this.episodes, ...this.media.podcastFeed.episodes]) {
const key = `${episode.pubDate}-${episode.title}`
if (added.has(key)) continue
episodes.push(episode)
added.add(key)
}
return episodes
},
selectedIsFinished() {
// Find an item that is not finished, if none then all items finished
return !this.selectedEpisodes.find((episode) => {
@ -290,6 +316,49 @@ export default {
this.$store.commit('globals/setSelectedEpisode', episode)
this.$store.commit('globals/setShowViewPodcastEpisodeModal', true)
},
refreshPodcastFeed() {
this.$axios
.get(`/api/podcasts/${this.libraryItem.id}/refresh-episodes-list`)
.then(() => {
this.$toast.success('Fetched episodes!')
})
.catch((error) => {
this.$toast.error('Fetching episodes failed')
console.error('Fetching episodes failed', error)
})
},
downloadSelectedEpisodes() {
var episodesToDownload = this.selectedEpisodes
var payloadSize = JSON.stringify(episodesToDownload).length
var sizeInMb = payloadSize / 1024 / 1024
var sizeInMbPretty = sizeInMb.toFixed(2) + 'MB'
console.log('Request size', sizeInMb)
if (sizeInMb > 4.99) {
return this.$toast.error(`Request is too large (${sizeInMbPretty}) should be < 5Mb`)
}
this.processing = true
this.$axios
.$post(`/api/podcasts/${this.libraryItem.id}/download-episodes`, episodesToDownload)
.then(() => {
this.processing = false
this.$toast.success('Started downloading episodes')
this.show = false
this.clearSelected()
})
.catch((error) => {
var errorMsg = error.response && error.response.data ? error.response.data : 'Failed to download episodes'
console.error('Failed to download episodes', error)
this.processing = false
this.$toast.error(errorMsg)
this.clearSelected()
})
},
isDownloading(episode) {
return this.episodesDownloading.map(ep => ep.url).includes(episode?.url || episode?.enclosure?.url)
},
isDownloadQueued(episode) {
return this.episodesQueued.map(ep => ep.url).includes(episode?.url || episode?.enclosure?.url)
},
init() {
this.episodesCopy = this.episodes.map((ep) => ({ ...ep }))
}