mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Add:Purge cache promp alert
This commit is contained in:
		
							parent
							
								
									3150822117
								
							
						
					
					
						commit
						173b72c3b5
					
				| @ -171,6 +171,20 @@ | ||||
|         </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> | ||||
| </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', | ||||
|         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' | ||||
|       } | ||||
|       }, | ||||
|       showConfirmPurgeCache: false | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
| @ -285,7 +300,11 @@ export default { | ||||
|           }) | ||||
|       } | ||||
|     }, | ||||
|     async purgeCache() { | ||||
|     purgeCache() { | ||||
|       this.showConfirmPurgeCache = true | ||||
|     }, | ||||
|     async confirmPurge() { | ||||
|       this.showConfirmPurgeCache = false | ||||
|       this.isPurgingCache = true | ||||
|       await this.$axios | ||||
|         .$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 Series = require('../objects/entities/Series') | ||||
| const Audiobook = require('../objects/entities/Audiobook') | ||||
| const EBook = require('../objects/entities/EBook') | ||||
| 
 | ||||
| const MediaProgress = require('../objects/user/MediaProgress') | ||||
| const PlaybackSession = require('../objects/PlaybackSession') | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user