2021-09-01 20:07:11 -05:00
< template >
2023-12-10 17:53:27 -06:00
< div class = "w-full layout-wrapper bg-bg" >
2021-09-01 20:07:11 -05:00
< app-appbar / >
2023-06-19 12:37:44 -05:00
< div id = "content" class = "overflow-hidden relative" : class = "isPlayerOpen ? 'playerOpen' : ''" >
2023-12-04 17:53:36 -06:00
< Nuxt :key = "currentLang" / >
2021-09-01 20:07:11 -05:00
< / div >
2021-11-01 21:06:51 -05:00
< app-audio-player-container ref = "streamContainer" / >
2021-10-06 07:24:15 -05:00
< modals-libraries-modal / >
2022-12-03 17:05:43 -06:00
< modals-playlists-add-create-modal / >
2023-06-04 14:59:55 -05:00
< modals-select-local-folder-modal / >
2023-06-24 14:45:25 -05:00
< modals-rssfeeds-rss-feed-modal / >
2023-12-04 17:53:36 -06:00
< app-side-drawer :key = "currentLang" / >
2021-10-17 20:20:00 -05:00
< readers-reader / >
2021-09-01 20:07:11 -05:00
< / div >
< / template >
< script >
2023-09-15 17:35:44 -05:00
import { CapacitorHttp } from '@capacitor/core'
2025-04-19 17:26:32 -05:00
import { AbsLogger } from '@/plugins/capacitor'
2023-09-15 17:35:44 -05:00
2021-09-01 20:07:11 -05:00
export default {
data ( ) {
2022-04-07 18:46:58 -05:00
return {
2022-04-09 18:36:32 -05:00
inittingLibraries : false ,
hasMounted : false ,
2023-09-10 17:51:53 -05:00
disconnectTime : 0 ,
2023-12-04 17:53:36 -06:00
timeLostFocus : 0 ,
currentLang : null
2022-04-07 18:46:58 -05:00
}
2021-09-01 20:07:11 -05:00
} ,
2021-11-14 19:59:34 -06:00
watch : {
networkConnected : {
2022-04-07 18:46:58 -05:00
handler ( newVal , oldVal ) {
2022-04-09 18:36:32 -05:00
if ( ! this . hasMounted ) {
// watcher runs before mount, handling libraries/connection should be handled in mount
return
}
2021-11-14 19:59:34 -06:00
if ( newVal ) {
2022-04-07 18:46:58 -05:00
console . log ( ` [default] network connected changed ${ oldVal } -> ${ newVal } ` )
if ( ! this . user ) {
this . attemptConnection ( )
} else if ( ! this . currentLibraryId ) {
this . initLibraries ( )
2022-04-09 18:36:32 -05:00
} else {
var timeSinceDisconnect = Date . now ( ) - this . disconnectTime
if ( timeSinceDisconnect > 5000 ) {
console . log ( 'Time since disconnect was' , timeSinceDisconnect , 'sync with server' )
setTimeout ( ( ) => {
2024-02-05 19:04:11 -06:00
this . syncLocalSessions ( false )
2022-04-09 18:36:32 -05:00
} , 4000 )
}
2022-04-07 18:46:58 -05:00
}
2022-04-09 18:36:32 -05:00
} else {
console . log ( ` [default] lost network connection ` )
this . disconnectTime = Date . now ( )
2021-11-14 19:59:34 -06:00
}
}
}
} ,
2021-09-01 20:07:11 -05:00
computed : {
2023-06-19 12:37:44 -05:00
isPlayerOpen ( ) {
return this . $store . getters [ 'getIsPlayerOpen' ]
2023-06-17 17:34:08 -05:00
} ,
2021-09-01 20:07:11 -05:00
routeName ( ) {
return this . $route . name
2021-11-14 19:59:34 -06:00
} ,
networkConnected ( ) {
return this . $store . state . networkConnected
2021-12-04 19:56:29 -06:00
} ,
2022-04-03 14:24:17 -05:00
user ( ) {
return this . $store . state . user . user
} ,
2021-12-04 19:56:29 -06:00
currentLibraryId ( ) {
return this . $store . state . libraries . currentLibraryId
2023-06-04 17:14:26 -05:00
} ,
2025-04-19 17:26:32 -05:00
currentLibraryName ( ) {
return this . $store . getters [ 'libraries/getCurrentLibraryName' ]
} ,
2023-06-04 17:14:26 -05:00
attemptingConnection : {
get ( ) {
return this . $store . state . attemptingConnection
} ,
set ( val ) {
this . $store . commit ( 'setAttemptingConnection' , val )
}
2021-09-01 20:07:11 -05:00
}
} ,
methods : {
initialStream ( stream ) {
2023-06-19 12:37:44 -05:00
if ( this . $refs . streamContainer ? . audioPlayerReady ) {
2021-09-01 20:07:11 -05:00
this . $refs . streamContainer . streamOpen ( stream )
}
2021-09-02 12:19:26 -05:00
} ,
2021-12-05 18:31:47 -06:00
async loadSavedSettings ( ) {
2022-12-17 14:48:56 -06:00
const userSavedServerSettings = await this . $localStore . getServerSettings ( )
2021-12-05 18:31:47 -06:00
if ( userSavedServerSettings ) {
this . $store . commit ( 'setServerSettings' , userSavedServerSettings )
}
2022-12-17 14:48:56 -06:00
await this . $store . dispatch ( 'user/loadUserSettings' )
2021-12-05 18:31:47 -06:00
} ,
2023-09-15 17:35:44 -05:00
async postRequest ( url , data , headers , connectTimeout = 30000 ) {
const options = {
url ,
headers ,
data ,
connectTimeout
}
const response = await CapacitorHttp . post ( options )
console . log ( '[default] POST request response' , response )
if ( response . status >= 400 ) {
throw new Error ( response . data )
} else {
return response . data
}
} ,
2021-11-14 19:59:34 -06:00
async attemptConnection ( ) {
2022-04-09 18:36:32 -05:00
console . warn ( '[default] attemptConnection' )
2021-11-14 19:59:34 -06:00
if ( ! this . networkConnected ) {
2022-04-09 18:36:32 -05:00
console . warn ( '[default] No network connection' )
2025-04-20 12:36:27 -05:00
AbsLogger . info ( { tag : 'default' , message : 'attemptConnection: No network connection' } )
2021-11-14 19:59:34 -06:00
return
}
2022-04-07 18:46:58 -05:00
if ( this . attemptingConnection ) {
return
}
this . attemptingConnection = true
2021-11-14 19:59:34 -06:00
2023-01-08 15:32:15 -06:00
const deviceData = await this . $db . getDeviceData ( )
let serverConfig = null
if ( deviceData ) {
2023-02-26 12:54:56 -06:00
this . $store . commit ( 'globals/setHapticFeedback' , deviceData . deviceSettings ? . hapticFeedback )
2023-01-08 15:32:15 -06:00
if ( deviceData . lastServerConnectionConfigId && deviceData . serverConnectionConfigs . length ) {
serverConfig = deviceData . serverConnectionConfigs . find ( ( scc ) => scc . id == deviceData . lastServerConnectionConfigId )
}
2021-11-14 19:59:34 -06:00
}
2023-01-08 15:32:15 -06:00
2022-04-03 14:24:17 -05:00
if ( ! serverConfig ) {
// No last server config set
2022-04-07 18:46:58 -05:00
this . attemptingConnection = false
2025-04-20 12:36:27 -05:00
AbsLogger . info ( { tag : 'default' , message : 'attemptConnection: No last server config set' } )
2022-04-03 14:24:17 -05:00
return
}
2025-04-20 12:36:27 -05:00
AbsLogger . info ( { tag : 'default' , message : ` attemptConnection: Got server config, attempt authorize ( ${ serverConfig . name } ) ` } )
2022-04-07 18:46:58 -05:00
2024-02-04 15:46:26 -06:00
const authRes = await this . postRequest ( ` ${ serverConfig . address } /api/authorize ` , null , { Authorization : ` Bearer ${ serverConfig . token } ` } , 6000 ) . catch ( ( error ) => {
2025-04-20 12:36:27 -05:00
AbsLogger . error ( { tag : 'default' , message : ` attemptConnection: Server auth failed ( ${ serverConfig . name } ) ` } )
2022-04-03 14:24:17 -05:00
return false
} )
2022-04-07 18:46:58 -05:00
if ( ! authRes ) {
this . attemptingConnection = false
return
}
2022-04-03 14:24:17 -05:00
2023-11-02 16:10:55 -05:00
const { user , userDefaultLibraryId , serverSettings , ereaderDevices } = authRes
2022-07-28 18:36:43 -05:00
this . $store . commit ( 'setServerSettings' , serverSettings )
2023-11-02 16:10:55 -05:00
this . $store . commit ( 'libraries/setEReaderDevices' , ereaderDevices )
2022-04-10 20:31:47 -05:00
// Set library - Use last library if set and available fallback to default user library
2023-01-08 15:32:15 -06:00
const lastLibraryId = await this . $localStore . getLastLibraryId ( )
2022-04-10 20:31:47 -05:00
if ( lastLibraryId && ( ! user . librariesAccessible . length || user . librariesAccessible . includes ( lastLibraryId ) ) ) {
this . $store . commit ( 'libraries/setCurrentLibrary' , lastLibraryId )
} else if ( userDefaultLibraryId ) {
2022-04-03 14:24:17 -05:00
this . $store . commit ( 'libraries/setCurrentLibrary' , userDefaultLibraryId )
}
2023-01-08 15:32:15 -06:00
const serverConnectionConfig = await this . $db . setServerConnectionConfig ( serverConfig )
2022-04-03 14:24:17 -05:00
this . $store . commit ( 'user/setUser' , user )
this . $store . commit ( 'user/setServerConnectionConfig' , serverConnectionConfig )
this . $socket . connect ( serverConnectionConfig . address , serverConnectionConfig . token )
2025-04-20 12:36:27 -05:00
AbsLogger . info ( { tag : 'default' , message : ` attemptConnection: Successful connection to last saved server config ( ${ serverConnectionConfig . name } ) ` } )
2022-04-03 14:24:17 -05:00
await this . initLibraries ( )
2022-04-07 18:46:58 -05:00
this . attemptingConnection = false
2021-12-05 18:31:47 -06:00
} ,
2022-03-23 17:59:14 -05:00
itemRemoved ( libraryItem ) {
if ( this . $route . name . startsWith ( 'item' ) ) {
if ( this . $route . params . id === libraryItem . id ) {
2021-12-05 18:31:47 -06:00
this . $router . replace ( ` /bookshelf ` )
}
}
} ,
2022-04-03 14:24:17 -05:00
socketConnectionFailed ( err ) {
this . $toast . error ( 'Socket connection error: ' + err . message )
} ,
async initLibraries ( ) {
2022-04-07 18:46:58 -05:00
if ( this . inittingLibraries ) {
return
}
this . inittingLibraries = true
2022-04-03 14:24:17 -05:00
await this . $store . dispatch ( 'libraries/load' )
2025-04-19 17:26:32 -05:00
2025-04-20 12:36:27 -05:00
AbsLogger . info ( { tag : 'default' , message : ` initLibraries loading library ${ this . currentLibraryName } ` } )
2022-06-05 16:32:28 -05:00
await this . $store . dispatch ( 'libraries/fetch' , this . currentLibraryId )
2022-04-03 14:24:17 -05:00
this . $eventBus . $emit ( 'library-changed' )
2022-04-07 18:46:58 -05:00
this . inittingLibraries = false
2022-04-09 18:36:32 -05:00
} ,
2024-02-05 19:04:11 -06:00
async syncLocalSessions ( isFirstSync ) {
2023-02-05 16:54:46 -06:00
if ( ! this . user ) {
console . log ( '[default] No need to sync local sessions - not connected to server' )
return
}
2025-04-20 12:36:27 -05:00
AbsLogger . info ( { tag : 'default' , message : 'Calling syncLocalSessions' } )
2024-02-05 19:04:11 -06:00
const response = await this . $db . syncLocalSessionsWithServer ( isFirstSync )
2023-09-10 13:37:41 -05:00
if ( response ? . error ) {
2023-02-05 16:54:46 -06:00
console . error ( '[default] Failed to sync local sessions' , response . error )
} else {
console . log ( '[default] Successfully synced local sessions' )
2023-09-10 13:37:41 -05:00
// Reload local media progresses
await this . $store . dispatch ( 'globals/loadLocalMediaProgress' )
2023-02-05 16:54:46 -06:00
}
} ,
2023-01-28 14:20:00 -06:00
userUpdated ( user ) {
2024-03-03 13:29:58 -06:00
if ( this . user ? . id == user . id ) {
2022-04-09 20:29:59 -05:00
this . $store . commit ( 'user/setUser' , user )
}
2022-06-01 19:38:26 -05:00
} ,
2023-06-19 12:37:44 -05:00
async userMediaProgressUpdated ( payload ) {
const prog = payload . data // MediaProgress
2025-04-20 12:36:27 -05:00
await AbsLogger . info ( { tag : 'default' , message : ` userMediaProgressUpdate: Received updated media progress for current user from socket event. Media item id ${ payload . id } ` } )
2023-06-19 12:37:44 -05:00
2023-12-15 16:04:58 -06:00
// Check if this media item is currently open in the player, paused, and this progress update is coming from a different session
const isMediaOpenInPlayer = this . $store . getters [ 'getIsMediaStreaming' ] ( prog . libraryItemId , prog . episodeId )
if ( isMediaOpenInPlayer && this . $store . getters [ 'getCurrentPlaybackSessionId' ] !== payload . sessionId && ! this . $store . state . playerIsPlaying ) {
2025-04-20 12:36:27 -05:00
await AbsLogger . info ( { tag : 'default' , message : ` userMediaProgressUpdate: Item is currently open in player, paused and this progress update is coming from a different session. Updating playback time to ${ payload . data . currentTime } ` } )
2023-12-15 16:04:58 -06:00
this . $eventBus . $emit ( 'playback-time-update' , payload . data . currentTime )
}
// Get local media progress if exists
2023-01-15 14:58:26 -06:00
const localProg = await this . $db . getLocalMediaProgressForServerItem ( { libraryItemId : prog . libraryItemId , episodeId : prog . episodeId } )
2023-01-28 14:20:00 -06:00
let newLocalMediaProgress = null
2023-12-15 16:04:58 -06:00
// Progress update is more recent then local progress
2022-06-01 19:38:26 -05:00
if ( localProg && localProg . lastUpdate < prog . lastUpdate ) {
2023-01-15 14:58:26 -06:00
if ( localProg . currentTime == prog . currentTime && localProg . isFinished == prog . isFinished ) {
2025-04-20 12:36:27 -05:00
await AbsLogger . info ( { tag : 'default' , message : ` userMediaProgressUpdate: server lastUpdate is more recent but progress is up-to-date (libraryItemId: ${ prog . libraryItemId } ${ prog . episodeId ? ` episodeId: ${ prog . episodeId } ` : '' } ) ` } )
2023-01-15 14:58:26 -06:00
return
2023-09-10 15:10:26 -05:00
}
2022-06-01 19:38:26 -05:00
// Server progress is more up-to-date
2025-04-20 12:36:27 -05:00
await AbsLogger . info ( { tag : 'default' , message : ` userMediaProgressUpdate: syncing progress from server with local item for " ${ prog . libraryItemId } " ${ prog . episodeId ? ` episode ${ prog . episodeId } ` : '' } | server lastUpdate= ${ prog . lastUpdate } > local lastUpdate= ${ localProg . lastUpdate } ` } )
2022-06-01 19:38:26 -05:00
const payload = {
localMediaProgressId : localProg . id ,
mediaProgress : prog
}
newLocalMediaProgress = await this . $db . syncServerMediaProgressWithLocalMediaProgress ( payload )
2022-07-13 17:10:47 -05:00
} else if ( ! localProg ) {
2022-06-01 19:38:26 -05:00
// Check if local library item exists
2022-07-13 17:10:47 -05:00
// local media progress may not exist yet if it hasn't been played
2023-01-28 14:20:00 -06:00
const localLibraryItem = await this . $db . getLocalLibraryItemByLId ( prog . libraryItemId )
2022-06-01 19:38:26 -05:00
if ( localLibraryItem ) {
if ( prog . episodeId ) {
// If episode check if local episode exists
2023-01-28 14:20:00 -06:00
const lliEpisodes = localLibraryItem . media . episodes || [ ]
const localEpisode = lliEpisodes . find ( ( ep ) => ep . serverEpisodeId === prog . episodeId )
2022-06-01 19:38:26 -05:00
if ( localEpisode ) {
// Add new local media progress
const payload = {
localLibraryItemId : localLibraryItem . id ,
localEpisodeId : localEpisode . id ,
mediaProgress : prog
}
newLocalMediaProgress = await this . $db . syncServerMediaProgressWithLocalMediaProgress ( payload )
}
} else {
// Add new local media progress
const payload = {
localLibraryItemId : localLibraryItem . id ,
mediaProgress : prog
}
newLocalMediaProgress = await this . $db . syncServerMediaProgressWithLocalMediaProgress ( payload )
}
} else {
console . log ( ` [default] userMediaProgressUpdate no local media progress or lli found for this server item ${ prog . id } ` )
}
}
2023-06-19 12:37:44 -05:00
if ( newLocalMediaProgress ? . id ) {
2025-04-20 12:36:27 -05:00
await AbsLogger . info ( { tag : 'default' , message : ` userMediaProgressUpdate: local media progress updated for ${ newLocalMediaProgress . id } ` } )
2022-06-01 19:38:26 -05:00
this . $store . commit ( 'globals/updateLocalMediaProgress' , newLocalMediaProgress )
}
2023-09-10 17:51:53 -05:00
} ,
async visibilityChanged ( ) {
if ( document . visibilityState === 'visible' ) {
const elapsedTimeOutOfFocus = Date . now ( ) - this . timeLostFocus
console . log ( ` ✅ [default] device visibility: has focus ( ${ elapsedTimeOutOfFocus } ms out of focus) ` )
// If device out of focus for more than 30s then reload local media progress
if ( elapsedTimeOutOfFocus > 30000 ) {
console . log ( ` ✅ [default] device visibility: reloading local media progress ` )
// Reload local media progresses
await this . $store . dispatch ( 'globals/loadLocalMediaProgress' )
}
if ( document . visibilityState === 'visible' ) {
this . $eventBus . $emit ( 'device-focus-update' , true )
}
} else {
console . log ( '⛔️ [default] device visibility: does NOT have focus' )
this . timeLostFocus = Date . now ( )
this . $eventBus . $emit ( 'device-focus-update' , false )
}
2023-12-04 17:53:36 -06:00
} ,
changeLanguage ( code ) {
console . log ( 'Changed lang' , code )
this . currentLang = code
document . documentElement . lang = code
2021-09-12 18:37:08 -05:00
}
2021-09-01 20:07:11 -05:00
} ,
2021-11-14 19:59:34 -06:00
async mounted ( ) {
2023-12-04 17:53:36 -06:00
this . $eventBus . $on ( 'change-lang' , this . changeLanguage )
2023-09-10 17:51:53 -05:00
document . addEventListener ( 'visibilitychange' , this . visibilityChanged )
2022-04-09 20:29:59 -05:00
this . $socket . on ( 'user_updated' , this . userUpdated )
2022-06-01 19:38:26 -05:00
this . $socket . on ( 'user_media_progress_updated' , this . userMediaProgressUpdated )
2021-09-01 20:07:11 -05:00
2021-09-19 18:44:10 -05:00
if ( this . $store . state . isFirstLoad ) {
2025-04-20 14:33:48 -05:00
AbsLogger . info ( { tag : 'default' , message : ` mounted: initializing first load ( ${ this . $platform } v ${ this . $config . version } ) ` } )
2021-09-19 18:44:10 -05:00
this . $store . commit ( 'setIsFirstLoad' , false )
2022-07-01 20:05:11 -05:00
2023-12-08 16:10:57 -06:00
this . loadSavedSettings ( )
2022-07-01 20:05:11 -05:00
const deviceData = await this . $db . getDeviceData ( )
this . $store . commit ( 'setDeviceData' , deviceData )
2023-06-20 16:29:56 -05:00
2022-12-04 10:41:09 -06:00
this . $setOrientationLock ( this . $store . getters [ 'getOrientationLockSetting' ] )
2022-07-01 20:05:11 -05:00
2021-11-21 06:54:10 -06:00
await this . $store . dispatch ( 'setupNetworkListener' )
2022-04-03 14:24:17 -05:00
if ( this . $store . state . user . serverConnectionConfig ) {
2025-04-20 14:33:48 -05:00
AbsLogger . info ( { tag : 'default' , message : ` mounted: Server connected, init libraries ( ${ this . $store . getters [ 'user/getServerConfigName' ] } ) ` } )
2022-04-03 14:24:17 -05:00
await this . initLibraries ( )
} else {
2025-04-20 12:36:27 -05:00
AbsLogger . info ( { tag : 'default' , message : ` mounted: Server not connected, attempt connection ` } )
2022-04-03 14:24:17 -05:00
await this . attemptConnection ( )
}
2024-02-05 19:04:11 -06:00
await this . syncLocalSessions ( true )
2022-07-22 17:00:49 -05:00
2022-04-09 18:36:32 -05:00
this . hasMounted = true
2022-08-19 16:36:56 -04:00
2025-04-20 12:36:27 -05:00
AbsLogger . info ( { tag : 'default' , message : 'mounted: fully initialized' } )
2022-08-19 16:36:56 -04:00
this . $eventBus . $emit ( 'abs-ui-ready' )
2021-09-19 18:44:10 -05:00
}
} ,
beforeDestroy ( ) {
2023-12-04 17:53:36 -06:00
this . $eventBus . $off ( 'change-lang' , this . changeLanguage )
2023-09-10 17:51:53 -05:00
document . removeEventListener ( 'visibilitychange' , this . visibilityChanged )
2022-04-09 20:29:59 -05:00
this . $socket . off ( 'user_updated' , this . userUpdated )
2022-06-01 19:38:26 -05:00
this . $socket . off ( 'user_media_progress_updated' , this . userMediaProgressUpdated )
2021-09-01 20:07:11 -05:00
}
}
< / script >