mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-01-27 16:29:30 +01:00
Adding files tables, fixing loading when switching streams
This commit is contained in:
parent
6e8fe32bf5
commit
7e482352b1
@ -5,12 +5,14 @@ export { default as AppAppbar } from '../..\\components\\app\\Appbar.vue'
|
|||||||
export { default as AppBookShelf } from '../..\\components\\app\\BookShelf.vue'
|
export { default as AppBookShelf } from '../..\\components\\app\\BookShelf.vue'
|
||||||
export { default as AppBookShelfToolbar } from '../..\\components\\app\\BookShelfToolbar.vue'
|
export { default as AppBookShelfToolbar } from '../..\\components\\app\\BookShelfToolbar.vue'
|
||||||
export { default as AppStreamContainer } from '../..\\components\\app\\StreamContainer.vue'
|
export { default as AppStreamContainer } from '../..\\components\\app\\StreamContainer.vue'
|
||||||
export { default as AppTracksTable } from '../..\\components\\app\\TracksTable.vue'
|
|
||||||
export { default as CardsBookCard } from '../..\\components\\cards\\BookCard.vue'
|
export { default as CardsBookCard } from '../..\\components\\cards\\BookCard.vue'
|
||||||
export { default as CardsBookCover } from '../..\\components\\cards\\BookCover.vue'
|
export { default as CardsBookCover } from '../..\\components\\cards\\BookCover.vue'
|
||||||
export { default as ControlsVolumeControl } from '../..\\components\\controls\\VolumeControl.vue'
|
export { default as ControlsVolumeControl } from '../..\\components\\controls\\VolumeControl.vue'
|
||||||
export { default as ModalsEditModal } from '../..\\components\\modals\\EditModal.vue'
|
export { default as ModalsEditModal } from '../..\\components\\modals\\EditModal.vue'
|
||||||
export { default as ModalsModal } from '../..\\components\\modals\\Modal.vue'
|
export { default as ModalsModal } from '../..\\components\\modals\\Modal.vue'
|
||||||
|
export { default as TablesAudioFilesTable } from '../..\\components\\tables\\AudioFilesTable.vue'
|
||||||
|
export { default as TablesOtherFilesTable } from '../..\\components\\tables\\OtherFilesTable.vue'
|
||||||
|
export { default as TablesTracksTable } from '../..\\components\\tables\\TracksTable.vue'
|
||||||
export { default as UiBtn } from '../..\\components\\ui\\Btn.vue'
|
export { default as UiBtn } from '../..\\components\\ui\\Btn.vue'
|
||||||
export { default as UiLoadingIndicator } from '../..\\components\\ui\\LoadingIndicator.vue'
|
export { default as UiLoadingIndicator } from '../..\\components\\ui\\LoadingIndicator.vue'
|
||||||
export { default as UiMenu } from '../..\\components\\ui\\Menu.vue'
|
export { default as UiMenu } from '../..\\components\\ui\\Menu.vue'
|
||||||
@ -30,12 +32,14 @@ export const LazyAppAppbar = import('../..\\components\\app\\Appbar.vue' /* webp
|
|||||||
export const LazyAppBookShelf = import('../..\\components\\app\\BookShelf.vue' /* webpackChunkName: "components/app-book-shelf" */).then(c => wrapFunctional(c.default || c))
|
export const LazyAppBookShelf = import('../..\\components\\app\\BookShelf.vue' /* webpackChunkName: "components/app-book-shelf" */).then(c => wrapFunctional(c.default || c))
|
||||||
export const LazyAppBookShelfToolbar = import('../..\\components\\app\\BookShelfToolbar.vue' /* webpackChunkName: "components/app-book-shelf-toolbar" */).then(c => wrapFunctional(c.default || c))
|
export const LazyAppBookShelfToolbar = import('../..\\components\\app\\BookShelfToolbar.vue' /* webpackChunkName: "components/app-book-shelf-toolbar" */).then(c => wrapFunctional(c.default || c))
|
||||||
export const LazyAppStreamContainer = import('../..\\components\\app\\StreamContainer.vue' /* webpackChunkName: "components/app-stream-container" */).then(c => wrapFunctional(c.default || c))
|
export const LazyAppStreamContainer = import('../..\\components\\app\\StreamContainer.vue' /* webpackChunkName: "components/app-stream-container" */).then(c => wrapFunctional(c.default || c))
|
||||||
export const LazyAppTracksTable = import('../..\\components\\app\\TracksTable.vue' /* webpackChunkName: "components/app-tracks-table" */).then(c => wrapFunctional(c.default || c))
|
|
||||||
export const LazyCardsBookCard = import('../..\\components\\cards\\BookCard.vue' /* webpackChunkName: "components/cards-book-card" */).then(c => wrapFunctional(c.default || c))
|
export const LazyCardsBookCard = import('../..\\components\\cards\\BookCard.vue' /* webpackChunkName: "components/cards-book-card" */).then(c => wrapFunctional(c.default || c))
|
||||||
export const LazyCardsBookCover = import('../..\\components\\cards\\BookCover.vue' /* webpackChunkName: "components/cards-book-cover" */).then(c => wrapFunctional(c.default || c))
|
export const LazyCardsBookCover = import('../..\\components\\cards\\BookCover.vue' /* webpackChunkName: "components/cards-book-cover" */).then(c => wrapFunctional(c.default || c))
|
||||||
export const LazyControlsVolumeControl = import('../..\\components\\controls\\VolumeControl.vue' /* webpackChunkName: "components/controls-volume-control" */).then(c => wrapFunctional(c.default || c))
|
export const LazyControlsVolumeControl = import('../..\\components\\controls\\VolumeControl.vue' /* webpackChunkName: "components/controls-volume-control" */).then(c => wrapFunctional(c.default || c))
|
||||||
export const LazyModalsEditModal = import('../..\\components\\modals\\EditModal.vue' /* webpackChunkName: "components/modals-edit-modal" */).then(c => wrapFunctional(c.default || c))
|
export const LazyModalsEditModal = import('../..\\components\\modals\\EditModal.vue' /* webpackChunkName: "components/modals-edit-modal" */).then(c => wrapFunctional(c.default || c))
|
||||||
export const LazyModalsModal = import('../..\\components\\modals\\Modal.vue' /* webpackChunkName: "components/modals-modal" */).then(c => wrapFunctional(c.default || c))
|
export const LazyModalsModal = import('../..\\components\\modals\\Modal.vue' /* webpackChunkName: "components/modals-modal" */).then(c => wrapFunctional(c.default || c))
|
||||||
|
export const LazyTablesAudioFilesTable = import('../..\\components\\tables\\AudioFilesTable.vue' /* webpackChunkName: "components/tables-audio-files-table" */).then(c => wrapFunctional(c.default || c))
|
||||||
|
export const LazyTablesOtherFilesTable = import('../..\\components\\tables\\OtherFilesTable.vue' /* webpackChunkName: "components/tables-other-files-table" */).then(c => wrapFunctional(c.default || c))
|
||||||
|
export const LazyTablesTracksTable = import('../..\\components\\tables\\TracksTable.vue' /* webpackChunkName: "components/tables-tracks-table" */).then(c => wrapFunctional(c.default || c))
|
||||||
export const LazyUiBtn = import('../..\\components\\ui\\Btn.vue' /* webpackChunkName: "components/ui-btn" */).then(c => wrapFunctional(c.default || c))
|
export const LazyUiBtn = import('../..\\components\\ui\\Btn.vue' /* webpackChunkName: "components/ui-btn" */).then(c => wrapFunctional(c.default || c))
|
||||||
export const LazyUiLoadingIndicator = import('../..\\components\\ui\\LoadingIndicator.vue' /* webpackChunkName: "components/ui-loading-indicator" */).then(c => wrapFunctional(c.default || c))
|
export const LazyUiLoadingIndicator = import('../..\\components\\ui\\LoadingIndicator.vue' /* webpackChunkName: "components/ui-loading-indicator" */).then(c => wrapFunctional(c.default || c))
|
||||||
export const LazyUiMenu = import('../..\\components\\ui\\Menu.vue' /* webpackChunkName: "components/ui-menu" */).then(c => wrapFunctional(c.default || c))
|
export const LazyUiMenu = import('../..\\components\\ui\\Menu.vue' /* webpackChunkName: "components/ui-menu" */).then(c => wrapFunctional(c.default || c))
|
||||||
|
@ -7,12 +7,14 @@ const components = {
|
|||||||
AppBookShelf: () => import('../..\\components\\app\\BookShelf.vue' /* webpackChunkName: "components/app-book-shelf" */).then(c => wrapFunctional(c.default || c)),
|
AppBookShelf: () => import('../..\\components\\app\\BookShelf.vue' /* webpackChunkName: "components/app-book-shelf" */).then(c => wrapFunctional(c.default || c)),
|
||||||
AppBookShelfToolbar: () => import('../..\\components\\app\\BookShelfToolbar.vue' /* webpackChunkName: "components/app-book-shelf-toolbar" */).then(c => wrapFunctional(c.default || c)),
|
AppBookShelfToolbar: () => import('../..\\components\\app\\BookShelfToolbar.vue' /* webpackChunkName: "components/app-book-shelf-toolbar" */).then(c => wrapFunctional(c.default || c)),
|
||||||
AppStreamContainer: () => import('../..\\components\\app\\StreamContainer.vue' /* webpackChunkName: "components/app-stream-container" */).then(c => wrapFunctional(c.default || c)),
|
AppStreamContainer: () => import('../..\\components\\app\\StreamContainer.vue' /* webpackChunkName: "components/app-stream-container" */).then(c => wrapFunctional(c.default || c)),
|
||||||
AppTracksTable: () => import('../..\\components\\app\\TracksTable.vue' /* webpackChunkName: "components/app-tracks-table" */).then(c => wrapFunctional(c.default || c)),
|
|
||||||
CardsBookCard: () => import('../..\\components\\cards\\BookCard.vue' /* webpackChunkName: "components/cards-book-card" */).then(c => wrapFunctional(c.default || c)),
|
CardsBookCard: () => import('../..\\components\\cards\\BookCard.vue' /* webpackChunkName: "components/cards-book-card" */).then(c => wrapFunctional(c.default || c)),
|
||||||
CardsBookCover: () => import('../..\\components\\cards\\BookCover.vue' /* webpackChunkName: "components/cards-book-cover" */).then(c => wrapFunctional(c.default || c)),
|
CardsBookCover: () => import('../..\\components\\cards\\BookCover.vue' /* webpackChunkName: "components/cards-book-cover" */).then(c => wrapFunctional(c.default || c)),
|
||||||
ControlsVolumeControl: () => import('../..\\components\\controls\\VolumeControl.vue' /* webpackChunkName: "components/controls-volume-control" */).then(c => wrapFunctional(c.default || c)),
|
ControlsVolumeControl: () => import('../..\\components\\controls\\VolumeControl.vue' /* webpackChunkName: "components/controls-volume-control" */).then(c => wrapFunctional(c.default || c)),
|
||||||
ModalsEditModal: () => import('../..\\components\\modals\\EditModal.vue' /* webpackChunkName: "components/modals-edit-modal" */).then(c => wrapFunctional(c.default || c)),
|
ModalsEditModal: () => import('../..\\components\\modals\\EditModal.vue' /* webpackChunkName: "components/modals-edit-modal" */).then(c => wrapFunctional(c.default || c)),
|
||||||
ModalsModal: () => import('../..\\components\\modals\\Modal.vue' /* webpackChunkName: "components/modals-modal" */).then(c => wrapFunctional(c.default || c)),
|
ModalsModal: () => import('../..\\components\\modals\\Modal.vue' /* webpackChunkName: "components/modals-modal" */).then(c => wrapFunctional(c.default || c)),
|
||||||
|
TablesAudioFilesTable: () => import('../..\\components\\tables\\AudioFilesTable.vue' /* webpackChunkName: "components/tables-audio-files-table" */).then(c => wrapFunctional(c.default || c)),
|
||||||
|
TablesOtherFilesTable: () => import('../..\\components\\tables\\OtherFilesTable.vue' /* webpackChunkName: "components/tables-other-files-table" */).then(c => wrapFunctional(c.default || c)),
|
||||||
|
TablesTracksTable: () => import('../..\\components\\tables\\TracksTable.vue' /* webpackChunkName: "components/tables-tracks-table" */).then(c => wrapFunctional(c.default || c)),
|
||||||
UiBtn: () => import('../..\\components\\ui\\Btn.vue' /* webpackChunkName: "components/ui-btn" */).then(c => wrapFunctional(c.default || c)),
|
UiBtn: () => import('../..\\components\\ui\\Btn.vue' /* webpackChunkName: "components/ui-btn" */).then(c => wrapFunctional(c.default || c)),
|
||||||
UiLoadingIndicator: () => import('../..\\components\\ui\\LoadingIndicator.vue' /* webpackChunkName: "components/ui-loading-indicator" */).then(c => wrapFunctional(c.default || c)),
|
UiLoadingIndicator: () => import('../..\\components\\ui\\LoadingIndicator.vue' /* webpackChunkName: "components/ui-loading-indicator" */).then(c => wrapFunctional(c.default || c)),
|
||||||
UiMenu: () => import('../..\\components\\ui\\Menu.vue' /* webpackChunkName: "components/ui-menu" */).then(c => wrapFunctional(c.default || c)),
|
UiMenu: () => import('../..\\components\\ui\\Menu.vue' /* webpackChunkName: "components/ui-menu" */).then(c => wrapFunctional(c.default || c)),
|
||||||
|
@ -11,12 +11,14 @@ You can directly use them in pages and other components without the need to impo
|
|||||||
- `<AppBookShelf>` | `<app-book-shelf>` (components/app/BookShelf.vue)
|
- `<AppBookShelf>` | `<app-book-shelf>` (components/app/BookShelf.vue)
|
||||||
- `<AppBookShelfToolbar>` | `<app-book-shelf-toolbar>` (components/app/BookShelfToolbar.vue)
|
- `<AppBookShelfToolbar>` | `<app-book-shelf-toolbar>` (components/app/BookShelfToolbar.vue)
|
||||||
- `<AppStreamContainer>` | `<app-stream-container>` (components/app/StreamContainer.vue)
|
- `<AppStreamContainer>` | `<app-stream-container>` (components/app/StreamContainer.vue)
|
||||||
- `<AppTracksTable>` | `<app-tracks-table>` (components/app/TracksTable.vue)
|
|
||||||
- `<CardsBookCard>` | `<cards-book-card>` (components/cards/BookCard.vue)
|
- `<CardsBookCard>` | `<cards-book-card>` (components/cards/BookCard.vue)
|
||||||
- `<CardsBookCover>` | `<cards-book-cover>` (components/cards/BookCover.vue)
|
- `<CardsBookCover>` | `<cards-book-cover>` (components/cards/BookCover.vue)
|
||||||
- `<ControlsVolumeControl>` | `<controls-volume-control>` (components/controls/VolumeControl.vue)
|
- `<ControlsVolumeControl>` | `<controls-volume-control>` (components/controls/VolumeControl.vue)
|
||||||
- `<ModalsEditModal>` | `<modals-edit-modal>` (components/modals/EditModal.vue)
|
- `<ModalsEditModal>` | `<modals-edit-modal>` (components/modals/EditModal.vue)
|
||||||
- `<ModalsModal>` | `<modals-modal>` (components/modals/Modal.vue)
|
- `<ModalsModal>` | `<modals-modal>` (components/modals/Modal.vue)
|
||||||
|
- `<TablesAudioFilesTable>` | `<tables-audio-files-table>` (components/tables/AudioFilesTable.vue)
|
||||||
|
- `<TablesOtherFilesTable>` | `<tables-other-files-table>` (components/tables/OtherFilesTable.vue)
|
||||||
|
- `<TablesTracksTable>` | `<tables-tracks-table>` (components/tables/TracksTable.vue)
|
||||||
- `<UiBtn>` | `<ui-btn>` (components/ui/Btn.vue)
|
- `<UiBtn>` | `<ui-btn>` (components/ui/Btn.vue)
|
||||||
- `<UiLoadingIndicator>` | `<ui-loading-indicator>` (components/ui/LoadingIndicator.vue)
|
- `<UiLoadingIndicator>` | `<ui-loading-indicator>` (components/ui/LoadingIndicator.vue)
|
||||||
- `<UiMenu>` | `<ui-menu>` (components/ui/Menu.vue)
|
- `<UiMenu>` | `<ui-menu>` (components/ui/Menu.vue)
|
||||||
|
@ -14,9 +14,6 @@
|
|||||||
"AppStreamContainer": {
|
"AppStreamContainer": {
|
||||||
"description": "Auto imported from components/app/StreamContainer.vue"
|
"description": "Auto imported from components/app/StreamContainer.vue"
|
||||||
},
|
},
|
||||||
"AppTracksTable": {
|
|
||||||
"description": "Auto imported from components/app/TracksTable.vue"
|
|
||||||
},
|
|
||||||
"CardsBookCard": {
|
"CardsBookCard": {
|
||||||
"description": "Auto imported from components/cards/BookCard.vue"
|
"description": "Auto imported from components/cards/BookCard.vue"
|
||||||
},
|
},
|
||||||
@ -32,6 +29,15 @@
|
|||||||
"ModalsModal": {
|
"ModalsModal": {
|
||||||
"description": "Auto imported from components/modals/Modal.vue"
|
"description": "Auto imported from components/modals/Modal.vue"
|
||||||
},
|
},
|
||||||
|
"TablesAudioFilesTable": {
|
||||||
|
"description": "Auto imported from components/tables/AudioFilesTable.vue"
|
||||||
|
},
|
||||||
|
"TablesOtherFilesTable": {
|
||||||
|
"description": "Auto imported from components/tables/OtherFilesTable.vue"
|
||||||
|
},
|
||||||
|
"TablesTracksTable": {
|
||||||
|
"description": "Auto imported from components/tables/TracksTable.vue"
|
||||||
|
},
|
||||||
"UiBtn": {
|
"UiBtn": {
|
||||||
"description": "Auto imported from components/ui/Btn.vue"
|
"description": "Auto imported from components/ui/Btn.vue"
|
||||||
},
|
},
|
||||||
|
@ -42,11 +42,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<!-- Track -->
|
<!-- Track -->
|
||||||
<div ref="track" class="w-full h-2 bg-gray-700 relative cursor-pointer transform duration-100 hover:scale-y-125" :class="loading ? 'animate-pulse' : ''" @mousemove="mousemoveTrack" @mouseleave="mouseleaveTrack" @click.stop="clickTrack">
|
<div ref="track" class="w-full h-2 bg-gray-700 relative cursor-pointer transform duration-100 hover:scale-y-125 overflow-hidden" @mousemove="mousemoveTrack" @mouseleave="mouseleaveTrack" @click.stop="clickTrack">
|
||||||
<div ref="readyTrack" class="h-full bg-gray-600 absolute top-0 left-0 pointer-events-none" />
|
<div ref="readyTrack" class="h-full bg-gray-500 absolute top-0 left-0 pointer-events-none" />
|
||||||
<div ref="bufferTrack" class="h-full bg-gray-400 absolute top-0 left-0 pointer-events-none" />
|
<div ref="bufferTrack" class="h-full bg-gray-400 absolute top-0 left-0 pointer-events-none" />
|
||||||
<div ref="playedTrack" class="h-full bg-gray-200 absolute top-0 left-0 pointer-events-none" />
|
<div ref="playedTrack" class="h-full bg-gray-200 absolute top-0 left-0 pointer-events-none" />
|
||||||
<div ref="trackCursor" class="h-full w-0.5 bg-gray-50 absolute top-0 left-0 opacity-0 pointer-events-none" />
|
<div ref="trackCursor" class="h-full w-0.5 bg-gray-50 absolute top-0 left-0 opacity-0 pointer-events-none" />
|
||||||
|
<div v-if="loading" class="h-full w-1/4 absolute left-0 top-0 loadingTrack pointer-events-none bg-white bg-opacity-25" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Hover timestamp -->
|
<!-- Hover timestamp -->
|
||||||
@ -97,6 +98,9 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
seek(time) {
|
seek(time) {
|
||||||
|
if (this.loading) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (this.seekLoading) {
|
if (this.seekLoading) {
|
||||||
console.error('Already seek loading', this.seekedTime)
|
console.error('Already seek loading', this.seekedTime)
|
||||||
return
|
return
|
||||||
@ -169,6 +173,7 @@ export default {
|
|||||||
setStreamReady() {
|
setStreamReady() {
|
||||||
this.readyTrackWidth = this.trackWidth
|
this.readyTrackWidth = this.trackWidth
|
||||||
this.$refs.readyTrack.style.width = this.trackWidth + 'px'
|
this.$refs.readyTrack.style.width = this.trackWidth + 'px'
|
||||||
|
console.warn('SET STREAM READY', this.readyTrackWidth)
|
||||||
},
|
},
|
||||||
setChunksReady(chunks, numSegments) {
|
setChunksReady(chunks, numSegments) {
|
||||||
var largestSeg = 0
|
var largestSeg = 0
|
||||||
@ -307,7 +312,6 @@ export default {
|
|||||||
console.error('No audio on paused()')
|
console.error('No audio on paused()')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
console.log('Paused')
|
|
||||||
this.isPaused = this.$refs.audio.paused
|
this.isPaused = this.$refs.audio.paused
|
||||||
},
|
},
|
||||||
playing() {
|
playing() {
|
||||||
@ -321,7 +325,6 @@ export default {
|
|||||||
this.totalDuration = this.audioEl.duration
|
this.totalDuration = this.audioEl.duration
|
||||||
},
|
},
|
||||||
set(url, currentTime, playOnLoad = false) {
|
set(url, currentTime, playOnLoad = false) {
|
||||||
console.log('[AudioPlayer] SET PlayOnLoad ', playOnLoad)
|
|
||||||
if (this.hlsInstance) {
|
if (this.hlsInstance) {
|
||||||
this.terminateStream()
|
this.terminateStream()
|
||||||
}
|
}
|
||||||
@ -342,13 +345,13 @@ export default {
|
|||||||
xhr.setRequestHeader('Authorization', `Bearer ${this.token}`)
|
xhr.setRequestHeader('Authorization', `Bearer ${this.token}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('[AudioPlayer-Set] HLS Config', hlsOptions, this.$secondsToTimestamp(hlsOptions.startPosition))
|
console.log('[AudioPlayer-Set] HLS Config', hlsOptions)
|
||||||
this.hlsInstance = new Hls(hlsOptions)
|
this.hlsInstance = new Hls(hlsOptions)
|
||||||
var audio = this.$refs.audio
|
var audio = this.$refs.audio
|
||||||
audio.volume = this.volume
|
audio.volume = this.volume
|
||||||
this.hlsInstance.attachMedia(audio)
|
this.hlsInstance.attachMedia(audio)
|
||||||
this.hlsInstance.on(Hls.Events.MEDIA_ATTACHED, () => {
|
this.hlsInstance.on(Hls.Events.MEDIA_ATTACHED, () => {
|
||||||
console.log('[HLS] MEDIA ATTACHED')
|
// console.log('[HLS] MEDIA ATTACHED')
|
||||||
this.hlsInstance.loadSource(url)
|
this.hlsInstance.loadSource(url)
|
||||||
|
|
||||||
this.hlsInstance.on(Hls.Events.MANIFEST_PARSED, function () {
|
this.hlsInstance.on(Hls.Events.MANIFEST_PARSED, function () {
|
||||||
@ -366,10 +369,7 @@ export default {
|
|||||||
})
|
})
|
||||||
this.hlsInstance.on(Hls.Events.FRAG_LOADED, (e, data) => {
|
this.hlsInstance.on(Hls.Events.FRAG_LOADED, (e, data) => {
|
||||||
var frag = data.frag
|
var frag = data.frag
|
||||||
console.log('[HLS] Frag Loaded', frag.sn, this.$secondsToTimestamp(frag.start), frag)
|
// console.log('[HLS] Frag Loaded', frag.sn, this.$secondsToTimestamp(frag.start), frag)
|
||||||
})
|
|
||||||
this.hlsInstance.on(Hls.Events.STREAM_STATE_TRANSITION, (e, data) => {
|
|
||||||
console.log('[HLS] Stream State Transition', data)
|
|
||||||
})
|
})
|
||||||
this.hlsInstance.on(Hls.Events.BUFFER_APPENDED, (e, data) => {
|
this.hlsInstance.on(Hls.Events.BUFFER_APPENDED, (e, data) => {
|
||||||
// console.log('[HLS] BUFFER', data)
|
// console.log('[HLS] BUFFER', data)
|
||||||
@ -419,7 +419,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$nextTick(this.init)
|
// this.$nextTick(this.init)
|
||||||
|
this.init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -432,4 +433,17 @@ export default {
|
|||||||
border-right: 6px solid transparent;
|
border-right: 6px solid transparent;
|
||||||
border-top: 6px solid white;
|
border-top: 6px solid white;
|
||||||
}
|
}
|
||||||
|
.loadingTrack {
|
||||||
|
animation-name: loadingTrack;
|
||||||
|
animation-duration: 1s;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
}
|
||||||
|
@keyframes loadingTrack {
|
||||||
|
0% {
|
||||||
|
left: -25%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full h-16 bg-primary relative">
|
<div class="w-full h-16 bg-primary relative">
|
||||||
<div id="appbar" class="absolute top-0 bottom-0 left-0 w-full h-full px-6 py-1 z-10">
|
<div id="appbar" class="absolute top-0 bottom-0 left-0 w-full h-full px-6 py-1 z-20">
|
||||||
<div class="flex h-full items-center">
|
<div class="flex h-full items-center">
|
||||||
<img v-if="!showBack" src="/LogoTransparent.png" class="w-12 h-12 mr-4" />
|
<img v-if="!showBack" src="/LogoTransparent.png" class="w-12 h-12 mr-4" />
|
||||||
<a v-if="showBack" @click="back" class="rounded-full h-12 w-12 flex items-center justify-center hover:bg-white hover:bg-opacity-10 mr-4 cursor-pointer">
|
<a v-if="showBack" @click="back" class="rounded-full h-12 w-12 flex items-center justify-center hover:bg-white hover:bg-opacity-10 mr-4 cursor-pointer">
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
<span v-if="stream" class="material-icons px-4 cursor-pointer" @click="cancelStream">close</span>
|
<span v-if="stream" class="material-icons px-4 cursor-pointer" @click="cancelStream">close</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<audio-player ref="audioPlayer" :loading="!stream" @updateTime="updateTime" @hook:mounted="audioPlayerMounted" />
|
<audio-player ref="audioPlayer" :loading="isLoading" @updateTime="updateTime" @hook:mounted="audioPlayerMounted" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -34,6 +34,14 @@ export default {
|
|||||||
user() {
|
user() {
|
||||||
return this.$store.state.user
|
return this.$store.state.user
|
||||||
},
|
},
|
||||||
|
isLoading() {
|
||||||
|
if (!this.streamAudiobook) return false
|
||||||
|
if (this.stream) {
|
||||||
|
// IF Stream exists, set loading if stream is diff from next stream
|
||||||
|
return this.stream.audiobook.id !== this.streamAudiobook.id
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
streamAudiobook() {
|
streamAudiobook() {
|
||||||
return this.$store.state.streamAudiobook
|
return this.$store.state.streamAudiobook
|
||||||
},
|
},
|
||||||
@ -56,7 +64,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
audioPlayerMounted() {
|
audioPlayerMounted() {
|
||||||
if (this.stream) {
|
if (this.stream) {
|
||||||
// this.$refs.audioPlayer.set(this.playlistUrl)
|
console.log('[STREAM-CONTAINER] audioPlayerMounted w/ Stream', this.stream)
|
||||||
this.openStream()
|
this.openStream()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -77,6 +85,9 @@ export default {
|
|||||||
}
|
}
|
||||||
var currentTime = this.stream.clientCurrentTime || 0
|
var currentTime = this.stream.clientCurrentTime || 0
|
||||||
this.$refs.audioPlayer.set(this.playlistUrl, currentTime, playOnLoad)
|
this.$refs.audioPlayer.set(this.playlistUrl, currentTime, playOnLoad)
|
||||||
|
if (this.stream.isTranscodeComplete) {
|
||||||
|
this.$refs.audioPlayer.setStreamReady()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
streamProgress(data) {
|
streamProgress(data) {
|
||||||
if (!data.numSegments) return
|
if (!data.numSegments) return
|
||||||
@ -87,14 +98,16 @@ export default {
|
|||||||
},
|
},
|
||||||
streamOpen(stream) {
|
streamOpen(stream) {
|
||||||
this.stream = stream
|
this.stream = stream
|
||||||
this.$nextTick(() => {
|
if (this.$refs.audioPlayer) {
|
||||||
|
console.log('[STREAM-CONTAINER] streamOpen', stream)
|
||||||
this.openStream()
|
this.openStream()
|
||||||
})
|
}
|
||||||
},
|
},
|
||||||
streamClosed(streamId) {
|
streamClosed(streamId) {
|
||||||
if (this.stream && this.stream.id === streamId) {
|
if (this.stream && this.stream.id === streamId) {
|
||||||
this.terminateStream()
|
this.terminateStream()
|
||||||
this.$store.commit('clearStreamAudiobook', this.stream.audiobook.id)
|
this.$store.commit('clearStreamAudiobook', this.stream.audiobook.id)
|
||||||
|
this.stream = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
streamReady() {
|
streamReady() {
|
||||||
@ -123,14 +136,6 @@ export default {
|
|||||||
this.$refs.audioPlayer.resetStream(startTime)
|
this.$refs.audioPlayer.resetStream(startTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (this.stream) {
|
|
||||||
console.log('[STREAM_CONTAINER] Mounted with STREAM', this.stream)
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.openStream()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
67
client/components/tables/AudioFilesTable.vue
Normal file
67
client/components/tables/AudioFilesTable.vue
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<template>
|
||||||
|
<div class="w-full my-2">
|
||||||
|
<div class="w-full bg-primary px-6 py-2 flex items-center cursor-pointer" @click.stop="clickBar">
|
||||||
|
<p class="pr-4">Other Audio Files</p>
|
||||||
|
<span class="bg-black-400 rounded-xl py-1 px-2 text-sm font-mono">{{ files.length }}</span>
|
||||||
|
<div class="flex-grow" />
|
||||||
|
<nuxt-link :to="`/audiobook/${audiobookId}/edit`" class="mr-4">
|
||||||
|
<ui-btn small color="primary">Manage Tracks</ui-btn>
|
||||||
|
</nuxt-link>
|
||||||
|
<div class="cursor-pointer h-10 w-10 rounded-full hover:bg-black-400 flex justify-center items-center duration-500" :class="showTracks ? 'transform rotate-180' : ''">
|
||||||
|
<span class="material-icons text-4xl">expand_more</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<transition name="slide">
|
||||||
|
<div class="w-full" v-show="showTracks">
|
||||||
|
<table class="text-sm tracksTable">
|
||||||
|
<tr class="font-book">
|
||||||
|
<th class="text-left">Filename</th>
|
||||||
|
<th class="text-left">Size</th>
|
||||||
|
<th class="text-left">Duration</th>
|
||||||
|
<th class="text-left">Notes</th>
|
||||||
|
</tr>
|
||||||
|
<template v-for="track in files">
|
||||||
|
<tr :key="track.path">
|
||||||
|
<td class="font-book pl-2">
|
||||||
|
{{ track.filename }}
|
||||||
|
</td>
|
||||||
|
<td class="font-mono">
|
||||||
|
{{ $bytesPretty(track.size) }}
|
||||||
|
</td>
|
||||||
|
<td class="font-mono">
|
||||||
|
{{ $secondsToTimestamp(track.duration) }}
|
||||||
|
</td>
|
||||||
|
<td class="text-xs">
|
||||||
|
<p>{{ track.error || '' }}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
files: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
audiobookId: String
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showTracks: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
methods: {
|
||||||
|
clickBar() {
|
||||||
|
this.showTracks = !this.showTracks
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {}
|
||||||
|
}
|
||||||
|
</script>
|
59
client/components/tables/OtherFilesTable.vue
Normal file
59
client/components/tables/OtherFilesTable.vue
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<template>
|
||||||
|
<div class="w-full my-2">
|
||||||
|
<div class="w-full bg-primary px-6 py-2 flex items-center cursor-pointer" @click.stop="clickBar">
|
||||||
|
<p class="pr-4">Other Files</p>
|
||||||
|
<span class="bg-black-400 rounded-xl py-1 px-2 text-sm font-mono">{{ files.length }}</span>
|
||||||
|
<div class="flex-grow" />
|
||||||
|
<!-- <nuxt-link :to="`/audiobook/${audiobookId}/edit`" class="mr-4">
|
||||||
|
<ui-btn small color="primary">Manage Tracks</ui-btn>
|
||||||
|
</nuxt-link> -->
|
||||||
|
<div class="cursor-pointer h-10 w-10 rounded-full hover:bg-black-400 flex justify-center items-center duration-500" :class="showFiles ? 'transform rotate-180' : ''">
|
||||||
|
<span class="material-icons text-4xl">expand_more</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<transition name="slide">
|
||||||
|
<div class="w-full" v-show="showFiles">
|
||||||
|
<table class="text-sm tracksTable">
|
||||||
|
<tr class="font-book">
|
||||||
|
<th class="text-left">Path</th>
|
||||||
|
<th class="text-left">Filetype</th>
|
||||||
|
</tr>
|
||||||
|
<template v-for="file in files">
|
||||||
|
<tr :key="file.path">
|
||||||
|
<td class="font-book pl-2">
|
||||||
|
{{ file.path }}
|
||||||
|
</td>
|
||||||
|
<td class="text-xs">
|
||||||
|
<p>{{ file.filetype }}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
files: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
audiobookId: String
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showFiles: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {},
|
||||||
|
methods: {
|
||||||
|
clickBar() {
|
||||||
|
this.showFiles = !this.showFiles
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {}
|
||||||
|
}
|
||||||
|
</script>
|
@ -5,7 +5,7 @@
|
|||||||
<span class="bg-black-400 rounded-xl py-1 px-2 text-sm font-mono">{{ tracks.length }}</span>
|
<span class="bg-black-400 rounded-xl py-1 px-2 text-sm font-mono">{{ tracks.length }}</span>
|
||||||
<div class="flex-grow" />
|
<div class="flex-grow" />
|
||||||
<nuxt-link :to="`/audiobook/${audiobookId}/edit`" class="mr-4">
|
<nuxt-link :to="`/audiobook/${audiobookId}/edit`" class="mr-4">
|
||||||
<ui-btn small color="primary">Edit Track Order</ui-btn>
|
<ui-btn small color="primary">Manage Tracks</ui-btn>
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<div class="cursor-pointer h-10 w-10 rounded-full hover:bg-black-400 flex justify-center items-center duration-500" :class="showTracks ? 'transform rotate-180' : ''">
|
<div class="cursor-pointer h-10 w-10 rounded-full hover:bg-black-400 flex justify-center items-center duration-500" :class="showTracks ? 'transform rotate-180' : ''">
|
||||||
<span class="material-icons text-4xl">expand_more</span>
|
<span class="material-icons text-4xl">expand_more</span>
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "audiobookshelf-client",
|
"name": "audiobookshelf-client",
|
||||||
"version": "0.9.3",
|
"version": "0.9.4",
|
||||||
"description": "Audiobook manager and player",
|
"description": "Audiobook manager and player",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -47,7 +47,11 @@
|
|||||||
<p class="text-sm font-mono">{{ invalidParts.join(', ') }}</p>
|
<p class="text-sm font-mono">{{ invalidParts.join(', ') }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-tracks-table :tracks="tracks" :audiobook-id="audiobook.id" class="mt-6" />
|
<tables-tracks-table :tracks="tracks" :audiobook-id="audiobook.id" class="mt-6" />
|
||||||
|
|
||||||
|
<tables-audio-files-table v-if="otherAudioFiles.length" :audiobook-id="audiobook.id" :files="otherAudioFiles" class="mt-6" />
|
||||||
|
|
||||||
|
<tables-other-files-table v-if="otherFiles.length" :audiobook-id="audiobook.id" :files="otherFiles" class="mt-6" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -136,9 +140,20 @@ export default {
|
|||||||
book() {
|
book() {
|
||||||
return this.audiobook.book || {}
|
return this.audiobook.book || {}
|
||||||
},
|
},
|
||||||
|
otherFiles() {
|
||||||
|
return this.audiobook.otherFiles || []
|
||||||
|
},
|
||||||
|
otherAudioFiles() {
|
||||||
|
return this.audioFiles.filter((af) => {
|
||||||
|
return !this.tracks.find((t) => t.path === af.path)
|
||||||
|
})
|
||||||
|
},
|
||||||
tracks() {
|
tracks() {
|
||||||
return this.audiobook.tracks || []
|
return this.audiobook.tracks || []
|
||||||
},
|
},
|
||||||
|
audioFiles() {
|
||||||
|
return this.audiobook.audioFiles || []
|
||||||
|
},
|
||||||
description() {
|
description() {
|
||||||
return this.book.description || 'No Description'
|
return this.book.description || 'No Description'
|
||||||
},
|
},
|
||||||
|
@ -25,7 +25,6 @@ export const actions = {
|
|||||||
export const mutations = {
|
export const mutations = {
|
||||||
setUser(state, user) {
|
setUser(state, user) {
|
||||||
state.user = user
|
state.user = user
|
||||||
console.log('SETUSER', user)
|
|
||||||
if (user.token) {
|
if (user.token) {
|
||||||
localStorage.setItem('token', user.token)
|
localStorage.setItem('token', user.token)
|
||||||
}
|
}
|
||||||
@ -58,6 +57,7 @@ export const mutations = {
|
|||||||
state.isScanning = isScanning
|
state.isScanning = isScanning
|
||||||
},
|
},
|
||||||
setScanProgress(state, progress) {
|
setScanProgress(state, progress) {
|
||||||
|
if (progress > 0) state.isScanning = true
|
||||||
state.scanProgress = progress
|
state.scanProgress = progress
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "audiobookshelf",
|
"name": "audiobookshelf",
|
||||||
"version": "0.9.3",
|
"version": "0.9.4",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -14,7 +14,6 @@ class Audiobook {
|
|||||||
this.invalidParts = []
|
this.invalidParts = []
|
||||||
|
|
||||||
this.audioFiles = []
|
this.audioFiles = []
|
||||||
this.ebookFiles = []
|
|
||||||
this.otherFiles = []
|
this.otherFiles = []
|
||||||
|
|
||||||
this.tags = []
|
this.tags = []
|
||||||
@ -38,7 +37,6 @@ class Audiobook {
|
|||||||
this.invalidParts = audiobook.invalidParts
|
this.invalidParts = audiobook.invalidParts
|
||||||
|
|
||||||
this.audioFiles = audiobook.audioFiles
|
this.audioFiles = audiobook.audioFiles
|
||||||
this.ebookFiles = audiobook.ebookFiles
|
|
||||||
this.otherFiles = audiobook.otherFiles
|
this.otherFiles = audiobook.otherFiles
|
||||||
|
|
||||||
this.tags = audiobook.tags
|
this.tags = audiobook.tags
|
||||||
@ -103,7 +101,6 @@ class Audiobook {
|
|||||||
book: this.bookToJSON(),
|
book: this.bookToJSON(),
|
||||||
tracks: this.tracksToJSON(),
|
tracks: this.tracksToJSON(),
|
||||||
audioFiles: this.audioFiles,
|
audioFiles: this.audioFiles,
|
||||||
ebookFiles: this.ebookFiles,
|
|
||||||
otherFiles: this.otherFiles
|
otherFiles: this.otherFiles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +138,6 @@ class Audiobook {
|
|||||||
missingParts: this.missingParts,
|
missingParts: this.missingParts,
|
||||||
invalidParts: this.invalidParts,
|
invalidParts: this.invalidParts,
|
||||||
audioFiles: this.audioFiles,
|
audioFiles: this.audioFiles,
|
||||||
ebookFiles: this.ebookFiles,
|
|
||||||
otherFiles: this.otherFiles,
|
otherFiles: this.otherFiles,
|
||||||
tags: this.tags,
|
tags: this.tags,
|
||||||
book: this.bookToJSON(),
|
book: this.bookToJSON(),
|
||||||
@ -156,7 +152,6 @@ class Audiobook {
|
|||||||
this.addedAt = Date.now()
|
this.addedAt = Date.now()
|
||||||
|
|
||||||
this.otherFiles = data.otherFiles || []
|
this.otherFiles = data.otherFiles || []
|
||||||
this.ebookFiles = data.ebooks || []
|
|
||||||
this.setBook(data)
|
this.setBook(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,8 @@ class Stream extends EventEmitter {
|
|||||||
clientPlaylistUri: this.clientPlaylistUri,
|
clientPlaylistUri: this.clientPlaylistUri,
|
||||||
clientCurrentTime: this.clientCurrentTime,
|
clientCurrentTime: this.clientCurrentTime,
|
||||||
startTime: this.startTime,
|
startTime: this.startTime,
|
||||||
segmentStartNumber: this.segmentStartNumber
|
segmentStartNumber: this.segmentStartNumber,
|
||||||
|
isTranscodeComplete: this.isTranscodeComplete
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,17 +92,14 @@ async function scanParts(audiobook, parts) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var audioFileObj = {
|
|
||||||
path: parts[i],
|
|
||||||
filename: Path.basename(parts[i]),
|
|
||||||
fullPath: fullPath
|
|
||||||
}
|
|
||||||
|
|
||||||
var trackNumFromMeta = getTrackNumberFromMeta(scanData)
|
var trackNumFromMeta = getTrackNumberFromMeta(scanData)
|
||||||
var trackNumFromFilename = getTrackNumberFromFilename(parts[i])
|
var trackNumFromFilename = getTrackNumberFromFilename(parts[i])
|
||||||
|
|
||||||
audioFileObj = {
|
var audioFileObj = {
|
||||||
...audioFileObj,
|
path: Path.join(audiobook.path, parts[i]),
|
||||||
|
ext: Path.extname(parts[i]),
|
||||||
|
filename: parts[i],
|
||||||
|
fullPath: fullPath,
|
||||||
...scanData,
|
...scanData,
|
||||||
trackNumFromMeta,
|
trackNumFromMeta,
|
||||||
trackNumFromFilename
|
trackNumFromFilename
|
||||||
@ -129,15 +126,8 @@ async function scanParts(audiobook, parts) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var track = {
|
audioFileObj.index = trackNumber
|
||||||
index: trackNumber,
|
tracks.push(audioFileObj)
|
||||||
filename: parts[i],
|
|
||||||
ext: Path.extname(parts[i]),
|
|
||||||
path: Path.join(audiobook.path, parts[i]),
|
|
||||||
fullPath: Path.join(audiobook.fullPath, parts[i]),
|
|
||||||
...scanData
|
|
||||||
}
|
|
||||||
tracks.push(track)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tracks.length) {
|
if (!tracks.length) {
|
||||||
|
@ -26,47 +26,44 @@ function getFileType(ext) {
|
|||||||
if (INFO_FORMATS.includes(ext_cleaned)) return 'info'
|
if (INFO_FORMATS.includes(ext_cleaned)) return 'info'
|
||||||
if (IMAGE_FORMATS.includes(ext_cleaned)) return 'image'
|
if (IMAGE_FORMATS.includes(ext_cleaned)) return 'image'
|
||||||
if (EBOOK_FORMATS.includes(ext_cleaned)) return 'ebook'
|
if (EBOOK_FORMATS.includes(ext_cleaned)) return 'ebook'
|
||||||
return null
|
return 'unknown'
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getAllAudiobookFiles(path) {
|
async function getAllAudiobookFiles(path) {
|
||||||
console.log('getAllAudiobooks', path)
|
console.log('getAllAudiobooks', path)
|
||||||
var paths = await getPaths(path)
|
var paths = await getPaths(path)
|
||||||
var books = {}
|
var audiobooks = {}
|
||||||
|
|
||||||
paths.files.forEach((filepath) => {
|
paths.files.forEach((filepath) => {
|
||||||
var relpath = filepath.replace(path, '').slice(1)
|
var relpath = filepath.replace(path, '').slice(1)
|
||||||
var pathformat = Path.parse(relpath)
|
var pathformat = Path.parse(relpath)
|
||||||
var authordir = Path.dirname(pathformat.dir)
|
var authordir = Path.dirname(pathformat.dir)
|
||||||
var bookdir = Path.basename(pathformat.dir)
|
var bookdir = Path.basename(pathformat.dir)
|
||||||
if (!books[bookdir]) {
|
if (!audiobooks[bookdir]) {
|
||||||
books[bookdir] = {
|
audiobooks[bookdir] = {
|
||||||
author: authordir,
|
author: authordir,
|
||||||
title: bookdir,
|
title: bookdir,
|
||||||
path: pathformat.dir,
|
path: pathformat.dir,
|
||||||
fullPath: Path.join(path, pathformat.dir),
|
fullPath: Path.join(path, pathformat.dir),
|
||||||
parts: [],
|
parts: [],
|
||||||
infos: [],
|
|
||||||
images: [],
|
|
||||||
ebooks: [],
|
|
||||||
otherFiles: []
|
otherFiles: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var filetype = getFileType(pathformat.ext)
|
var filetype = getFileType(pathformat.ext)
|
||||||
if (filetype === 'abpart') {
|
if (filetype === 'abpart') {
|
||||||
books[bookdir].parts.push(`${pathformat.name}${pathformat.ext}`)
|
audiobooks[bookdir].parts.push(pathformat.base)
|
||||||
} else if (filetype === 'info') {
|
|
||||||
books[bookdir].infos.push(`${pathformat.name}${pathformat.ext}`)
|
|
||||||
} else if (filetype === 'image') {
|
|
||||||
books[bookdir].images.push(`${pathformat.name}${pathformat.ext}`)
|
|
||||||
} else if (filetype === 'ebook') {
|
|
||||||
books[bookdir].ebooks.push(`${pathformat.name}${pathformat.ext}`)
|
|
||||||
} else {
|
} else {
|
||||||
Logger.warn('Invalid file type', pathformat.name, pathformat.ext)
|
var fileObj = {
|
||||||
books[bookdir].otherFiles.push(`${pathformat.name}${pathformat.ext}`)
|
filetype: filetype,
|
||||||
|
filename: pathformat.base,
|
||||||
|
path: relpath,
|
||||||
|
fullPath: filepath,
|
||||||
|
ext: pathformat.ext
|
||||||
|
}
|
||||||
|
audiobooks[bookdir].otherFiles.push(fileObj)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return Object.values(books)
|
return Object.values(audiobooks)
|
||||||
}
|
}
|
||||||
module.exports.getAllAudiobookFiles = getAllAudiobookFiles
|
module.exports.getAllAudiobookFiles = getAllAudiobookFiles
|
Loading…
Reference in New Issue
Block a user