diff --git a/client/components/ui/Tooltip.vue b/client/components/ui/Tooltip.vue index f376329b..c1eabfc6 100644 --- a/client/components/ui/Tooltip.vue +++ b/client/components/ui/Tooltip.vue @@ -51,8 +51,8 @@ export default { tooltip.style.zIndex = 100 tooltip.style.backgroundColor = 'rgba(0,0,0,0.85)' tooltip.innerHTML = this.text - tooltip.addEventListener('mouseover', this.cancelHide); - tooltip.addEventListener('mouseleave', this.hideTooltip); + tooltip.addEventListener('mouseover', this.cancelHide) + tooltip.addEventListener('mouseleave', this.hideTooltip) this.setTooltipPosition(tooltip) @@ -107,7 +107,7 @@ export default { this.isShowing = false }, cancelHide() { - if (this.hideTimeout) clearTimeout(this.hideTimeout); + if (this.hideTimeout) clearTimeout(this.hideTimeout) }, mouseover() { if (!this.isShowing) this.showTooltip() diff --git a/server/objects/PodcastEpisodeDownload.js b/server/objects/PodcastEpisodeDownload.js index 73eee038..5a683322 100644 --- a/server/objects/PodcastEpisodeDownload.js +++ b/server/objects/PodcastEpisodeDownload.js @@ -56,7 +56,14 @@ class PodcastEpisodeDownload { setData(podcastEpisode, libraryItem, isAutoDownload, libraryId) { this.id = getId('epdl') this.podcastEpisode = podcastEpisode - this.url = encodeURI(podcastEpisode.enclosure.url) + + const url = podcastEpisode.enclosure.url + if (decodeURIComponent(url) !== url) { // Already encoded + this.url = url + } else { + this.url = encodeURI(url) + } + this.libraryItem = libraryItem this.isAutoDownload = isAutoDownload this.createdAt = Date.now() diff --git a/server/objects/mediaTypes/Book.js b/server/objects/mediaTypes/Book.js index b25938ca..2983faf7 100644 --- a/server/objects/mediaTypes/Book.js +++ b/server/objects/mediaTypes/Book.js @@ -356,9 +356,9 @@ class Book { } updateAudioTracks(orderedFileData) { - var index = 1 + let index = 1 this.audioFiles = orderedFileData.map((fileData) => { - var audioFile = this.audioFiles.find(af => af.ino === fileData.ino) + const audioFile = this.audioFiles.find(af => af.ino === fileData.ino) audioFile.manuallyVerified = true audioFile.invalid = false audioFile.error = null @@ -376,11 +376,11 @@ class Book { this.rebuildTracks() } - rebuildTracks(preferOverdriveMediaMarker) { + rebuildTracks() { Logger.debug(`[Book] Tracks being rebuilt...!`) this.audioFiles.sort((a, b) => a.index - b.index) this.missingParts = [] - this.setChapters(preferOverdriveMediaMarker) + this.setChapters() this.checkUpdateMissingTracks() } @@ -412,14 +412,16 @@ class Book { return wasUpdated } - setChapters(preferOverdriveMediaMarker = false) { + setChapters() { + const preferOverdriveMediaMarker = !!global.ServerSettings.scannerPreferOverdriveMediaMarker + // If 1 audio file without chapters, then no chapters will be set - var includedAudioFiles = this.audioFiles.filter(af => !af.exclude) + const includedAudioFiles = this.audioFiles.filter(af => !af.exclude) if (!includedAudioFiles.length) return // If overdrive media markers are present and preferred, use those instead if (preferOverdriveMediaMarker) { - var overdriveChapters = parseOverdriveMediaMarkersAsChapters(includedAudioFiles) + const overdriveChapters = parseOverdriveMediaMarkersAsChapters(includedAudioFiles) if (overdriveChapters) { Logger.info('[Book] Overdrive Media Markers and preference found! Using these for chapter definitions') this.chapters = overdriveChapters @@ -460,17 +462,26 @@ class Book { }) } } else if (includedAudioFiles.length > 1) { + const preferAudioMetadata = !!global.ServerSettings.scannerPreferAudioMetadata + // Build chapters from audio files this.chapters = [] - var currChapterId = 0 - var currStartTime = 0 + let currChapterId = 0 + let currStartTime = 0 includedAudioFiles.forEach((file) => { if (file.duration) { + let title = file.metadata.filename ? Path.basename(file.metadata.filename, Path.extname(file.metadata.filename)) : `Chapter ${currChapterId}` + + // When prefer audio metadata server setting is set then use ID3 title tag as long as it is not the same as the book title + if (preferAudioMetadata && file.metaTags?.tagTitle && file.metaTags?.tagTitle !== this.metadata.title) { + title = file.metaTags.tagTitle + } + this.chapters.push({ id: currChapterId++, start: currStartTime, end: currStartTime + file.duration, - title: file.metadata.filename ? Path.basename(file.metadata.filename, Path.extname(file.metadata.filename)) : `Chapter ${currChapterId}` + title }) currStartTime += file.duration } diff --git a/server/scanner/MediaFileScanner.js b/server/scanner/MediaFileScanner.js index e9a54b66..a10b949c 100644 --- a/server/scanner/MediaFileScanner.js +++ b/server/scanner/MediaFileScanner.js @@ -221,7 +221,7 @@ class MediaFileScanner { */ async scanMediaFiles(mediaLibraryFiles, libraryItem, libraryScan = null) { const preferAudioMetadata = libraryScan ? !!libraryScan.preferAudioMetadata : !!global.ServerSettings.scannerPreferAudioMetadata - const preferOverdriveMediaMarker = libraryScan ? !!libraryScan.preferOverdriveMediaMarker : !!global.ServerSettings.scannerPreferOverdriveMediaMarker + const preferOverdriveMediaMarker = !!global.ServerSettings.scannerPreferOverdriveMediaMarker let hasUpdated = false @@ -280,7 +280,7 @@ class MediaFileScanner { } if (hasUpdated) { - libraryItem.media.rebuildTracks(preferOverdriveMediaMarker) + libraryItem.media.rebuildTracks() } } else if (libraryItem.mediaType === 'podcast') { // Podcast Media Type const existingAudioFiles = mediaScanResult.audioFiles.filter(af => libraryItem.media.findFileWithInode(af.ino)) diff --git a/server/utils/filePerms.js b/server/utils/filePerms.js index c48b4261..85fa7e84 100644 --- a/server/utils/filePerms.js +++ b/server/utils/filePerms.js @@ -107,7 +107,6 @@ module.exports.setDefaultDirSync = (path, silent = false) => { const uid = global.Uid const gid = global.Gid if (isNaN(uid) || isNaN(gid)) { - if (!silent) Logger.debug('Not modifying permissions since no uid/gid is specified') return true } if (!silent) Logger.debug(`[FilePerms] Setting dir permission "${mode}" for uid ${uid} and gid ${gid} | "${path}"`)