Size
@@ -220,6 +219,10 @@ export default {
audiobooks() {
return this.media.audiobooks || []
},
+ defaultAudiobook() {
+ if (!this.audiobooks.length) return null
+ return this.audiobooks[0]
+ },
title() {
return this.mediaMetadata.title || 'No Title'
},
@@ -258,33 +261,28 @@ export default {
})
},
durationPretty() {
- return this.$elapsedPretty(this.media.duration)
+ if (!this.defaultAudiobook) return 'N/A'
+ return this.$elapsedPretty(this.defaultAudiobook.duration)
},
duration() {
- return this.media.duration
+ if (!this.defaultAudiobook) return 0
+ return this.defaultAudiobook.duration
},
sizePretty() {
- return this.$bytesPretty(this.media.size)
+ if (!this.defaultAudiobook) return 'N/A'
+ return this.$bytesPretty(this.defaultAudiobook.size)
},
libraryFiles() {
return this.libraryItem.libraryFiles || []
},
- otherAudioFiles() {
- return this.audioFiles.filter((af) => {
- return !this.tracks.find((t) => t.path === af.path)
- })
- },
- tracks() {
- return this.media.tracks || []
- },
- audioFiles() {
- return this.media.audioFiles || []
+ audiobooks() {
+ return this.media.audiobooks || []
},
ebooks() {
return this.media.ebooks || []
},
showExperimentalReadAlert() {
- return !this.tracks.length && this.ebooks.length && !this.showExperimentalFeatures
+ return !this.audiobooks.length && this.ebooks.length && !this.showExperimentalFeatures
},
description() {
return this.mediaMetadata.description || ''
@@ -292,14 +290,13 @@ export default {
userItemProgress() {
return this.$store.getters['user/getUserLibraryItemProgress'](this.libraryItemId)
},
- userCurrentTime() {
- return this.userItemProgress ? this.userItemProgress.currentTime : 0
- },
userIsFinished() {
return this.userItemProgress ? !!this.userItemProgress.isFinished : false
},
userTimeRemaining() {
- return this.duration - this.userCurrentTime
+ if (!this.userItemProgress) return 0
+ var duration = this.userItemProgress.duration || this.duration
+ return duration - this.userItemProgress.currentTime
},
progressPercent() {
return this.userItemProgress ? Math.max(Math.min(1, this.userItemProgress.progress), 0) : 0
diff --git a/client/players/AudioTrack.js b/client/players/AudioTrack.js
index 529d5a73..6cf785e2 100644
--- a/client/players/AudioTrack.js
+++ b/client/players/AudioTrack.js
@@ -26,6 +26,6 @@ export default class AudioTrack {
return `${process.env.serverUrl}${this.contentUrl}?token=${this.userToken}`
}
- return this.contentUrl + '?token=${this.userToken}'
+ return this.contentUrl + `?token=${this.userToken}`
}
}
\ No newline at end of file
diff --git a/client/players/PlayerHandler.js b/client/players/PlayerHandler.js
index e5fae273..321951cd 100644
--- a/client/players/PlayerHandler.js
+++ b/client/players/PlayerHandler.js
@@ -11,6 +11,7 @@ export default class PlayerHandler {
this.playerState = 'IDLE'
this.isHlsTranscode = false
this.currentSessionId = null
+ this.mediaEntityId = null
this.startTime = 0
this.lastSyncTime = 0
@@ -107,7 +108,7 @@ export default class PlayerHandler {
this.stopPlayInterval()
}
if (this.playerState === 'LOADED' || this.playerState === 'PLAYING') {
- this.ctx.setDuration(this.player.getDuration())
+ this.ctx.setDuration(this.getDuration())
}
if (this.playerState !== 'LOADING') {
this.ctx.setCurrentTime(this.player.getCurrentTime())
@@ -149,6 +150,7 @@ export default class PlayerHandler {
prepareSession(session) {
this.startTime = session.currentTime
this.currentSessionId = session.id
+ this.mediaEntityId = session.mediaEntityId
console.log('[PlayerHandler] Preparing Session', session)
var audioTracks = session.audioTracks.map(at => new AudioTrack(at, this.userToken))
@@ -207,7 +209,9 @@ export default class PlayerHandler {
var listeningTimeToAdd = Math.max(0, Math.floor(this.listeningTimeSinceSync))
syncData = {
timeListened: listeningTimeToAdd,
- currentTime: this.player.getCurrentTime()
+ duration: this.getDuration(),
+ mediaEntityId: this.mediaEntityId,
+ currentTime: this.getCurrentTime()
}
}
this.listeningTimeSinceSync = 0
@@ -224,6 +228,8 @@ export default class PlayerHandler {
var listeningTimeToAdd = Math.max(0, Math.floor(this.listeningTimeSinceSync))
var syncData = {
timeListened: listeningTimeToAdd,
+ duration: this.getDuration(),
+ mediaEntityId: this.mediaEntityId,
currentTime
}
this.listeningTimeSinceSync = 0
diff --git a/server/PlaybackSessionManager.js b/server/PlaybackSessionManager.js
index 6ca92d71..3e0190e2 100644
--- a/server/PlaybackSessionManager.js
+++ b/server/PlaybackSessionManager.js
@@ -80,15 +80,23 @@ class PlaybackSessionManager {
}
async syncSession(user, session, syncData) {
+ var libraryItem = this.db.libraryItems.find(li => li.id === session.libraryItemId)
+ if (!libraryItem) {
+ Logger.error(`[PlaybackSessionManager] syncSession Library Item not found "${sessino.libraryItemId}"`)
+ return
+ }
+
session.currentTime = syncData.currentTime
session.addListeningTime(syncData.timeListened)
Logger.debug(`[PlaybackSessionManager] syncSession "${session.id}" | Total Time Listened: ${session.timeListening}`)
const itemProgressUpdate = {
+ mediaEntityId: syncData.mediaEntityId || null,
+ duration: syncData.duration,
currentTime: syncData.currentTime,
progress: session.progress
}
- var wasUpdated = user.createUpdateLibraryItemProgress(session.libraryItemId, itemProgressUpdate)
+ var wasUpdated = user.createUpdateLibraryItemProgress(libraryItem, itemProgressUpdate)
if (wasUpdated) {
await this.db.updateEntity('user', user)
var itemProgress = user.getLibraryItemProgress(session.libraryItemId)
@@ -112,6 +120,8 @@ class PlaybackSessionManager {
}
saveSession(session) {
+ if (!session.timeListening) return // Do not save a session with no listening time
+
if (session.lastSave) {
return this.db.updateEntity('session', session)
} else {
diff --git a/server/controllers/MeController.js b/server/controllers/MeController.js
index 6adaaabe..8f88ed4e 100644
--- a/server/controllers/MeController.js
+++ b/server/controllers/MeController.js
@@ -23,7 +23,7 @@ class MeController {
return res.sendStatus(200)
}
await this.db.updateEntity('user', req.user)
- this.clientEmitter(req.user.id, 'user_item_progress_updated', { id: libraryItem.id, data: null })
+ // this.clientEmitter(req.user.id, 'user_item_progress_updated', { id: libraryItem.id, data: null })
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
res.sendStatus(200)
@@ -35,7 +35,7 @@ class MeController {
if (!libraryItem) {
return res.status(404).send('Item not found')
}
- var wasUpdated = req.user.createUpdateLibraryItemProgress(libraryItem.id, req.body)
+ var wasUpdated = req.user.createUpdateLibraryItemProgress(libraryItem, req.body)
if (wasUpdated) {
await this.db.updateEntity('user', req.user)
this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser())
@@ -54,7 +54,7 @@ class MeController {
itemProgressPayloads.forEach((itemProgress) => {
var libraryItem = this.db.libraryItems.find(li => li.id === itemProgress.id) // Make sure this library item exists
if (libraryItem) {
- var wasUpdated = req.user.createUpdateLibraryItemProgress(libraryItem.id, itemProgress)
+ var wasUpdated = req.user.createUpdateLibraryItemProgress(libraryItem, itemProgress)
if (wasUpdated) shouldUpdate = true
} else {
Logger.error(`[MeController] batchUpdateLibraryItemProgress: Library Item does not exist ${itemProgress.id}`)
diff --git a/server/objects/user/LibraryItemProgress.js b/server/objects/user/LibraryItemProgress.js
index 127268ea..cd3be7ca 100644
--- a/server/objects/user/LibraryItemProgress.js
+++ b/server/objects/user/LibraryItemProgress.js
@@ -4,7 +4,9 @@ class LibraryItemProgress {
constructor(progress) {
this.id = null // Same as library item id
this.libraryItemId = null
+ this.mediaEntityId = null
+ this.duration = null
this.progress = null // 0 to 1
this.currentTime = null // seconds
this.isFinished = false
@@ -22,6 +24,8 @@ class LibraryItemProgress {
return {
id: this.id,
libraryItemId: this.libraryItemId,
+ mediaEntityId: this.mediaEntityId,
+ duration: this.duration,
progress: this.progress,
currentTime: this.currentTime,
isFinished: this.isFinished,
@@ -34,6 +38,8 @@ class LibraryItemProgress {
construct(progress) {
this.id = progress.id
this.libraryItemId = progress.libraryItemId
+ this.mediaEntityId = progress.mediaEntityId || null
+ this.duration = progress.duration || 0
this.progress = progress.progress
this.currentTime = progress.currentTime
this.isFinished = !!progress.isFinished
@@ -46,9 +52,11 @@ class LibraryItemProgress {
return !this.isFinished && this.progress > 0
}
- setData(libraryItemId, progress) {
+ setData(libraryItemId, mediaEntityId, progress) {
this.id = libraryItemId
this.libraryItemId = libraryItemId
+ this.mediaEntityId = mediaEntityId
+ this.duration = progress.duration || 0
this.progress = Math.min(1, (progress.progress || 0))
this.currentTime = progress.currentTime || 0
this.isFinished = !!progress.isFinished || this.progress == 1
diff --git a/server/objects/user/User.js b/server/objects/user/User.js
index 2cd40273..1d04dda4 100644
--- a/server/objects/user/User.js
+++ b/server/objects/user/User.js
@@ -211,11 +211,20 @@ class User {
return this.libraryItemProgress.find(lip => lip.id === libraryItemId)
}
- createUpdateLibraryItemProgress(libraryItemId, updatePayload) {
- var itemProgress = this.libraryItemProgress.find(li => li.id === libraryItemId)
+ createUpdateLibraryItemProgress(libraryItem, updatePayload) {
+ var itemProgress = this.libraryItemProgress.find(li => li.id === libraryItem.id)
if (!itemProgress) {
var newItemProgress = new LibraryItemProgress()
- newItemProgress.setData(libraryItemId, updatePayload)
+
+ var mediaEntity = null
+ if (updatePayload.mediaEntityId) mediaEntity = libraryItem.media.getMediaEntityById(updatePayload.mediaEntityId)
+ if (!mediaEntity) mediaEntity = libraryItem.media.getPlaybackMediaEntity()
+ if (!mediaEntity) {
+ Logger.error(`[User] createUpdateLibraryItemProgress invalid library item has no playback media entity "${libraryItem.id}"`)
+ return false
+ }
+
+ newItemProgress.setData(libraryItem.id, mediaEntity.id, updatePayload)
this.libraryItemProgress.push(newItemProgress)
return true
}
@@ -225,7 +234,7 @@ class User {
removeLibraryItemProgress(libraryItemId) {
if (!this.libraryItemProgress.some(lip => lip.id == libraryItemId)) return false
- this.libraryItemProgress = this.libraryItemProgress.filter(lip => lip != libraryItemId)
+ this.libraryItemProgress = this.libraryItemProgress.filter(lip => lip.id != libraryItemId)
return true
}
diff --git a/server/utils/dbMigration.js b/server/utils/dbMigration.js
index 8abde1d2..c4c5bc17 100644
--- a/server/utils/dbMigration.js
+++ b/server/utils/dbMigration.js
@@ -338,6 +338,8 @@ function cleanUserObject(db, userObj) {
var liProgress = new LibraryItemProgress() // New Progress Object
liProgress.id = userAudiobookData.audiobookId // This ID will be updated when library item is created
liProgress.libraryItemId = userAudiobookData.audiobookId
+ liProgress.mediaEntityId = userAudiobookData.audiobookId
+ liProgress.duration = userAudiobookData.totalDuration
liProgress.isFinished = !!userAudiobookData.isRead
Object.keys(liProgress.toJSON()).forEach((key) => {
if (userAudiobookData[key] !== undefined) {