mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			207 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const STANDARD_GENRES = ['Adventure', 'Autobiography', 'Biography', 'Childrens', 'Comedy', 'Crime', 'Dystopian', 'Fantasy', 'Fiction', 'Health', 'History', 'Horror', 'Mystery', 'New Adult', 'Nonfiction', 'Philosophy', 'Politics', 'Religion', 'Romance', 'Sci-Fi', 'Self-Help', 'Short Story', 'Technology', 'Thriller', 'True Crime', 'Western', 'Young Adult']
 | |
| 
 | |
| export const state = () => ({
 | |
|   audiobooks: [],
 | |
|   loadedLibraryId: '',
 | |
|   listeners: [],
 | |
|   genres: [...STANDARD_GENRES],
 | |
|   tags: [],
 | |
|   series: [],
 | |
|   keywordFilter: null,
 | |
|   selectedSeries: null
 | |
| })
 | |
| 
 | |
| export const getters = {
 | |
|   getBookCoverSrc: (state, getters, rootState, rootGetters) => (bookItem, placeholder = '/book_placeholder.jpg') => {
 | |
|     if (!bookItem) return placeholder
 | |
|     var book = bookItem.book
 | |
|     if (!book || !book.cover || book.cover === placeholder) return placeholder
 | |
|     var cover = book.cover
 | |
| 
 | |
|     // Absolute URL covers (should no longer be used)
 | |
|     if (cover.startsWith('http:') || cover.startsWith('https:')) return cover
 | |
| 
 | |
|     // Server hosted covers
 | |
|     try {
 | |
|       // Ensure cover is refreshed if cached
 | |
|       var bookLastUpdate = book.lastUpdate || Date.now()
 | |
|       var userToken = rootGetters['user/getToken']
 | |
| 
 | |
|       cover = cover.replace(/\\/g, '/')
 | |
| 
 | |
|       // Map old covers to new format /s/book/{bookid}/*
 | |
|       if (cover.startsWith('/local')) {
 | |
|         cover = cover.replace('local', `s/book/${bookItem.id}`)
 | |
|         if (cover.includes(bookItem.path + '/')) { // Remove book path
 | |
|           cover = cover.replace(bookItem.path + '/', '')
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       // Easier to replace these special characters then to encodeUriComponent of the filename
 | |
|       var encodedCover = cover.replace(/%/g, '%25').replace(/#/g, '%23')
 | |
| 
 | |
|       var url = new URL(encodedCover, document.baseURI)
 | |
|       return url.href + `?token=${userToken}&ts=${bookLastUpdate}`
 | |
|     } catch (err) {
 | |
|       console.error(err)
 | |
|       return placeholder
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| export const actions = {
 | |
| 
 | |
| }
 | |
| 
 | |
| export const mutations = {
 | |
|   setKeywordFilter(state, val) {
 | |
|     state.keywordFilter = val
 | |
|   },
 | |
|   setSelectedSeries(state, val) {
 | |
|     state.selectedSeries = val
 | |
|   },
 | |
|   set(state, audiobooks) {
 | |
|     // GENRES
 | |
|     var genres = [...state.genres]
 | |
|     audiobooks.forEach((ab) => {
 | |
|       if (!ab.book) return
 | |
|       genres = genres.concat(ab.book.genres)
 | |
|     })
 | |
|     state.genres = [...new Set(genres)] // Remove Duplicates
 | |
|     state.genres.sort((a, b) => a.toLowerCase() < b.toLowerCase() ? -1 : 1)
 | |
| 
 | |
|     // TAGS
 | |
|     var tags = []
 | |
|     audiobooks.forEach((ab) => {
 | |
|       tags = tags.concat(ab.tags)
 | |
|     })
 | |
|     state.tags = [...new Set(tags)] // Remove Duplicates
 | |
|     state.tags.sort((a, b) => a.toLowerCase() < b.toLowerCase() ? -1 : 1)
 | |
| 
 | |
|     // SERIES
 | |
|     var series = []
 | |
|     audiobooks.forEach((ab) => {
 | |
|       if (!ab.book || !ab.book.series || series.includes(ab.book.series)) return
 | |
|       series.push(ab.book.series)
 | |
|     })
 | |
|     state.series = series
 | |
|     state.series.sort((a, b) => a.toLowerCase() < b.toLowerCase() ? -1 : 1)
 | |
| 
 | |
|     state.audiobooks = audiobooks
 | |
|     state.listeners.forEach((listener) => {
 | |
|       listener.meth()
 | |
|     })
 | |
|   },
 | |
|   addUpdate(state, audiobook) {
 | |
|     if (state.loadedLibraryId && audiobook.libraryId !== state.loadedLibraryId) {
 | |
|       console.warn('Invalid library', audiobook, 'loaded library', state.loadedLibraryId, '"')
 | |
|       return
 | |
|     }
 | |
| 
 | |
|     var index = state.audiobooks.findIndex(a => a.id === audiobook.id)
 | |
|     var origAudiobook = null
 | |
|     if (index >= 0) {
 | |
|       origAudiobook = { ...state.audiobooks[index] }
 | |
|       state.audiobooks.splice(index, 1, audiobook)
 | |
|     } else {
 | |
|       state.audiobooks.push(audiobook)
 | |
|     }
 | |
| 
 | |
|     if (audiobook.book) {
 | |
|       // GENRES
 | |
|       var newGenres = []
 | |
|       audiobook.book.genres.forEach((genre) => {
 | |
|         if (!state.genres.includes(genre)) newGenres.push(genre)
 | |
|       })
 | |
|       if (newGenres.length) {
 | |
|         state.genres = state.genres.concat(newGenres)
 | |
|         state.genres.sort((a, b) => a.toLowerCase() < b.toLowerCase() ? -1 : 1)
 | |
|       }
 | |
| 
 | |
|       // SERIES
 | |
|       if (audiobook.book.series && !state.series.includes(audiobook.book.series)) {
 | |
|         state.series.push(audiobook.book.series)
 | |
|         state.series.sort((a, b) => a.toLowerCase() < b.toLowerCase() ? -1 : 1)
 | |
|       }
 | |
|       if (origAudiobook && origAudiobook.book && origAudiobook.book.series) {
 | |
|         var isInAB = state.audiobooks.find(ab => ab.book && ab.book.series === origAudiobook.book.series)
 | |
|         if (!isInAB) state.series = state.series.filter(series => series !== origAudiobook.book.series)
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     // TAGS
 | |
|     var newTags = []
 | |
|     audiobook.tags.forEach((tag) => {
 | |
|       if (!state.tags.includes(tag)) newTags.push(tag)
 | |
|     })
 | |
|     if (newTags.length) {
 | |
|       state.tags = state.tags.concat(newTags)
 | |
|       state.tags.sort((a, b) => a.toLowerCase() < b.toLowerCase() ? -1 : 1)
 | |
|     }
 | |
| 
 | |
|     state.listeners.forEach((listener) => {
 | |
|       if (!listener.audiobookId || listener.audiobookId === audiobook.id) {
 | |
|         listener.meth()
 | |
|       }
 | |
|     })
 | |
|   },
 | |
|   remove(state, audiobook) {
 | |
|     state.audiobooks = state.audiobooks.filter(a => a.id !== audiobook.id)
 | |
| 
 | |
|     if (audiobook.book) {
 | |
|       // GENRES
 | |
|       audiobook.book.genres.forEach((genre) => {
 | |
|         if (!STANDARD_GENRES.includes(genre)) {
 | |
|           var isInOtherAB = state.audiobooks.find(ab => {
 | |
|             return ab.book && ab.book.genres.includes(genre)
 | |
|           })
 | |
|           if (!isInOtherAB) {
 | |
|             // Genre is not used by any other audiobook - remove it
 | |
|             state.genres = state.genres.filter(g => g !== genre)
 | |
|           }
 | |
|         }
 | |
|       })
 | |
| 
 | |
|       // SERIES
 | |
|       if (audiobook.book.series) {
 | |
|         var isInOtherAB = state.audiobooks.find(ab => ab.book && ab.book.series === audiobook.book.series)
 | |
|         if (!isInOtherAB) {
 | |
|           // Series not used in any other audiobook - remove it
 | |
|           state.series = state.series.filter(s => s !== audiobook.book.series)
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     // TAGS
 | |
|     audiobook.tags.forEach((tag) => {
 | |
|       var isInOtherAB = state.audiobooks.find(ab => {
 | |
|         return ab.tags.includes(tag)
 | |
|       })
 | |
|       if (!isInOtherAB) {
 | |
|         // Tag is not used by any other audiobook - remove it
 | |
|         state.tags = state.tags.filter(t => t !== tag)
 | |
|       }
 | |
|     })
 | |
| 
 | |
|     state.listeners.forEach((listener) => {
 | |
|       if (!listener.audiobookId || listener.audiobookId === audiobook.id) {
 | |
|         listener.meth()
 | |
|       }
 | |
|     })
 | |
|   },
 | |
|   addListener(state, listener) {
 | |
|     var index = state.listeners.findIndex(l => l.id === listener.id)
 | |
|     if (index >= 0) state.listeners.splice(index, 1, listener)
 | |
|     else state.listeners.push(listener)
 | |
|   },
 | |
|   removeListener(state, listenerId) {
 | |
|     state.listeners = state.listeners.filter(l => l.id !== listenerId)
 | |
|   },
 | |
|   audiobookUpdated(state, audiobook) {
 | |
|     state.listeners.forEach((listener) => {
 | |
|       if (!listener.audiobookId || listener.audiobookId === audiobook.id) {
 | |
|         listener.meth()
 | |
|       }
 | |
|     })
 | |
|   }
 | |
| } |