mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-06-14 01:16:52 +02:00
Merge branch 'master' into feat/book-series-info
This commit is contained in:
commit
82c3670ee2
@ -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()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user