Merge branch 'master' into feat/book-series-info

This commit is contained in:
Greg Lorenzen 2025-01-14 16:58:16 -08:00
commit 82c3670ee2
4 changed files with 48 additions and 11 deletions

View File

@ -80,7 +80,8 @@ export default {
episodeComponentRefs: {}, episodeComponentRefs: {},
windowHeight: 0, windowHeight: 0,
episodesTableOffsetTop: 0, episodesTableOffsetTop: 0,
episodeRowHeight: 176 episodeRowHeight: 176,
currScrollTop: 0
} }
}, },
watch: { watch: {
@ -484,9 +485,8 @@ export default {
} }
} }
}, },
scroll(evt) { handleScroll() {
if (!evt?.target?.scrollTop) return const scrollTop = this.currScrollTop
const scrollTop = Math.max(evt.target.scrollTop - this.episodesTableOffsetTop, 0)
let firstEpisodeIndex = Math.floor(scrollTop / this.episodeRowHeight) let firstEpisodeIndex = Math.floor(scrollTop / this.episodeRowHeight)
let lastEpisodeIndex = Math.ceil((scrollTop + this.windowHeight) / this.episodeRowHeight) let lastEpisodeIndex = Math.ceil((scrollTop + this.windowHeight) / this.episodeRowHeight)
lastEpisodeIndex = Math.min(this.totalEpisodes - 1, lastEpisodeIndex) lastEpisodeIndex = Math.min(this.totalEpisodes - 1, lastEpisodeIndex)
@ -501,6 +501,12 @@ export default {
}) })
this.mountEpisodes(firstEpisodeIndex, lastEpisodeIndex + 1) this.mountEpisodes(firstEpisodeIndex, lastEpisodeIndex + 1)
}, },
scroll(evt) {
if (!evt?.target?.scrollTop) return
const scrollTop = Math.max(evt.target.scrollTop - this.episodesTableOffsetTop, 0)
this.currScrollTop = scrollTop
this.handleScroll()
},
initListeners() { initListeners() {
const itemPageWrapper = document.getElementById('item-page-wrapper') const itemPageWrapper = document.getElementById('item-page-wrapper')
if (itemPageWrapper) { if (itemPageWrapper) {
@ -535,7 +541,12 @@ export default {
this.episodesPerPage = Math.ceil(this.windowHeight / this.episodeRowHeight) this.episodesPerPage = Math.ceil(this.windowHeight / this.episodeRowHeight)
this.$nextTick(() => { this.$nextTick(() => {
this.mountEpisodes(0, Math.min(this.episodesPerPage, this.totalEpisodes)) // Maybe update currScrollTop if items were removed
const itemPageWrapper = document.getElementById('item-page-wrapper')
const { scrollHeight, clientHeight } = itemPageWrapper
const maxScrollTop = scrollHeight - clientHeight
this.currScrollTop = Math.min(this.currScrollTop, maxScrollTop)
this.handleScroll()
}) })
} }
}, },

View File

@ -461,6 +461,9 @@ class PodcastController {
return res.sendStatus(404) return res.sendStatus(404)
} }
// Remove it from the podcastEpisodes array
req.libraryItem.media.podcastEpisodes = req.libraryItem.media.podcastEpisodes.filter((ep) => ep.id !== episodeId)
if (hardDelete) { if (hardDelete) {
const audioFile = episode.audioFile const audioFile = episode.audioFile
// TODO: this will trigger the watcher. should maybe handle this gracefully // TODO: this will trigger the watcher. should maybe handle this gracefully

View File

@ -115,10 +115,24 @@ class PodcastManager {
let success = false let success = false
if (this.currentDownload.isMp3) { if (this.currentDownload.isMp3) {
// Download episode and tag it // Download episode and tag it
success = await ffmpegHelpers.downloadPodcastEpisode(this.currentDownload).catch((error) => { const ffmpegDownloadResponse = await ffmpegHelpers.downloadPodcastEpisode(this.currentDownload).catch((error) => {
Logger.error(`[PodcastManager] Podcast Episode download failed`, error) Logger.error(`[PodcastManager] Podcast Episode download failed`, error)
return false
}) })
success = !!ffmpegDownloadResponse?.success
// If failed due to ffmpeg error, retry without tagging
// e.g. RSS feed may have incorrect file extension and file type
// See https://github.com/advplyr/audiobookshelf/issues/3837
if (!success && ffmpegDownloadResponse?.isFfmpegError) {
Logger.info(`[PodcastManager] Retrying episode download without tagging`)
// Download episode only
success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath)
.then(() => true)
.catch((error) => {
Logger.error(`[PodcastManager] Podcast Episode download failed`, error)
return false
})
}
} else { } else {
// Download episode only // Download episode only
success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath) success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath)

View File

@ -99,7 +99,7 @@ module.exports.resizeImage = resizeImage
/** /**
* *
* @param {import('../objects/PodcastEpisodeDownload')} podcastEpisodeDownload * @param {import('../objects/PodcastEpisodeDownload')} podcastEpisodeDownload
* @returns * @returns {Promise<{success: boolean, isFfmpegError?: boolean}>}
*/ */
module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => { module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
@ -115,7 +115,11 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
Logger.error(`[ffmpegHelpers] Failed to download podcast episode with url "${podcastEpisodeDownload.url}"`, error) Logger.error(`[ffmpegHelpers] Failed to download podcast episode with url "${podcastEpisodeDownload.url}"`, error)
return null return null
}) })
if (!response) return resolve(false) if (!response) {
return resolve({
success: false
})
}
/** @type {import('../libs/fluentFfmpeg/index').FfmpegCommand} */ /** @type {import('../libs/fluentFfmpeg/index').FfmpegCommand} */
const ffmpeg = Ffmpeg(response.data) const ffmpeg = Ffmpeg(response.data)
@ -177,7 +181,10 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
if (stderrLines.length) { if (stderrLines.length) {
Logger.error(`Full stderr dump for episode url "${podcastEpisodeDownload.url}": ${stderrLines.join('\n')}`) Logger.error(`Full stderr dump for episode url "${podcastEpisodeDownload.url}": ${stderrLines.join('\n')}`)
} }
resolve(false) resolve({
success: false,
isFfmpegError: true
})
}) })
ffmpeg.on('progress', (progress) => { ffmpeg.on('progress', (progress) => {
let progressPercent = 0 let progressPercent = 0
@ -189,7 +196,9 @@ module.exports.downloadPodcastEpisode = (podcastEpisodeDownload) => {
}) })
ffmpeg.on('end', () => { ffmpeg.on('end', () => {
Logger.debug(`[FfmpegHelpers] downloadPodcastEpisode: Complete`) Logger.debug(`[FfmpegHelpers] downloadPodcastEpisode: Complete`)
resolve(podcastEpisodeDownload.targetPath) resolve({
success: true
})
}) })
ffmpeg.run() ffmpeg.run()
}) })