2022-05-11 00:03:41 +02:00
< template >
< div id = "page-wrapper" class = "bg-bg page overflow-y-auto relative" : class = "streamLibraryItem ? 'streaming' : ''" >
< div class = "flex items-center py-4 max-w-7xl mx-auto" >
< nuxt -link :to ="`/item/${libraryItem.id}`" class = "hover:underline" >
< h1 class = "text-xl" > { { title } } < / h1 >
< / n u x t - l i n k >
< button class = "w-7 h-7 flex items-center justify-center mx-4 hover:scale-110 duration-100 transform text-gray-200 hover:text-white" @click ="editItem" >
< span class = "material-icons text-base" > edit < / span >
< / button >
< div class = "flex-grow" / >
2022-11-08 01:27:17 +01:00
< p class = "text-base" > { { $strings . LabelDuration } } : < / p >
2022-09-30 00:55:45 +02:00
< p class = "text-base font-mono ml-8" > { { $secondsToTimestamp ( mediaDurationRounded ) } } < / p >
2022-05-11 00:03:41 +02:00
< / div >
< div class = "flex flex-wrap-reverse justify-center py-4" >
< div class = "w-full max-w-3xl py-4" >
< div class = "flex items-center" >
2022-11-08 01:27:17 +01:00
< p class = "text-lg mb-4 font-semibold" > { { $strings . HeaderChapters } } < / p >
2022-05-11 00:03:41 +02:00
< div class = "flex-grow" / >
2022-07-26 01:40:11 +02:00
< ui -checkbox v -model = " showSecondInputs " checkbox -bg = " primary " small label -class = " text -sm text -gray -200 pl -1 " label = "Show seconds" class = "mx-2" / >
2022-10-06 01:01:42 +02:00
< div class = "w-40" / >
< / div >
< div class = "flex items-center mb-3 py-1" >
< div class = "flex-grow" / >
2022-11-08 01:27:17 +01:00
< ui -btn v-if ="newChapters.length > 1" :color="showShiftTimes ? 'bg' : 'primary'" small @click="showShiftTimes = !showShiftTimes" > {{ $ strings.ButtonShiftTimes }} < / ui -btn >
< ui -btn color = "primary" small class = "mx-2" @ click = "showFindChaptersModal = true" > { { $strings . ButtonLookup } } < / u i - b t n >
< ui -btn color = "success" small @click ="saveChapters" > {{ $ strings.ButtonSave }} < / ui -btn >
2022-05-11 00:03:41 +02:00
< div class = "w-40" / >
< / div >
2022-10-06 01:01:42 +02:00
< div class = "overflow-hidden" >
< transition name = "slide" >
< div v-if ="showShiftTimes" class="flex mb-4" >
< div class = "w-12" > < / div >
< div class = "flex-grow" >
< div class = "flex items-center" >
2022-11-08 01:27:17 +01:00
< p class = "text-sm mb-1 font-semibold pr-2" > { { $strings . LabelTimeToShift } } < / p >
2022-10-06 01:01:42 +02:00
< ui -text -input v -model = " shiftAmount " type = "number" class = "max-w-20" style = "height: 30px" / >
2022-11-08 01:27:17 +01:00
< ui -btn color = "primary" class = "mx-1" small @click ="shiftChapterTimes" > {{ $ strings.ButtonAdd }} < / ui -btn >
2022-10-06 01:01:42 +02:00
< div class = "flex-grow" / >
< span class = "material-icons text-gray-200 hover:text-white cursor-pointer" @ click = "showShiftTimes = false" > close < / span >
< / div >
2022-11-08 01:27:17 +01:00
< p class = "text-xs py-1.5 text-gray-300 max-w-md" > { { $strings . NoteChapterEditorTimes } } < / p >
2022-10-06 01:01:42 +02:00
< / div >
< div class = "w-40" > < / div >
< / div >
< / transition >
< / div >
2022-05-11 00:03:41 +02:00
< div class = "flex text-xs uppercase text-gray-300 font-semibold mb-2" >
< div class = "w-12" > < / div >
2022-11-08 01:27:17 +01:00
< div class = "w-32 px-2" > { { $strings . LabelStart } } < / div >
< div class = "flex-grow px-2" > { { $strings . LabelTitle } } < / div >
2022-05-11 00:03:41 +02:00
< div class = "w-40" > < / div >
< / div >
< template v-for ="chapter in newChapters" >
< div :key ="chapter.id" class = "flex py-1" >
< div class = "w-12" > # { { chapter . id + 1 } } < / div >
< div class = "w-32 px-1" >
2022-07-26 01:40:11 +02:00
< ui -text -input v -if = " showSecondInputs " v -model = " chapter.start " type = "number" class = "text-xs" @change ="checkChapters" / >
2022-07-26 02:32:04 +02:00
< ui -time -picker v -else class = "text-xs" v -model = " chapter.start " : show -three -digit -hour = " mediaDuration > = 360000 " @change=" checkChapters " / >
2022-05-11 00:03:41 +02:00
< / div >
< div class = "flex-grow px-1" >
< ui -text -input v -model = " chapter.title " class = "text-xs" / >
< / div >
< div class = "w-40 px-2 py-1" >
< div class = "flex items-center" >
2022-11-20 18:50:34 +01:00
< ui -tooltip :text ="$strings.MessageRemoveChapter" direction = "bottom" >
< button v-if ="newChapters.length > 1" class="w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-error transform hover:scale-110 duration-150" @click="removeChapter(chapter)" >
< span class = "material-icons-outlined text-base" > remove < / span >
< / button >
< / u i - t o o l t i p >
2022-05-11 00:03:41 +02:00
2022-11-08 01:27:17 +01:00
< ui -tooltip :text ="$strings.MessageInsertChapterBelow" direction = "bottom" >
2022-05-11 00:03:41 +02:00
< button class = "w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-success transform hover:scale-110 duration-150" @click ="addChapter(chapter)" >
< span class = "material-icons text-lg" > add < / span >
< / button >
< / u i - t o o l t i p >
2022-11-20 18:50:34 +01:00
< ui -tooltip : text = "selectedChapterId === chapter.id && isPlayingChapter ? $strings.MessagePauseChapter : $strings.MessagePlayChapter" direction = "bottom" >
< button class = "w-7 h-7 rounded-full flex items-center justify-center text-gray-300 hover:text-white transform hover:scale-110 duration-150" @click ="playChapter(chapter)" >
< widgets -loading -spinner v -if = " selectedChapterId = = = chapter.id & & isLoadingChapter " / >
< span v -else -if = " selectedChapterId = = = chapter.id & & isPlayingChapter " class = "material-icons-outlined text-base" > pause < / span >
< span v -else class = "material-icons-outlined text-base" > play _arrow < / span >
< / button >
< / u i - t o o l t i p >
2022-05-11 00:03:41 +02:00
< ui -tooltip v-if ="chapter.error" :text="chapter.error" direction="left" >
< button class = "w-7 h-7 rounded-full flex items-center justify-center text-error" >
< span class = "material-icons-outlined text-lg" > error _outline < / span >
< / button >
< / u i - t o o l t i p >
< / div >
< / div >
< / div >
< / template >
< / div >
< div class = "w-full max-w-xl py-4" >
2022-11-28 23:55:13 +01:00
< div class = "flex items-center mb-4 py-1" >
< p class = "text-lg font-semibold" > { { $strings . HeaderAudioTracks } } < / p >
< div class = "flex-grow" / >
< ui -btn small @click ="setChaptersFromTracks" > Set chapters from tracks < / ui -btn >
< ui -tooltip : text = "'Set chapters using each audio file as a chapter and chapter title as the audio file name'" direction = "top" class = "flex items-center mx-1 cursor-default" >
< span class = "material-icons-outlined text-xl text-gray-200" > info < / span >
< / u i - t o o l t i p >
< / div >
2022-05-11 00:03:41 +02:00
< div class = "flex text-xs uppercase text-gray-300 font-semibold mb-2" >
2022-11-08 01:27:17 +01:00
< div class = "flex-grow" > { { $strings . LabelFilename } } < / div >
< div class = "w-20" > { { $strings . LabelDuration } } < / div >
< div class = "w-20 text-center" > { { $strings . HeaderChapters } } < / div >
2022-05-11 00:03:41 +02:00
< / div >
< template v-for ="track in audioTracks" >
< div :key ="track.ino" class = "flex items-center py-2" : class = "currentTrackIndex === track.index && isPlayingChapter ? 'bg-success bg-opacity-10' : ''" >
< div class = "flex-grow" >
< p class = "text-xs truncate max-w-sm" > { { track . metadata . filename } } < / p >
< / div >
< div class = "w-20" style = "min-width: 80px" >
2022-09-30 00:55:45 +02:00
< p class = "text-xs font-mono text-gray-200" > { { $secondsToTimestamp ( Math . round ( track . duration ) , false , true ) } } < / p >
2022-05-11 00:03:41 +02:00
< / div >
< div class = "w-20 flex justify-center" style = "min-width: 80px" >
< span v-if ="(track.chapters || []).length" class="material-icons text-success text-sm" > check < / span >
< / div >
< / div >
< / template >
< / div >
< / div >
< div v-if ="saving" class="w-full h-full absolute top-0 left-0 bottom-0 right-0 z-30 bg-black bg-opacity-25 flex items-center justify-center" >
< ui -loading -indicator / >
< / div >
< modals -modal v-model ="showFindChaptersModal" name="edit-book" :width="500" :processing ="findingChapters" >
< template # outer >
< div class = "absolute top-0 left-0 p-5 w-2/3 overflow-hidden pointer-events-none" >
2022-11-08 01:27:17 +01:00
< p class = "font-book text-3xl text-white truncate pointer-events-none" > { { $strings . HeaderFindChapters } } < / p >
2022-05-11 00:03:41 +02:00
< / div >
< / template >
< div class = "w-full h-full max-h-full text-sm rounded-lg bg-bg shadow-lg border border-black-300 relative" >
< div v-if ="!chapterData" class="flex p-20" >
< ui -text -input -with -label v -model = " asinInput " label = "ASIN" / >
2022-11-08 01:27:17 +01:00
< ui -dropdown v -model = " regionInput " :label ="$strings.LabelRegion" small :items ="audibleRegions" class = "w-32 mx-1" / >
< ui -btn small color = "primary" class = "mt-5" @click ="findChapters" > {{ $ strings.ButtonSearch }} < / ui -btn >
2022-05-11 00:03:41 +02:00
< / div >
< div v -else class = "w-full p-4" >
2022-09-30 00:55:45 +02:00
< div class = "flex justify-between mb-4" >
< p >
2022-11-09 00:10:08 +01:00
{ { $strings . LabelDurationFound } } < span class = "font-semibold" > { { $secondsToTimestamp ( chapterData . runtimeLengthSec ) } } < / s p a n
2022-11-02 23:28:26 +01:00
> < br / >
2022-11-09 00:10:08 +01:00
< span class = "font-semibold" : class = "{ 'text-warning': chapters.length !== chapterData.chapters.length }" > { { chapterData . chapters . length } } < / span > { { $strings . LabelChaptersFound } }
2022-09-30 00:55:45 +02:00
< / p >
< p >
2022-11-09 00:10:08 +01:00
{ { $strings . LabelYourAudiobookDuration } } : < span class = "font-semibold" > { { $secondsToTimestamp ( mediaDurationRounded ) } } < / s p a n
2022-11-02 23:28:26 +01:00
> < br / >
Your audiobook has < span class = "font-semibold" : class = "{ 'text-warning': chapters.length !== chapterData.chapters.length }" > { { chapters . length } } < / span > chapters
2022-09-30 00:55:45 +02:00
< / p >
2022-05-11 00:03:41 +02:00
< / div >
2022-11-09 00:10:08 +01:00
< widgets -alert v-if ="chapterData.runtimeLengthSec > mediaDurationRounded" type="warning" class="mb-2" > {{ $ strings.MessageYourAudiobookDurationIsShorter }} < / widgets -alert >
< widgets -alert v -else -if = " chapterData.runtimeLengthSec < mediaDurationRounded " type = "warning" class = "mb-2" > { { $strings . MessageYourAudiobookDurationIsLonger } } < / w i d g e t s - a l e r t >
2022-05-11 00:03:41 +02:00
< div class = "flex py-0.5 text-xs font-semibold uppercase text-gray-300 mb-1" >
2022-11-08 01:27:17 +01:00
< div class = "w-24 px-2" > { { $strings . LabelStart } } < / div >
< div class = "flex-grow px-2" > { { $strings . LabelTitle } } < / div >
2022-05-11 00:03:41 +02:00
< / div >
< div class = "w-full max-h-80 overflow-y-auto my-2" >
< div v-for ="(chapter, index) in chapterData.chapters" :key="index" class="flex py-0.5 text-xs" :class="chapter.startOffsetSec > mediaDuration ? 'bg-error bg-opacity-20' : chapter.startOffsetSec + chapter.lengthMs / 1000 > mediaDuration ? 'bg-warning bg-opacity-20' : index % 2 === 0 ? 'bg-primary bg-opacity-30' : ''" >
< div class = "w-24 min-w-24 px-2" >
< p class = "font-mono" > { { $secondsToTimestamp ( chapter . startOffsetSec ) } } < / p >
< / div >
< div class = "flex-grow px-2" >
< p class = "truncate max-w-sm" > { { chapter . title } } < / p >
< / div >
< / div >
< / div >
2022-09-30 00:55:45 +02:00
< div v-if ="chapterData.runtimeLengthSec > mediaDurationRounded" class="w-full pt-2" >
< div class = "flex items-center" >
< div class = "w-2 h-2 bg-warning bg-opacity-50" / >
2022-11-09 00:10:08 +01:00
< p class = "pl-2" > { { $strings . MessageChapterEndIsAfter } } < / p >
2022-09-30 00:55:45 +02:00
< / div >
< div class = "flex items-center" >
< div class = "w-2 h-2 bg-error bg-opacity-50" / >
2022-11-09 00:10:08 +01:00
< p class = "pl-2" > { { $strings . MessageChapterStartIsAfter } } < / p >
2022-09-30 00:55:45 +02:00
< / div >
< / div >
2022-09-30 01:06:13 +02:00
< div class = "flex items-center pt-2" >
2022-11-08 01:27:17 +01:00
< ui -btn small color = "primary" class = "mr-1" @click ="applyChapterNamesOnly" > {{ $ strings.ButtonMapChapterTitles }} < / ui -btn >
2022-11-28 23:55:13 +01:00
< ui -tooltip :text ="$strings.MessageMapChapterTitles" direction = "top" class = "flex items-center" >
< span class = "material-icons-outlined text-xl text-gray-200" > info < / span >
2022-09-30 01:06:13 +02:00
< / u i - t o o l t i p >
2022-05-11 00:03:41 +02:00
< div class = "flex-grow" / >
2022-11-08 01:27:17 +01:00
< ui -btn small color = "success" @click ="applyChapterData" > {{ $ strings.ButtonApplyChapters }} < / ui -btn >
2022-05-11 00:03:41 +02:00
< / div >
< / div >
< / div >
< / m o d a l s - m o d a l >
< / div >
< / template >
< script >
2022-11-28 23:55:13 +01:00
import path from 'path'
2022-05-11 00:03:41 +02:00
export default {
2022-07-26 01:57:00 +02:00
async asyncData ( { store , params , app , redirect , from } ) {
2022-05-11 00:03:41 +02:00
if ( ! store . getters [ 'user/getUserCanUpdate' ] ) {
return redirect ( '/?error=unauthorized' )
}
var libraryItem = await app . $axios . $get ( ` /api/items/ ${ params . id } ?expanded=1 ` ) . catch ( ( error ) => {
console . error ( 'Failed' , error )
return false
} )
if ( ! libraryItem ) {
console . error ( 'Not found...' , params . id )
return redirect ( '/' )
}
if ( libraryItem . mediaType != 'book' ) {
console . error ( 'Invalid media type' )
return redirect ( '/' )
}
2022-07-26 01:57:00 +02:00
var previousRoute = from ? from . fullPath : null
if ( from && from . path === '/login' ) previousRoute = null
2022-05-11 00:03:41 +02:00
return {
2022-07-26 01:57:00 +02:00
libraryItem ,
previousRoute
2022-05-11 00:03:41 +02:00
}
} ,
data ( ) {
return {
newChapters : [ ] ,
selectedChapter : null ,
2022-10-06 01:01:42 +02:00
showShiftTimes : false ,
shiftAmount : 0 ,
2022-05-11 00:03:41 +02:00
audioEl : null ,
isPlayingChapter : false ,
isLoadingChapter : false ,
currentTrackIndex : 0 ,
saving : false ,
asinInput : null ,
2022-10-15 22:31:07 +02:00
regionInput : 'US' ,
2022-05-11 00:03:41 +02:00
findingChapters : false ,
showFindChaptersModal : false ,
2022-07-26 01:40:11 +02:00
chapterData : null ,
2022-10-15 22:31:07 +02:00
showSecondInputs : false ,
audibleRegions : [ 'US' , 'CA' , 'UK' , 'AU' , 'FR' , 'DE' , 'JP' , 'IT' , 'IN' , 'ES' ]
2022-05-11 00:03:41 +02:00
}
} ,
computed : {
streamLibraryItem ( ) {
return this . $store . state . streamLibraryItem
} ,
userToken ( ) {
return this . $store . getters [ 'user/getToken' ]
} ,
media ( ) {
return this . libraryItem . media || { }
} ,
mediaMetadata ( ) {
return this . media . metadata || { }
} ,
title ( ) {
return this . mediaMetadata . title
} ,
mediaDuration ( ) {
return this . media . duration
} ,
2022-09-30 00:55:45 +02:00
mediaDurationRounded ( ) {
return Math . round ( this . mediaDuration )
} ,
2022-05-11 00:03:41 +02:00
chapters ( ) {
return this . media . chapters || [ ]
} ,
tracks ( ) {
return this . media . tracks || [ ]
} ,
audioFiles ( ) {
return this . media . audioFiles || [ ]
} ,
audioTracks ( ) {
return this . audioFiles . filter ( ( af ) => ! af . exclude && ! af . invalid )
} ,
selectedChapterId ( ) {
return this . selectedChapter ? this . selectedChapter . id : null
}
} ,
methods : {
2022-11-28 23:55:13 +01:00
setChaptersFromTracks ( ) {
let currentStartTime = 0
let index = 0
const chapters = [ ]
for ( const track of this . audioTracks ) {
chapters . push ( {
id : index ++ ,
title : path . basename ( track . metadata . filename , path . extname ( track . metadata . filename ) ) ,
start : currentStartTime ,
end : currentStartTime + track . duration
} )
currentStartTime += track . duration
}
this . newChapters = chapters
this . checkChapters ( )
} ,
2022-10-06 01:01:42 +02:00
shiftChapterTimes ( ) {
if ( ! this . shiftAmount || isNaN ( this . shiftAmount ) || this . newChapters . length <= 1 ) {
return
}
const amount = Number ( this . shiftAmount )
const lastChapter = this . newChapters [ this . newChapters . length - 1 ]
if ( lastChapter . start + amount > this . mediaDurationRounded ) {
this . $toast . error ( 'Invalid shift amount. Last chapter start time would extend beyond the duration of this audiobook.' )
return
}
if ( this . newChapters [ 0 ] . end + amount <= 0 ) {
this . $toast . error ( 'Invalid shift amount. First chapter would have zero or negative length.' )
return
}
for ( let i = 0 ; i < this . newChapters . length ; i ++ ) {
const chap = this . newChapters [ i ]
chap . end = Math . min ( chap . end + amount , this . mediaDuration )
if ( i > 0 ) {
chap . start = Math . max ( 0 , chap . start + amount )
}
}
} ,
2022-05-11 00:03:41 +02:00
editItem ( ) {
this . $store . commit ( 'showEditModal' , this . libraryItem )
} ,
addChapter ( chapter ) {
console . log ( 'Add chapter' , chapter )
const newChapter = {
id : chapter . id + 1 ,
start : chapter . start ,
end : chapter . end ,
title : ''
}
this . newChapters . splice ( chapter . id + 1 , 0 , newChapter )
this . checkChapters ( )
} ,
removeChapter ( chapter ) {
this . newChapters = this . newChapters . filter ( ( ch ) => ch . id !== chapter . id )
this . checkChapters ( )
} ,
checkChapters ( ) {
var previousStart = 0
for ( let i = 0 ; i < this . newChapters . length ; i ++ ) {
this . newChapters [ i ] . id = i
this . newChapters [ i ] . start = Number ( this . newChapters [ i ] . start )
if ( i === 0 && this . newChapters [ i ] . start !== 0 ) {
this . newChapters [ i ] . error = 'First chapter must start at 0'
} else if ( this . newChapters [ i ] . start <= previousStart && i > 0 ) {
this . newChapters [ i ] . error = 'Invalid start time must be >= previous chapter start time'
} else if ( this . newChapters [ i ] . start >= this . mediaDuration ) {
this . newChapters [ i ] . error = 'Invalid start time must be < duration'
} else {
this . newChapters [ i ] . error = null
}
previousStart = this . newChapters [ i ] . start
}
} ,
playChapter ( chapter ) {
console . log ( 'Play Chapter' , chapter . id )
if ( this . selectedChapterId === chapter . id ) {
console . log ( 'Chapter already playing' , this . isLoadingChapter , this . isPlayingChapter )
if ( this . isLoadingChapter ) return
if ( this . isPlayingChapter ) {
this . destroyAudioEl ( )
return
}
}
if ( this . selectedChapterId ) {
this . destroyAudioEl ( )
}
const audioTrack = this . tracks . find ( ( at ) => {
return chapter . start >= at . startOffset && chapter . start < at . startOffset + at . duration
} )
console . log ( 'audio track' , audioTrack )
this . selectedChapter = chapter
this . isLoadingChapter = true
const trackOffset = chapter . start - audioTrack . startOffset
this . playTrackAtTime ( audioTrack , trackOffset )
} ,
playTrackAtTime ( audioTrack , trackOffset ) {
this . currentTrackIndex = audioTrack . index
const audioEl = this . audioEl || document . createElement ( 'audio' )
var src = audioTrack . contentUrl + ` ?token= ${ this . userToken } `
if ( this . $isDev ) {
2022-10-01 23:07:30 +02:00
src = ` http://localhost:3333 ${ this . $config . routerBasePath } ${ src } `
2022-05-11 00:03:41 +02:00
}
console . log ( 'src' , src )
audioEl . src = src
audioEl . id = 'chapter-audio'
document . body . appendChild ( audioEl )
audioEl . addEventListener ( 'loadeddata' , ( ) => {
console . log ( 'Audio loaded data' , audioEl . duration )
audioEl . currentTime = trackOffset
audioEl . play ( )
console . log ( 'Playing audio at current time' , trackOffset )
} )
audioEl . addEventListener ( 'play' , ( ) => {
console . log ( 'Audio playing' )
this . isLoadingChapter = false
this . isPlayingChapter = true
} )
audioEl . addEventListener ( 'ended' , ( ) => {
console . log ( 'Audio ended' )
const nextTrack = this . tracks . find ( ( t ) => t . index === this . currentTrackIndex + 1 )
if ( nextTrack ) {
console . log ( 'Playing next track' , nextTrack . index )
this . currentTrackIndex = nextTrack . index
this . playTrackAtTime ( nextTrack , 0 )
} else {
console . log ( 'No next track' )
this . destroyAudioEl ( )
}
} )
this . audioEl = audioEl
} ,
destroyAudioEl ( ) {
if ( ! this . audioEl ) return
this . audioEl . remove ( )
this . audioEl = null
this . selectedChapter = null
this . isPlayingChapter = false
this . isLoadingChapter = false
} ,
saveChapters ( ) {
this . checkChapters ( )
for ( let i = 0 ; i < this . newChapters . length ; i ++ ) {
if ( this . newChapters [ i ] . error ) {
this . $toast . error ( 'Chapters have errors' )
return
}
if ( ! this . newChapters [ i ] . title ) {
this . $toast . error ( 'Chapters must have titles' )
return
}
const nextChapter = this . newChapters [ i + 1 ]
if ( nextChapter ) {
this . newChapters [ i ] . end = nextChapter . start
} else {
this . newChapters [ i ] . end = this . mediaDuration
}
}
this . saving = true
const payload = {
chapters : this . newChapters
}
this . $axios
. $post ( ` /api/items/ ${ this . libraryItem . id } /chapters ` , payload )
. then ( ( data ) => {
this . saving = false
if ( data . updated ) {
this . $toast . success ( 'Chapters updated' )
2022-07-26 01:57:00 +02:00
if ( this . previousRoute ) {
this . $router . push ( this . previousRoute )
} else {
this . $router . push ( ` /item/ ${ this . libraryItem . id } ` )
}
2022-05-11 00:03:41 +02:00
} else {
2022-11-09 00:10:08 +01:00
this . $toast . info ( this . $strings . MessageNoUpdatesWereNecessary )
2022-05-11 00:03:41 +02:00
}
} )
. catch ( ( error ) => {
this . saving = false
console . error ( 'Failed to update chapters' , error )
this . $toast . error ( 'Failed to update chapters' )
} )
} ,
2022-09-30 01:06:13 +02:00
applyChapterNamesOnly ( ) {
this . newChapters . forEach ( ( chapter , index ) => {
if ( this . chapterData . chapters [ index ] ) {
chapter . title = this . chapterData . chapters [ index ] . title
}
} )
this . showFindChaptersModal = false
this . chapterData = null
} ,
2022-05-11 00:03:41 +02:00
applyChapterData ( ) {
var index = 0
this . newChapters = this . chapterData . chapters
. filter ( ( chap ) => chap . startOffsetSec < this . mediaDuration )
. map ( ( chap ) => {
var chapEnd = Math . min ( this . mediaDuration , ( chap . startOffsetMs + chap . lengthMs ) / 1000 )
return {
id : index ++ ,
start : chap . startOffsetMs / 1000 ,
end : chapEnd ,
title : chap . title
}
} )
this . showFindChaptersModal = false
this . chapterData = null
} ,
findChapters ( ) {
if ( ! this . asinInput ) {
this . $toast . error ( 'Must input an ASIN' )
return
}
2022-10-15 22:31:07 +02:00
// Update local storage region
if ( this . regionInput !== localStorage . getItem ( 'audibleRegion' ) ) {
localStorage . setItem ( 'audibleRegion' , this . regionInput )
}
2022-05-11 00:03:41 +02:00
this . findingChapters = true
this . chapterData = null
this . $axios
2022-10-15 22:31:07 +02:00
. $get ( ` /api/search/chapters?asin= ${ this . asinInput } ®ion= ${ this . regionInput } ` )
2022-05-11 00:03:41 +02:00
. then ( ( data ) => {
this . findingChapters = false
if ( data . error ) {
this . $toast . error ( data . error )
this . showFindChaptersModal = false
} else {
console . log ( 'Chapter data' , data )
this . chapterData = data
}
} )
. catch ( ( error ) => {
this . findingChapters = false
console . error ( 'Failed to get chapter data' , error )
this . $toast . error ( 'Failed to find chapters' )
this . showFindChaptersModal = false
} )
}
} ,
mounted ( ) {
2022-10-15 22:31:07 +02:00
this . regionInput = localStorage . getItem ( 'audibleRegion' ) || 'US'
2022-05-11 00:03:41 +02:00
this . asinInput = this . mediaMetadata . asin || null
this . newChapters = this . chapters . map ( ( c ) => ( { ... c } ) )
if ( ! this . newChapters . length ) {
this . newChapters = [
{
id : 0 ,
start : 0 ,
end : this . mediaDuration ,
title : ''
}
]
}
2022-08-28 22:11:14 +02:00
} ,
beforeDestroy ( ) {
this . destroyAudioEl ( )
2022-05-11 00:03:41 +02:00
}
}
< / script >