2021-08-18 00:01:11 +02:00
< template >
< div class = "text-white max-h-screen h-screen overflow-hidden bg-bg" >
< app -appbar / >
2021-09-23 03:40:35 +02:00
2021-08-18 00:01:11 +02:00
< Nuxt / >
2021-09-23 03:40:35 +02:00
2021-08-18 00:01:11 +02:00
< app -stream -container ref = "streamContainer" / >
2021-10-23 03:08:02 +02:00
2021-08-18 00:01:11 +02:00
< modals -edit -modal / >
2021-10-18 01:05:43 +02:00
< readers -reader / >
2021-08-18 00:01:11 +02:00
< / div >
< / template >
< script >
2021-10-05 05:11:42 +02:00
import CloseButton from '@/components/widgets/CloseButton'
2021-08-18 00:01:11 +02:00
export default {
2021-08-24 02:37:40 +02:00
middleware : 'authenticated' ,
2021-08-18 00:01:11 +02:00
data ( ) {
return {
socket : null
}
} ,
watch : {
$route ( newVal ) {
if ( this . $store . state . showEditModal ) {
this . $store . commit ( 'setShowEditModal' , false )
}
2021-08-27 01:32:05 +02:00
if ( this . $store . state . selectedAudiobooks ) {
this . $store . commit ( 'setSelectedAudiobooks' , [ ] )
}
2021-09-26 22:34:08 +02:00
if ( this . $store . state . audiobooks . keywordFilter ) {
this . $store . commit ( 'audiobooks/setKeywordFilter' , '' )
}
2021-08-18 00:01:11 +02:00
}
} ,
computed : {
user ( ) {
2021-08-24 01:31:04 +02:00
return this . $store . state . user . user
2021-08-18 00:01:11 +02:00
}
} ,
methods : {
connect ( ) {
console . log ( '[SOCKET] Connected' )
2021-08-24 01:31:04 +02:00
var token = this . $store . getters [ 'user/getToken' ]
2021-08-18 00:01:11 +02:00
this . socket . emit ( 'auth' , token )
} ,
connectError ( ) { } ,
disconnect ( ) {
console . log ( '[SOCKET] Disconnected' )
} ,
reconnect ( ) { } ,
reconnectError ( ) { } ,
reconnectFailed ( ) { } ,
init ( payload ) {
console . log ( 'Init Payload' , payload )
if ( payload . stream ) {
if ( this . $refs . streamContainer ) {
this . $store . commit ( 'setStream' , payload . stream )
this . $refs . streamContainer . streamOpen ( payload . stream )
}
}
if ( payload . user ) {
2021-08-24 01:31:04 +02:00
this . $store . commit ( 'user/setUser' , payload . user )
this . $store . commit ( 'user/setSettings' , payload . user . settings )
2021-08-18 00:01:11 +02:00
}
2021-09-05 02:58:39 +02:00
if ( payload . serverSettings ) {
this . $store . commit ( 'setServerSettings' , payload . serverSettings )
}
2021-10-06 04:10:49 +02:00
if ( payload . librariesScanning ) {
payload . librariesScanning . forEach ( ( libraryScan ) => {
this . scanStart ( libraryScan )
} )
}
2021-10-09 00:30:20 +02:00
if ( payload . backups && payload . backups . length ) {
this . $store . commit ( 'setBackups' , payload . backups )
}
2021-10-23 03:08:02 +02:00
if ( payload . usersOnline ) {
this . $store . commit ( 'users/resetUsers' )
payload . usersOnline . forEach ( ( user ) => {
this . $store . commit ( 'users/updateUser' , user )
} )
}
2021-08-18 00:01:11 +02:00
} ,
streamOpen ( stream ) {
if ( this . $refs . streamContainer ) this . $refs . streamContainer . streamOpen ( stream )
} ,
streamClosed ( streamId ) {
if ( this . $refs . streamContainer ) this . $refs . streamContainer . streamClosed ( streamId )
} ,
streamProgress ( data ) {
if ( this . $refs . streamContainer ) this . $refs . streamContainer . streamProgress ( data )
} ,
streamReady ( ) {
if ( this . $refs . streamContainer ) this . $refs . streamContainer . streamReady ( )
} ,
streamReset ( payload ) {
if ( this . $refs . streamContainer ) this . $refs . streamContainer . streamReset ( payload )
} ,
audiobookAdded ( audiobook ) {
this . $store . commit ( 'audiobooks/addUpdate' , audiobook )
} ,
audiobookUpdated ( audiobook ) {
this . $store . commit ( 'audiobooks/addUpdate' , audiobook )
} ,
audiobookRemoved ( audiobook ) {
if ( this . $route . name . startsWith ( 'audiobook' ) ) {
if ( this . $route . params . id === audiobook . id ) {
2021-10-05 05:11:42 +02:00
this . $router . replace ( ` /library/ ${ this . $store . state . libraries . currentLibraryId } ` )
2021-08-18 00:01:11 +02:00
}
}
this . $store . commit ( 'audiobooks/remove' , audiobook )
} ,
2021-10-05 05:11:42 +02:00
libraryAdded ( library ) {
this . $store . commit ( 'libraries/addUpdate' , library )
} ,
libraryUpdated ( library ) {
this . $store . commit ( 'libraries/addUpdate' , library )
} ,
libraryRemoved ( library ) {
this . $store . commit ( 'libraries/remove' , library )
} ,
scanComplete ( data ) {
var message = ` Scan " ${ data . name } " complete! `
if ( data . results ) {
var scanResultMsgs = [ ]
var results = data . results
if ( results . added ) scanResultMsgs . push ( ` ${ results . added } added ` )
if ( results . updated ) scanResultMsgs . push ( ` ${ results . updated } updated ` )
if ( results . removed ) scanResultMsgs . push ( ` ${ results . removed } removed ` )
if ( results . missing ) scanResultMsgs . push ( ` ${ results . missing } missing ` )
if ( ! scanResultMsgs . length ) message += '\nEverything was up to date'
else message += '\n' + scanResultMsgs . join ( '\n' )
2021-08-25 03:24:40 +02:00
} else {
2021-10-05 05:11:42 +02:00
message = ` Scan " ${ data . name } " was canceled `
2021-08-25 03:24:40 +02:00
}
2021-10-05 05:11:42 +02:00
var existingScan = this . $store . getters [ 'scanners/getLibraryScan' ] ( data . id )
if ( existingScan && ! isNaN ( existingScan . toastId ) ) {
2021-10-06 04:10:49 +02:00
this . $toast . update ( existingScan . toastId , { content : message , options : { timeout : 5000 , type : 'success' , closeButton : false , position : 'bottom-center' , onClose : ( ) => null } } , true )
2021-08-25 03:24:40 +02:00
} else {
2021-10-05 05:11:42 +02:00
this . $toast . success ( message , { timeout : 5000 , position : 'bottom-center' } )
2021-08-25 03:24:40 +02:00
}
2021-10-05 05:11:42 +02:00
this . $store . commit ( 'scanners/remove' , data )
2021-08-18 00:01:11 +02:00
} ,
2021-10-05 05:11:42 +02:00
onScanToastCancel ( id ) {
this . $root . socket . emit ( 'cancel_scan' , id )
} ,
scanStart ( data ) {
data . toastId = this . $toast ( ` Scanning " ${ data . name } "... ` , { timeout : false , type : 'info' , draggable : false , closeOnClick : false , closeButton : CloseButton , closeButtonClassName : 'cancel-scan-btn' , showCloseButtonOnHover : false , position : 'bottom-center' , onClose : ( ) => this . onScanToastCancel ( data . id ) } )
this . $store . commit ( 'scanners/addUpdate' , data )
} ,
scanProgress ( data ) {
var existingScan = this . $store . getters [ 'scanners/getLibraryScan' ] ( data . id )
if ( existingScan && ! isNaN ( existingScan . toastId ) ) {
data . toastId = existingScan . toastId
this . $toast . update ( existingScan . toastId , { content : ` Scanning " ${ existingScan . name } "... ${ data . progress . progress || 0 } % ` , options : { timeout : false } } , true )
2021-10-06 04:10:49 +02:00
} else {
data . toastId = this . $toast ( ` Scanning " ${ data . name } "... ` , { timeout : false , type : 'info' , draggable : false , closeOnClick : false , closeButton : CloseButton , closeButtonClassName : 'cancel-scan-btn' , showCloseButtonOnHover : false , position : 'bottom-center' , onClose : ( ) => this . onScanToastCancel ( data . id ) } )
2021-08-25 03:24:40 +02:00
}
2021-10-05 05:11:42 +02:00
this . $store . commit ( 'scanners/addUpdate' , data )
2021-08-18 00:01:11 +02:00
} ,
userUpdated ( user ) {
2021-08-24 01:31:04 +02:00
if ( this . $store . state . user . user . id === user . id ) {
this . $store . commit ( 'user/setUser' , user )
this . $store . commit ( 'user/setSettings' , user . settings )
2021-08-18 00:01:11 +02:00
}
} ,
2021-10-13 03:07:42 +02:00
userOnline ( user ) {
this . $store . commit ( 'users/updateUser' , user )
} ,
userOffline ( user ) {
this . $store . commit ( 'users/removeUser' , user )
} ,
userStreamUpdate ( user ) {
this . $store . commit ( 'users/updateUser' , user )
} ,
2021-10-24 22:53:51 +02:00
currentUserAudiobookUpdate ( payload ) {
2021-10-26 04:14:54 +02:00
// console.log('Received user audiobook update', payload)
2021-10-24 22:53:51 +02:00
this . $store . commit ( 'user/updateUserAudiobook' , payload )
} ,
2021-09-15 03:45:00 +02:00
downloadToastClick ( download ) {
2021-09-18 01:40:30 +02:00
if ( ! download || ! download . audiobookId ) {
return console . error ( 'Invalid download object' , download )
}
2021-10-06 20:00:12 +02:00
2021-09-18 01:40:30 +02:00
var audiobook = this . $store . getters [ 'audiobooks/getAudiobook' ] ( download . audiobookId )
if ( ! audiobook ) {
return console . error ( 'Audiobook not found for download' , download )
}
this . $store . commit ( 'showEditModalOnTab' , { audiobook , tab : 'download' } )
2021-09-15 03:45:00 +02:00
} ,
2021-09-04 21:17:26 +02:00
downloadStarted ( download ) {
2021-09-15 03:45:00 +02:00
download . status = this . $constants . DownloadStatus . PENDING
2021-09-18 01:40:30 +02:00
download . toastId = this . $toast ( ` Preparing download " ${ download . filename } " ` , { timeout : false , draggable : false , closeOnClick : false , onClick : ( ) => this . downloadToastClick ( download ) } )
2021-09-04 21:17:26 +02:00
this . $store . commit ( 'downloads/addUpdateDownload' , download )
} ,
downloadReady ( download ) {
2021-09-15 03:45:00 +02:00
download . status = this . $constants . DownloadStatus . READY
var existingDownload = this . $store . getters [ 'downloads/getDownload' ] ( download . id )
2021-09-04 21:17:26 +02:00
2021-09-15 03:45:00 +02:00
if ( existingDownload && existingDownload . toastId !== undefined ) {
download . toastId = existingDownload . toastId
2021-09-18 01:40:30 +02:00
this . $toast . update ( existingDownload . toastId , { content : ` Download " ${ download . filename } " is ready! ` , options : { timeout : 5000 , type : 'success' , onClick : ( ) => this . downloadToastClick ( download ) } } , true )
2021-09-15 03:45:00 +02:00
} else {
this . $toast . success ( ` Download " ${ download . filename } " is ready! ` )
}
2021-09-04 21:17:26 +02:00
this . $store . commit ( 'downloads/addUpdateDownload' , download )
} ,
downloadFailed ( download ) {
2021-09-15 03:45:00 +02:00
download . status = this . $constants . DownloadStatus . FAILED
var existingDownload = this . $store . getters [ 'downloads/getDownload' ] ( download . id )
var failedMsg = download . isTimedOut ? 'timed out' : 'failed'
2021-09-04 21:17:26 +02:00
2021-09-15 03:45:00 +02:00
if ( existingDownload && existingDownload . toastId !== undefined ) {
download . toastId = existingDownload . toastId
2021-09-18 01:40:30 +02:00
this . $toast . update ( existingDownload . toastId , { content : ` Download " ${ download . filename } " ${ failedMsg } ` , options : { timeout : 5000 , type : 'error' , onClick : ( ) => this . downloadToastClick ( download ) } } , true )
2021-09-15 03:45:00 +02:00
} else {
console . warn ( 'Download failed no existing download' , existingDownload )
this . $toast . error ( ` Download " ${ download . filename } " ${ failedMsg } ` )
}
2021-09-04 21:17:26 +02:00
this . $store . commit ( 'downloads/addUpdateDownload' , download )
} ,
downloadKilled ( download ) {
2021-09-15 03:45:00 +02:00
var existingDownload = this . $store . getters [ 'downloads/getDownload' ] ( download . id )
if ( existingDownload && existingDownload . toastId !== undefined ) {
download . toastId = existingDownload . toastId
2021-09-18 01:40:30 +02:00
this . $toast . update ( existingDownload . toastId , { content : ` Download " ${ download . filename } " was terminated ` , options : { timeout : 5000 , type : 'error' , onClick : ( ) => this . downloadToastClick ( download ) } } , true )
2021-09-15 03:45:00 +02:00
} else {
console . warn ( 'Download killed no existing download found' , existingDownload )
this . $toast . error ( ` Download " ${ download . filename } " was terminated ` )
}
2021-09-04 21:17:26 +02:00
this . $store . commit ( 'downloads/removeDownload' , download )
} ,
downloadExpired ( download ) {
2021-09-15 03:45:00 +02:00
download . status = this . $constants . DownloadStatus . EXPIRED
2021-09-04 21:17:26 +02:00
this . $store . commit ( 'downloads/addUpdateDownload' , download )
} ,
2021-10-27 03:09:04 +02:00
showErrorToast ( message ) {
this . $toast . error ( message )
} ,
showSuccessToast ( message ) {
this . $toast . success ( message )
} ,
2021-10-09 00:30:20 +02:00
backupApplied ( ) {
// Force refresh
location . reload ( )
} ,
2021-08-18 00:01:11 +02:00
initializeSocket ( ) {
this . socket = this . $nuxtSocket ( {
name : process . env . NODE _ENV === 'development' ? 'dev' : 'prod' ,
persist : 'main' ,
teardown : true ,
transports : [ 'websocket' ] ,
upgrade : false
} )
this . $root . socket = this . socket
// Connection Listeners
this . socket . on ( 'connect' , this . connect )
this . socket . on ( 'connect_error' , this . connectError )
this . socket . on ( 'disconnect' , this . disconnect )
this . socket . on ( 'reconnecting' , this . reconnecting )
this . socket . on ( 'reconnect' , this . reconnect )
this . socket . on ( 'reconnect_error' , this . reconnectError )
this . socket . on ( 'reconnect_failed' , this . reconnectFailed )
this . socket . on ( 'init' , this . init )
// Stream Listeners
this . socket . on ( 'stream_open' , this . streamOpen )
this . socket . on ( 'stream_closed' , this . streamClosed )
this . socket . on ( 'stream_progress' , this . streamProgress )
this . socket . on ( 'stream_ready' , this . streamReady )
this . socket . on ( 'stream_reset' , this . streamReset )
// Audiobook Listeners
this . socket . on ( 'audiobook_updated' , this . audiobookUpdated )
this . socket . on ( 'audiobook_added' , this . audiobookAdded )
this . socket . on ( 'audiobook_removed' , this . audiobookRemoved )
2021-10-05 05:11:42 +02:00
// Library Listeners
this . socket . on ( 'library_updated' , this . libraryUpdated )
this . socket . on ( 'library_added' , this . libraryAdded )
this . socket . on ( 'library_removed' , this . libraryRemoved )
2021-08-18 00:01:11 +02:00
// User Listeners
this . socket . on ( 'user_updated' , this . userUpdated )
2021-10-13 03:07:42 +02:00
this . socket . on ( 'user_online' , this . userOnline )
this . socket . on ( 'user_offline' , this . userOffline )
this . socket . on ( 'user_stream_update' , this . userStreamUpdate )
2021-10-24 22:53:51 +02:00
this . socket . on ( 'current_user_audiobook_update' , this . currentUserAudiobookUpdate )
2021-08-18 00:01:11 +02:00
// Scan Listeners
this . socket . on ( 'scan_start' , this . scanStart )
this . socket . on ( 'scan_complete' , this . scanComplete )
this . socket . on ( 'scan_progress' , this . scanProgress )
2021-09-04 21:17:26 +02:00
// Download Listeners
this . socket . on ( 'download_started' , this . downloadStarted )
this . socket . on ( 'download_ready' , this . downloadReady )
this . socket . on ( 'download_failed' , this . downloadFailed )
this . socket . on ( 'download_killed' , this . downloadKilled )
this . socket . on ( 'download_expired' , this . downloadExpired )
2021-10-01 01:52:32 +02:00
2021-10-27 03:09:04 +02:00
// Toast Listeners
this . socket . on ( 'show_error_toast' , this . showErrorToast )
this . socket . on ( 'show_success_toast' , this . showSuccessToast )
2021-10-09 00:30:20 +02:00
this . socket . on ( 'backup_applied' , this . backupApplied )
2021-09-16 00:59:38 +02:00
} ,
showUpdateToast ( versionData ) {
var ignoreVersion = localStorage . getItem ( 'ignoreVersion' )
var latestVersion = versionData . latestVersion
if ( ! ignoreVersion || ignoreVersion !== latestVersion ) {
this . $toast . info ( ` Update is available! \ nCheck release notes for v ${ versionData . latestVersion } ` , {
position : 'top-center' ,
toastClassName : 'cursor-pointer' ,
bodyClassName : 'custom-class-1' ,
timeout : 20000 ,
closeOnClick : false ,
draggable : false ,
hideProgressBar : false ,
onClick : ( ) => {
window . open ( versionData . githubTagUrl , '_blank' )
} ,
onClose : ( ) => {
localStorage . setItem ( 'ignoreVersion' , versionData . latestVersion )
}
} )
} else {
console . warn ( ` Update is available but user chose to dismiss it! v ${ versionData . latestVersion } ` )
}
2021-10-23 03:08:02 +02:00
} ,
checkActiveElementIsInput ( ) {
var activeElement = document . activeElement
var inputs = [ 'input' , 'select' , 'button' , 'textarea' ]
return activeElement && inputs . indexOf ( activeElement . tagName . toLowerCase ( ) ) !== - 1
} ,
2021-10-24 21:02:49 +02:00
getHotkeyName ( e ) {
2021-10-23 23:49:34 +02:00
var keyCode = e . keyCode || e . which
if ( ! this . $keynames [ keyCode ] ) {
// Unused hotkey
2021-10-24 21:02:49 +02:00
return null
2021-10-23 03:08:02 +02:00
}
2021-10-23 23:49:34 +02:00
var keyName = this . $keynames [ keyCode ]
var name = keyName
if ( e . shiftKey ) name = 'Shift-' + keyName
if ( process . env . NODE _ENV !== 'production' ) {
console . log ( 'Hotkey command' , name )
}
2021-10-24 21:02:49 +02:00
return name
} ,
keyDown ( e ) {
var name = this . getHotkeyName ( e )
if ( ! name ) return
2021-10-23 23:49:34 +02:00
// Input is focused then ignore key press
2021-10-23 03:08:02 +02:00
if ( this . checkActiveElementIsInput ( ) ) {
return
}
2021-10-23 23:49:34 +02:00
// Modal is open
2021-10-24 21:02:49 +02:00
if ( this . $store . state . openModal && Object . values ( this . $hotkeys . Modal ) . includes ( name ) ) {
2021-10-23 23:49:34 +02:00
this . $eventBus . $emit ( 'modal-hotkey' , name )
2021-10-24 21:02:49 +02:00
e . preventDefault ( )
2021-10-23 23:49:34 +02:00
return
}
// EReader is open
2021-10-24 21:02:49 +02:00
if ( this . $store . state . showEReader && Object . values ( this . $hotkeys . EReader ) . includes ( name ) ) {
2021-10-23 23:49:34 +02:00
this . $eventBus . $emit ( 'reader-hotkey' , name )
2021-10-24 21:02:49 +02:00
e . preventDefault ( )
2021-10-23 23:49:34 +02:00
return
}
// Batch selecting
2021-10-24 21:02:49 +02:00
if ( this . $store . getters [ 'getNumAudiobooksSelected' ] && name === 'Escape' ) {
2021-10-23 23:49:34 +02:00
// ESCAPE key cancels batch selection
2021-10-24 21:02:49 +02:00
this . $store . commit ( 'setSelectedAudiobooks' , [ ] )
e . preventDefault ( )
2021-10-23 03:08:02 +02:00
return
}
// Playing audiobook
2021-10-24 21:02:49 +02:00
if ( this . $store . state . streamAudiobook && Object . values ( this . $hotkeys . AudioPlayer ) . includes ( name ) ) {
2021-10-23 23:49:34 +02:00
this . $eventBus . $emit ( 'player-hotkey' , name )
2021-10-24 21:02:49 +02:00
e . preventDefault ( )
2021-10-23 03:08:02 +02:00
}
2021-08-18 00:01:11 +02:00
}
} ,
mounted ( ) {
2021-10-24 21:02:49 +02:00
window . addEventListener ( 'keydown' , this . keyDown )
2021-10-23 03:08:02 +02:00
2021-08-18 00:01:11 +02:00
this . initializeSocket ( )
2021-10-05 05:11:42 +02:00
this . $store . dispatch ( 'libraries/load' )
2021-10-07 04:08:52 +02:00
// If experimental features set in local storage
var experimentalFeaturesSaved = localStorage . getItem ( 'experimental' )
if ( experimentalFeaturesSaved === '1' ) {
this . $store . commit ( 'setExperimentalFeatures' , true )
}
2021-09-16 00:59:38 +02:00
this . $store
. dispatch ( 'checkForUpdate' )
. then ( ( res ) => {
if ( res && res . hasUpdate ) this . showUpdateToast ( res )
} )
. catch ( ( err ) => console . error ( err ) )
2021-08-27 14:01:47 +02:00
if ( this . $route . query . error ) {
this . $toast . error ( this . $route . query . error )
this . $router . replace ( this . $route . path )
}
2021-10-23 03:08:02 +02:00
} ,
beforeDestroy ( ) {
2021-10-24 21:02:49 +02:00
window . removeEventListener ( 'keydown' , this . keyDown )
2021-08-18 00:01:11 +02:00
}
}
2021-09-16 00:59:38 +02:00
< / script >
< style >
. Vue - Toastification _ _toast - body . custom - class - 1 {
font - size : 14 px ;
}
< / style >