mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-05-22 01:18:13 +02:00
Add:Purge cache promp alert
This commit is contained in:
parent
3150822117
commit
173b72c3b5
@ -171,6 +171,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<prompt-dialog v-model="showConfirmPurgeCache" :width="675">
|
||||||
|
<div class="px-4 w-full text-sm py-6 rounded-lg bg-bg shadow-lg border border-black-300">
|
||||||
|
<p class="text-error text-lg font-semibold">Important Notice!</p>
|
||||||
|
<p class="text-lg my-2 text-center">Purge cache will delete the entire directory at <span class="font-mono">/metadata/cache</span>.</p>
|
||||||
|
|
||||||
|
<p class="text-lg text-center mb-8">Are you sure you want to remove the cache directory?</p>
|
||||||
|
<div class="flex px-1 items-center">
|
||||||
|
<ui-btn color="primary" @click="showConfirmPurgeCache = false">Nevermind</ui-btn>
|
||||||
|
<div class="flex-grow" />
|
||||||
|
<ui-btn color="success" @click="confirmPurge">Yes, Purge!</ui-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</prompt-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -194,7 +208,8 @@ export default {
|
|||||||
storeCoverWithBook: 'By default covers are stored in /metadata/books, enabling this setting will store covers in the books folder. Only one file named "cover" will be kept',
|
storeCoverWithBook: 'By default covers are stored in /metadata/books, enabling this setting will store covers in the books folder. Only one file named "cover" will be kept',
|
||||||
storeMetadataWithBook: 'By default metadata files are stored in /metadata/books, enabling this setting will store metadata files in the books folder. Uses .abs file extension',
|
storeMetadataWithBook: 'By default metadata files are stored in /metadata/books, enabling this setting will store metadata files in the books folder. Uses .abs file extension',
|
||||||
coverAspectRatio: 'Prefer to use square covers over standard 1.6:1 book covers'
|
coverAspectRatio: 'Prefer to use square covers over standard 1.6:1 book covers'
|
||||||
}
|
},
|
||||||
|
showConfirmPurgeCache: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -285,7 +300,11 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async purgeCache() {
|
purgeCache() {
|
||||||
|
this.showConfirmPurgeCache = true
|
||||||
|
},
|
||||||
|
async confirmPurge() {
|
||||||
|
this.showConfirmPurgeCache = false
|
||||||
this.isPurgingCache = true
|
this.isPurgingCache = true
|
||||||
await this.$axios
|
await this.$axios
|
||||||
.$post('/api/purgecache')
|
.$post('/api/purgecache')
|
||||||
|
@ -1,248 +0,0 @@
|
|||||||
const Path = require('path')
|
|
||||||
const AudioFile = require('../files/AudioFile')
|
|
||||||
const { areEquivalent, copyValue, getId } = require('../../utils/index')
|
|
||||||
const AudioTrack = require('../files/AudioTrack')
|
|
||||||
|
|
||||||
class Audiobook {
|
|
||||||
constructor(audiobook) {
|
|
||||||
this.id = null
|
|
||||||
this.index = null
|
|
||||||
this.name = null
|
|
||||||
this.audioFiles = []
|
|
||||||
this.chapters = []
|
|
||||||
this.missingParts = []
|
|
||||||
this.addedAt = null
|
|
||||||
this.updatedAt = null
|
|
||||||
|
|
||||||
if (audiobook) {
|
|
||||||
this.construct(audiobook)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
construct(audiobook) {
|
|
||||||
this.id = audiobook.id
|
|
||||||
this.index = audiobook.index
|
|
||||||
this.name = audiobook.name || null
|
|
||||||
this.audioFiles = audiobook.audioFiles.map(f => new AudioFile(f))
|
|
||||||
this.chapters = audiobook.chapters.map(c => ({ ...c }))
|
|
||||||
this.missingParts = audiobook.missingParts ? [...audiobook.missingParts] : []
|
|
||||||
this.addedAt = audiobook.addedAt
|
|
||||||
this.updatedAt = audiobook.updatedAt
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON() {
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
index: this.index,
|
|
||||||
name: this.name,
|
|
||||||
audioFiles: this.audioFiles.map(f => f.toJSON()),
|
|
||||||
chapters: this.chapters.map(c => ({ ...c })),
|
|
||||||
missingParts: [...this.missingParts],
|
|
||||||
addedAt: this.addedAt,
|
|
||||||
updatedAt: this.updatedAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSONMinified() {
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
index: this.index,
|
|
||||||
name: this.name,
|
|
||||||
numTracks: this.tracks.length,
|
|
||||||
numAudioFiles: this.audioFiles.length,
|
|
||||||
numChapters: this.chapters.length,
|
|
||||||
numMissingParts: this.missingParts.length,
|
|
||||||
duration: this.duration,
|
|
||||||
size: this.size,
|
|
||||||
addedAt: this.addedAt,
|
|
||||||
updatedAt: this.updatedAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSONExpanded() {
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
index: this.index,
|
|
||||||
name: this.name,
|
|
||||||
audioFiles: this.audioFiles.map(f => f.toJSON()),
|
|
||||||
chapters: this.chapters.map(c => ({ ...c })),
|
|
||||||
duration: this.duration,
|
|
||||||
size: this.size,
|
|
||||||
tracks: this.tracks.map(t => t.toJSON()),
|
|
||||||
missingParts: [...this.missingParts],
|
|
||||||
addedAt: this.addedAt,
|
|
||||||
updatedAt: this.updatedAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get isPlaybackMediaEntity() { return true }
|
|
||||||
get tracks() {
|
|
||||||
return this.audioFiles.filter(af => !af.exclude && !af.invalid)
|
|
||||||
}
|
|
||||||
get duration() {
|
|
||||||
var total = 0
|
|
||||||
this.tracks.forEach((track) => total += track.duration)
|
|
||||||
return total
|
|
||||||
}
|
|
||||||
get size() {
|
|
||||||
var total = 0
|
|
||||||
this.audioFiles.forEach((af) => total += af.metadata.size)
|
|
||||||
return total
|
|
||||||
}
|
|
||||||
get hasEmbeddedCoverArt() {
|
|
||||||
return this.audioFiles.some(af => af.embeddedCoverArt)
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(name, index) {
|
|
||||||
this.id = getId('ab')
|
|
||||||
this.name = name
|
|
||||||
this.index = index
|
|
||||||
this.addedAt = Date.now()
|
|
||||||
this.updatedAt = Date.now()
|
|
||||||
}
|
|
||||||
|
|
||||||
update(payload) {
|
|
||||||
var json = this.toJSON()
|
|
||||||
var hasUpdates = false
|
|
||||||
for (const key in json) {
|
|
||||||
if (payload[key] !== undefined) {
|
|
||||||
if (!areEquivalent(payload[key], json[key])) {
|
|
||||||
this[key] = copyValue(payload[key])
|
|
||||||
Logger.debug('[Audiobook] Key updated', key, this[key])
|
|
||||||
hasUpdates = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hasUpdates
|
|
||||||
}
|
|
||||||
|
|
||||||
updateAudioTracks(orderedFileData) {
|
|
||||||
var index = 1
|
|
||||||
this.audioFiles = orderedFileData.map((fileData) => {
|
|
||||||
var audioFile = this.audioFiles.find(af => af.ino === fileData.ino)
|
|
||||||
audioFile.manuallyVerified = true
|
|
||||||
audioFile.invalid = false
|
|
||||||
audioFile.error = null
|
|
||||||
if (fileData.exclude !== undefined) {
|
|
||||||
audioFile.exclude = !!fileData.exclude
|
|
||||||
}
|
|
||||||
if (audioFile.exclude) {
|
|
||||||
audioFile.index = -1
|
|
||||||
} else {
|
|
||||||
audioFile.index = index++
|
|
||||||
}
|
|
||||||
return audioFile
|
|
||||||
})
|
|
||||||
|
|
||||||
this.rebuildTracks()
|
|
||||||
}
|
|
||||||
|
|
||||||
rebuildTracks() {
|
|
||||||
this.audioFiles.sort((a, b) => a.index - b.index)
|
|
||||||
this.missingParts = []
|
|
||||||
this.setChapters()
|
|
||||||
this.checkUpdateMissingTracks()
|
|
||||||
}
|
|
||||||
|
|
||||||
checkUpdateMissingTracks() {
|
|
||||||
var currMissingParts = (this.missingParts || []).join(',') || ''
|
|
||||||
|
|
||||||
var current_index = 1
|
|
||||||
var missingParts = []
|
|
||||||
|
|
||||||
for (let i = 0; i < this.tracks.length; i++) {
|
|
||||||
var _track = this.tracks[i]
|
|
||||||
if (_track.index > current_index) {
|
|
||||||
var num_parts_missing = _track.index - current_index
|
|
||||||
for (let x = 0; x < num_parts_missing && x < 9999; x++) {
|
|
||||||
missingParts.push(current_index + x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current_index = _track.index + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
this.missingParts = missingParts
|
|
||||||
|
|
||||||
var newMissingParts = (this.missingParts || []).join(',') || ''
|
|
||||||
var wasUpdated = newMissingParts !== currMissingParts
|
|
||||||
if (wasUpdated && this.missingParts.length) {
|
|
||||||
Logger.info(`[Audiobook] "${this.name}" has ${missingParts.length} missing parts`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return wasUpdated
|
|
||||||
}
|
|
||||||
|
|
||||||
setChapters() {
|
|
||||||
// If 1 audio file without chapters, then no chapters will be set
|
|
||||||
var includedAudioFiles = this.audioFiles.filter(af => !af.exclude)
|
|
||||||
if (includedAudioFiles.length === 1) {
|
|
||||||
// 1 audio file with chapters
|
|
||||||
if (includedAudioFiles[0].chapters) {
|
|
||||||
this.chapters = includedAudioFiles[0].chapters.map(c => ({ ...c }))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.chapters = []
|
|
||||||
var currChapterId = 0
|
|
||||||
var currStartTime = 0
|
|
||||||
includedAudioFiles.forEach((file) => {
|
|
||||||
// If audio file has chapters use chapters
|
|
||||||
if (file.chapters && file.chapters.length) {
|
|
||||||
file.chapters.forEach((chapter) => {
|
|
||||||
var chapterDuration = chapter.end - chapter.start
|
|
||||||
if (chapterDuration > 0) {
|
|
||||||
var title = `Chapter ${currChapterId}`
|
|
||||||
if (chapter.title) {
|
|
||||||
title += ` (${chapter.title})`
|
|
||||||
}
|
|
||||||
this.chapters.push({
|
|
||||||
id: currChapterId++,
|
|
||||||
start: currStartTime,
|
|
||||||
end: currStartTime + chapterDuration,
|
|
||||||
title
|
|
||||||
})
|
|
||||||
currStartTime += chapterDuration
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else if (file.duration) {
|
|
||||||
// Otherwise just use track has chapter
|
|
||||||
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}`
|
|
||||||
})
|
|
||||||
currStartTime += file.duration
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
findFileWithInode(inode) {
|
|
||||||
return this.audioFiles.find(af => af.ino === inode)
|
|
||||||
}
|
|
||||||
|
|
||||||
removeFileWithInode(inode) {
|
|
||||||
this.audioFiles = this.audioFiles.filter(af => af.ino !== inode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only checks container format
|
|
||||||
checkCanDirectPlay(payload) {
|
|
||||||
var supportedMimeTypes = payload.supportedMimeTypes || []
|
|
||||||
return !this.tracks.some((t) => !supportedMimeTypes.includes(t.mimeType))
|
|
||||||
}
|
|
||||||
|
|
||||||
getDirectPlayTracklist(libraryItemId) {
|
|
||||||
var tracklist = []
|
|
||||||
|
|
||||||
var startOffset = 0
|
|
||||||
this.tracks.forEach((audioFile) => {
|
|
||||||
var audioTrack = new AudioTrack()
|
|
||||||
audioTrack.setData(libraryItemId, audioFile, startOffset)
|
|
||||||
startOffset += audioTrack.duration
|
|
||||||
tracklist.push(audioTrack)
|
|
||||||
})
|
|
||||||
|
|
||||||
return tracklist
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = Audiobook
|
|
@ -1,80 +0,0 @@
|
|||||||
const EBookFile = require('../files/EBookFile')
|
|
||||||
const { areEquivalent, copyValue, getId } = require('../../utils/index')
|
|
||||||
|
|
||||||
class EBook {
|
|
||||||
constructor(ebook) {
|
|
||||||
this.id = null
|
|
||||||
this.index = null
|
|
||||||
this.name = null
|
|
||||||
this.ebookFile = null
|
|
||||||
this.addedAt = null
|
|
||||||
this.updatedAt = null
|
|
||||||
|
|
||||||
if (ebook) {
|
|
||||||
this.construct(ebook)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
construct(ebook) {
|
|
||||||
this.id = ebook.id
|
|
||||||
this.index = ebook.index
|
|
||||||
this.name = ebook.name
|
|
||||||
this.ebookFile = new EBookFile(ebook.ebookFile)
|
|
||||||
this.addedAt = ebook.addedAt
|
|
||||||
this.updatedAt = ebook.updatedAt
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON() {
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
index: this.index,
|
|
||||||
name: this.name,
|
|
||||||
ebookFile: this.ebookFile.toJSON(),
|
|
||||||
addedAt: this.addedAt,
|
|
||||||
updatedAt: this.updatedAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSONMinified() {
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
index: this.index,
|
|
||||||
name: this.name,
|
|
||||||
ebookFormat: this.ebookFile.ebookFormat,
|
|
||||||
addedAt: this.addedAt,
|
|
||||||
updatedAt: this.updatedAt,
|
|
||||||
size: this.size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSONExpanded() {
|
|
||||||
return {
|
|
||||||
id: this.id,
|
|
||||||
index: this.index,
|
|
||||||
name: this.name,
|
|
||||||
ebookFile: this.ebookFile.toJSON(),
|
|
||||||
addedAt: this.addedAt,
|
|
||||||
updatedAt: this.updatedAt,
|
|
||||||
size: this.size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get isPlaybackMediaEntity() { return false }
|
|
||||||
get size() {
|
|
||||||
return this.ebookFile.metadata.size
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(ebookFile, index) {
|
|
||||||
this.id = getId('eb')
|
|
||||||
this.name = ebookFile.metadata.filename
|
|
||||||
this.index = index
|
|
||||||
this.ebookFile = ebookFile
|
|
||||||
this.addedAt = Date.now()
|
|
||||||
this.updatedAt = Date.now()
|
|
||||||
}
|
|
||||||
|
|
||||||
findFileWithInode(inode) {
|
|
||||||
return this.ebookFile.ino === inode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = EBook
|
|
@ -24,8 +24,6 @@ const AudioMetaTags = require('../objects/metadata/AudioMetaTags')
|
|||||||
|
|
||||||
const Author = require('../objects/entities/Author')
|
const Author = require('../objects/entities/Author')
|
||||||
const Series = require('../objects/entities/Series')
|
const Series = require('../objects/entities/Series')
|
||||||
const Audiobook = require('../objects/entities/Audiobook')
|
|
||||||
const EBook = require('../objects/entities/EBook')
|
|
||||||
|
|
||||||
const MediaProgress = require('../objects/user/MediaProgress')
|
const MediaProgress = require('../objects/user/MediaProgress')
|
||||||
const PlaybackSession = require('../objects/PlaybackSession')
|
const PlaybackSession = require('../objects/PlaybackSession')
|
||||||
|
Loading…
Reference in New Issue
Block a user