mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-12-28 14:49:38 +00:00
Support for libraries and folder mapping, updating static cover path, detect reader.txt
This commit is contained in:
parent
a590e795e3
commit
577f3bead9
43 changed files with 2548 additions and 768 deletions
|
|
@ -1,10 +1,12 @@
|
|||
import { sort } from '@/assets/fastSort'
|
||||
import { decode } from '@/plugins/init.client'
|
||||
import Path from 'path'
|
||||
|
||||
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: '',
|
||||
lastLoad: 0,
|
||||
listeners: [],
|
||||
genres: [...STANDARD_GENRES],
|
||||
|
|
@ -122,11 +124,12 @@ export const getters = {
|
|||
state.audiobooks.filter(ab => !!(ab.book && ab.book.genres)).forEach(ab => _genres = _genres.concat(ab.book.genres))
|
||||
return [...new Set(_genres)].sort((a, b) => a.toLowerCase() < b.toLowerCase() ? -1 : 1)
|
||||
},
|
||||
getBookCoverSrc: (state, getters, rootState, rootGetters) => (book, placeholder = '/book_placeholder.jpg') => {
|
||||
getBookCoverSrc: (state, getters, rootState, rootGetters) => (bookItem, placeholder = '/book_placeholder.jpg') => {
|
||||
var book = bookItem.book
|
||||
if (!book || !book.cover || book.cover === placeholder) return placeholder
|
||||
var cover = book.cover
|
||||
|
||||
// Absolute URL covers
|
||||
// Absolute URL covers (should no longer be used)
|
||||
if (cover.startsWith('http:') || cover.startsWith('https:')) return cover
|
||||
|
||||
// Server hosted covers
|
||||
|
|
@ -135,6 +138,14 @@ export const getters = {
|
|||
var bookLastUpdate = book.lastUpdate || Date.now()
|
||||
var userToken = rootGetters['user/getToken']
|
||||
|
||||
// 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 + '\\', '')
|
||||
}
|
||||
}
|
||||
|
||||
var url = new URL(cover, document.baseURI)
|
||||
return url.href + `?token=${userToken}&ts=${bookLastUpdate}`
|
||||
} catch (err) {
|
||||
|
|
@ -152,18 +163,24 @@ export const actions = {
|
|||
return false
|
||||
}
|
||||
|
||||
// Don't load again if already loaded in the last 5 minutes
|
||||
var lastLoadDiff = Date.now() - state.lastLoad
|
||||
if (lastLoadDiff < 5 * 60 * 1000) {
|
||||
// Already up to date
|
||||
return false
|
||||
var currentLibraryId = rootState.libraries.currentLibraryId
|
||||
|
||||
if (currentLibraryId === state.loadedLibraryId) {
|
||||
// Don't load again if already loaded in the last 5 minutes
|
||||
var lastLoadDiff = Date.now() - state.lastLoad
|
||||
if (lastLoadDiff < 5 * 60 * 1000) {
|
||||
// Already up to date
|
||||
return false
|
||||
}
|
||||
}
|
||||
commit('setLoadedLibrary', currentLibraryId)
|
||||
|
||||
this.$axios
|
||||
.$get(`/api/audiobooks`)
|
||||
.$get(`/api/library/${currentLibraryId}/audiobooks`)
|
||||
.then((data) => {
|
||||
commit('set', data)
|
||||
commit('setLastLoad')
|
||||
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed', error)
|
||||
|
|
@ -175,6 +192,9 @@ export const actions = {
|
|||
}
|
||||
|
||||
export const mutations = {
|
||||
setLoadedLibrary(state, val) {
|
||||
state.loadedLibraryId = val
|
||||
},
|
||||
setLastLoad(state) {
|
||||
state.lastLoad = Date.now()
|
||||
},
|
||||
|
|
@ -223,6 +243,10 @@ export const mutations = {
|
|||
})
|
||||
},
|
||||
addUpdate(state, audiobook) {
|
||||
if (audiobook.libraryId !== state.loadedLibraryId) {
|
||||
return
|
||||
}
|
||||
|
||||
var index = state.audiobooks.findIndex(a => a.id === audiobook.id)
|
||||
var origAudiobook = null
|
||||
if (index >= 0) {
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ export const state = () => ({
|
|||
showEditModal: false,
|
||||
selectedAudiobook: null,
|
||||
playOnLoad: false,
|
||||
isScanning: false,
|
||||
isScanningCovers: false,
|
||||
scanProgress: null,
|
||||
coverScanProgress: null,
|
||||
// isScanning: false,
|
||||
// isScanningCovers: false,
|
||||
// scanProgress: null,
|
||||
// coverScanProgress: null,
|
||||
developerMode: false,
|
||||
selectedAudiobooks: [],
|
||||
processingBatch: false,
|
||||
|
|
@ -113,20 +113,20 @@ export const mutations = {
|
|||
setShowEditModal(state, val) {
|
||||
state.showEditModal = val
|
||||
},
|
||||
setIsScanning(state, isScanning) {
|
||||
state.isScanning = isScanning
|
||||
},
|
||||
setScanProgress(state, scanProgress) {
|
||||
if (scanProgress && scanProgress.progress > 0) state.isScanning = true
|
||||
state.scanProgress = scanProgress
|
||||
},
|
||||
setIsScanningCovers(state, isScanningCovers) {
|
||||
state.isScanningCovers = isScanningCovers
|
||||
},
|
||||
setCoverScanProgress(state, coverScanProgress) {
|
||||
if (coverScanProgress && coverScanProgress.progress > 0) state.isScanningCovers = true
|
||||
state.coverScanProgress = coverScanProgress
|
||||
},
|
||||
// setIsScanning(state, isScanning) {
|
||||
// state.isScanning = isScanning
|
||||
// },
|
||||
// setScanProgress(state, scanProgress) {
|
||||
// if (scanProgress && scanProgress.progress > 0) state.isScanning = true
|
||||
// state.scanProgress = scanProgress
|
||||
// },
|
||||
// setIsScanningCovers(state, isScanningCovers) {
|
||||
// state.isScanningCovers = isScanningCovers
|
||||
// },
|
||||
// setCoverScanProgress(state, coverScanProgress) {
|
||||
// if (coverScanProgress && coverScanProgress.progress > 0) state.isScanningCovers = true
|
||||
// state.coverScanProgress = coverScanProgress
|
||||
// },
|
||||
setDeveloperMode(state, val) {
|
||||
state.developerMode = val
|
||||
},
|
||||
|
|
|
|||
144
client/store/libraries.js
Normal file
144
client/store/libraries.js
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
export const state = () => ({
|
||||
libraries: [],
|
||||
lastLoad: 0,
|
||||
listeners: [],
|
||||
currentLibraryId: 'main',
|
||||
showModal: false,
|
||||
folders: [],
|
||||
folderLastUpdate: 0
|
||||
})
|
||||
|
||||
export const getters = {
|
||||
getCurrentLibrary: state => {
|
||||
return state.libraries.find(lib => lib.id === state.currentLibraryId)
|
||||
}
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
loadFolders({ state, commit }) {
|
||||
if (state.folders.length) {
|
||||
var lastCheck = Date.now() - state.folderLastUpdate
|
||||
if (lastCheck < 1000 * 60 * 10) { // 10 minutes
|
||||
// Folders up to date
|
||||
return state.folders
|
||||
}
|
||||
}
|
||||
console.log('Loading folders')
|
||||
commit('setFoldersLastUpdate')
|
||||
|
||||
return this.$axios
|
||||
.$get('/api/filesystem')
|
||||
.then((res) => {
|
||||
console.log('Settings folders', res)
|
||||
commit('setFolders', res)
|
||||
return res
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed to load dirs', error)
|
||||
commit('setFolders', [])
|
||||
return []
|
||||
})
|
||||
},
|
||||
fetch({ state, commit, rootState }, libraryId) {
|
||||
if (!rootState.user || !rootState.user.user) {
|
||||
console.error('libraries/fetch - User not set')
|
||||
return false
|
||||
}
|
||||
|
||||
var library = state.libraries.find(lib => lib.id === libraryId)
|
||||
if (library) {
|
||||
commit('setCurrentLibrary', libraryId)
|
||||
return library
|
||||
}
|
||||
|
||||
return this.$axios
|
||||
.$get(`/api/library/${libraryId}`)
|
||||
.then((data) => {
|
||||
commit('addUpdate', data)
|
||||
commit('setCurrentLibrary', libraryId)
|
||||
return data
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed', error)
|
||||
return false
|
||||
})
|
||||
},
|
||||
// Return true if calling load
|
||||
load({ state, commit, rootState }) {
|
||||
if (!rootState.user || !rootState.user.user) {
|
||||
console.error('libraries/load - User not set')
|
||||
return false
|
||||
}
|
||||
|
||||
// Don't load again if already loaded in the last 5 minutes
|
||||
var lastLoadDiff = Date.now() - state.lastLoad
|
||||
if (lastLoadDiff < 5 * 60 * 1000) {
|
||||
// Already up to date
|
||||
return false
|
||||
}
|
||||
|
||||
this.$axios
|
||||
.$get(`/api/libraries`)
|
||||
.then((data) => {
|
||||
commit('set', data)
|
||||
commit('setLastLoad')
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed', error)
|
||||
commit('set', [])
|
||||
})
|
||||
return true
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
setFolders(state, folders) {
|
||||
state.folders = folders
|
||||
},
|
||||
setFoldersLastUpdate(state) {
|
||||
state.folderLastUpdate = Date.now()
|
||||
},
|
||||
setShowModal(state, val) {
|
||||
state.showModal = val
|
||||
},
|
||||
setLastLoad(state) {
|
||||
state.lastLoad = Date.now()
|
||||
},
|
||||
setCurrentLibrary(state, val) {
|
||||
state.currentLibraryId = val
|
||||
},
|
||||
set(state, libraries) {
|
||||
state.libraries = libraries
|
||||
state.listeners.forEach((listener) => {
|
||||
listener.meth()
|
||||
})
|
||||
},
|
||||
addUpdate(state, library) {
|
||||
var index = state.libraries.findIndex(a => a.id === library.id)
|
||||
if (index >= 0) {
|
||||
state.libraries.splice(index, 1, library)
|
||||
} else {
|
||||
state.libraries.push(library)
|
||||
}
|
||||
|
||||
state.listeners.forEach((listener) => {
|
||||
listener.meth()
|
||||
})
|
||||
},
|
||||
remove(state, library) {
|
||||
state.libraries = state.libraries.filter(a => a.id !== library.id)
|
||||
|
||||
state.listeners.forEach((listener) => {
|
||||
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)
|
||||
}
|
||||
}
|
||||
27
client/store/scanners.js
Normal file
27
client/store/scanners.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
export const state = () => ({
|
||||
libraryScans: []
|
||||
})
|
||||
|
||||
export const getters = {
|
||||
getLibraryScan: state => id => {
|
||||
return state.libraryScans.find(ls => ls.id === id)
|
||||
}
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
addUpdate(state, data) {
|
||||
var index = state.libraryScans.findIndex(lib => lib.id === data.id)
|
||||
if (index >= 0) {
|
||||
state.libraryScans.splice(index, 1, data)
|
||||
} else {
|
||||
state.libraryScans.push(data)
|
||||
}
|
||||
},
|
||||
remove(state, data) {
|
||||
state.libraryScans = state.libraryScans.filter(scan => scan.id !== data.id)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue