diff --git a/client/components/AudioPlayer.vue b/client/components/AudioPlayer.vue index cebd15df..703bf662 100644 --- a/client/components/AudioPlayer.vue +++ b/client/components/AudioPlayer.vue @@ -164,10 +164,6 @@ export default { audioPlayed() { if (!this.$refs.audio) return console.log('Audio Played', this.$refs.audio.currentTime, 'Total Duration', this.$refs.audio.duration) - // setTimeout(() => { - // console.log('Audio Played FOLLOW UP', this.$refs.audio.currentTime, 'Total Duration', this.$refs.audio.duration) - // this.startListenTimeInterval() - // }, 500) this.startListenTimeInterval() this.isPaused = this.$refs.audio.paused }, diff --git a/client/package.json b/client/package.json index 11f957bb..ea6100ba 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "audiobookshelf-client", - "version": "1.6.22", + "version": "1.6.23", "description": "Audiobook manager and player", "main": "index.js", "scripts": { diff --git a/package.json b/package.json index 997daffb..ab579d13 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "audiobookshelf", - "version": "1.6.22", + "version": "1.6.23", "description": "Self-hosted audiobook server for managing and playing audiobooks", "main": "index.js", "scripts": { diff --git a/server/ApiController.js b/server/ApiController.js index 0a5eef0d..cbe484a4 100644 --- a/server/ApiController.js +++ b/server/ApiController.js @@ -114,6 +114,8 @@ class ApiController { this.router.get('/listeningSessions', this.getCurrentUserListeningSessions.bind(this)) this.router.get('/listeningStats', this.getCurrentUserListeningStats.bind(this)) + + this.router.post('/syncUserAudiobookData', this.syncUserAudiobookData.bind(this)) } async find(req, res) { @@ -606,6 +608,12 @@ class ApiController { } req.user.resetAudiobookProgress(audiobook) await this.db.updateEntity('user', req.user) + + var userAudiobookData = req.user.audiobooks[audiobook.id] + if (userAudiobookData) { + this.clientEmitter(req.user.id, 'current_user_audiobook_update', { id: audiobook.id, data: userAudiobookData }) + } + this.clientEmitter(req.user.id, 'user_updated', req.user.toJSONForBrowser()) res.sendStatus(200) } @@ -1162,11 +1170,40 @@ class ApiController { } async getCurrentUserListeningStats(req, res) { - if (!req.user) { - return res.sendStatus(500) - } var listeningStats = await this.getUserListeningStatsHelpers(req.user.id) res.json(listeningStats) } + + async syncUserAudiobookData(req, res) { + if (!req.body.data) { + return res.status(403).send('Invalid local user audiobook data') + } + + var hasUpdates = false + + // Local user audiobook data use the latest update + req.body.data.forEach((uab) => { + if (!uab || !uab.audiobookId) { + Logger.error('[ApiController] Invalid user audiobook data', uab) + return + } + var audiobook = this.db.audiobooks.find(ab => ab.id === uab.audiobookId) + if (!audiobook) { + Logger.info('[ApiController] syncUserAudiobookData local audiobook data audiobook no longer exists', uab.audiobookId) + return + } + if (req.user.syncLocalUserAudiobookData(uab, audiobook)) { + this.clientEmitter(req.user.id, 'current_user_audiobook_update', { id: uab.audiobookId, data: uab }) + hasUpdates = true + } + }) + + if (hasUpdates) { + await this.db.updateEntity('user', req.user) + } + + var allUserAudiobookData = Object.values(req.user.audiobooksToJSON()) + res.json(allUserAudiobookData) + } } module.exports = ApiController \ No newline at end of file diff --git a/server/objects/User.js b/server/objects/User.js index 47c57fd3..bc0bdba5 100644 --- a/server/objects/User.js +++ b/server/objects/User.js @@ -328,5 +328,30 @@ class User { this.audiobooks[audiobookId].deleteBookmark(time) return this.audiobooks[audiobookId] } + + syncLocalUserAudiobookData(localUserAudiobookData, audiobook) { + if (!localUserAudiobookData || !localUserAudiobookData.audiobookId) { + Logger.error(`[User] Invalid local user audiobook data`, localUserAudiobookData) + return false + } + + if (!this.audiobooks[localUserAudiobookData.audiobookId]) { + this.audiobooks[localUserAudiobookData.audiobookId] = new UserAudiobookData(localUserAudiobookData) + return true + } + + var userAbD = this.audiobooks[localUserAudiobookData.audiobookId] + if (userAbD.lastUpdate >= localUserAudiobookData.lastUpdate) { + // Server audiobook data is more recent + return false + } + + // Local Data More recent + var wasUpdated = this.audiobooks[localUserAudiobookData.audiobookId].update(localUserAudiobookData) + if (wasUpdated) { + Logger.debug(`[User] syncLocalUserAudiobookData local data was more recent for "${audiobook.title}"`) + } + return wasUpdated + } } module.exports = User \ No newline at end of file diff --git a/server/objects/UserAudiobookData.js b/server/objects/UserAudiobookData.js index 6cbf3fb4..4043ad8e 100644 --- a/server/objects/UserAudiobookData.js +++ b/server/objects/UserAudiobookData.js @@ -5,7 +5,6 @@ class UserAudiobookData { constructor(progress) { this.audiobookId = null - this.id = null this.totalDuration = null // seconds this.progress = null // 0 to 1 this.currentTime = null // seconds