audiobookshelf/server/objects/user/MediaProgress.js

157 lines
4.8 KiB
JavaScript
Raw Normal View History

2023-07-05 01:14:44 +02:00
const uuidv4 = require("uuid").v4
class MediaProgress {
constructor(progress) {
this.id = null
2023-07-05 01:14:44 +02:00
this.userId = null
this.libraryItemId = null
this.episodeId = null // For podcasts
2023-07-05 01:14:44 +02:00
this.mediaItemId = null // For use in new data model
this.mediaItemType = null // For use in new data model
this.duration = null
this.progress = null // 0 to 1
this.currentTime = null // seconds
this.isFinished = false
this.hideFromContinueListening = false
this.ebookLocation = null // cfi tag for epub, page number for pdf
this.ebookProgress = null // 0 to 1
this.lastUpdate = null
this.startedAt = null
this.finishedAt = null
if (progress) {
this.construct(progress)
}
}
toJSON() {
return {
id: this.id,
2023-07-05 01:14:44 +02:00
userId: this.userId,
libraryItemId: this.libraryItemId,
episodeId: this.episodeId,
2023-07-05 01:14:44 +02:00
mediaItemId: this.mediaItemId,
mediaItemType: this.mediaItemType,
duration: this.duration,
progress: this.progress,
currentTime: this.currentTime,
isFinished: this.isFinished,
hideFromContinueListening: this.hideFromContinueListening,
ebookLocation: this.ebookLocation,
ebookProgress: this.ebookProgress,
lastUpdate: this.lastUpdate,
startedAt: this.startedAt,
finishedAt: this.finishedAt
}
}
construct(progress) {
this.id = progress.id
2023-07-05 01:14:44 +02:00
this.userId = progress.userId
this.libraryItemId = progress.libraryItemId
this.episodeId = progress.episodeId
2023-07-05 01:14:44 +02:00
this.mediaItemId = progress.mediaItemId
this.mediaItemType = progress.mediaItemType
this.duration = progress.duration || 0
this.progress = progress.progress
this.currentTime = progress.currentTime || 0
this.isFinished = !!progress.isFinished
this.hideFromContinueListening = !!progress.hideFromContinueListening
this.ebookLocation = progress.ebookLocation || null
this.ebookProgress = progress.ebookProgress || null
this.lastUpdate = progress.lastUpdate
this.startedAt = progress.startedAt
this.finishedAt = progress.finishedAt || null
}
get inProgress() {
return !this.isFinished && (this.progress > 0 || (this.ebookLocation != null && this.ebookProgress > 0))
}
get notStarted() {
return !this.isFinished && this.progress == 0
}
2023-07-05 01:14:44 +02:00
setData(libraryItem, progress, episodeId, userId) {
this.id = uuidv4()
this.userId = userId
this.libraryItemId = libraryItem.id
this.episodeId = episodeId
2023-07-05 01:14:44 +02:00
// PodcastEpisodeId or BookId
this.mediaItemId = episodeId || libraryItem.media.id
this.mediaItemType = episodeId ? 'podcastEpisode' : 'book'
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
this.hideFromContinueListening = !!progress.hideFromContinueListening
this.ebookLocation = progress.ebookLocation
this.ebookProgress = Math.min(1, (progress.ebookProgress || 0))
this.lastUpdate = Date.now()
this.finishedAt = null
if (this.isFinished) {
this.finishedAt = progress.finishedAt || Date.now()
this.progress = 1
}
this.startedAt = progress.startedAt || this.finishedAt || Date.now()
}
update(payload) {
let hasUpdates = false
for (const key in payload) {
2022-01-06 02:07:32 +01:00
if (this[key] !== undefined && payload[key] !== this[key]) {
if (key === 'isFinished') {
if (!payload[key]) { // Updating to Not Finished - Reset progress and current time
this.finishedAt = null
this.progress = 0
this.currentTime = 0
} else { // Updating to Finished
if (!this.finishedAt) this.finishedAt = Date.now()
this.progress = 1
}
}
this[key] = payload[key]
hasUpdates = true
}
}
var timeRemaining = this.duration - this.currentTime
// If time remaining is less than 5 seconds then mark as finished
if ((this.progress >= 1 || (this.duration && !isNaN(timeRemaining) && timeRemaining < 5))) {
this.isFinished = true
this.finishedAt = payload.finishedAt || Date.now()
this.progress = 1
} else if (this.progress < 1 && this.isFinished) {
this.isFinished = false
this.finishedAt = null
}
if (!this.startedAt) {
this.startedAt = this.finishedAt || Date.now()
}
if (hasUpdates) {
if (payload.hideFromContinueListening === undefined) {
// Reset this flag when the media progress is updated
this.hideFromContinueListening = false
}
this.lastUpdate = Date.now()
}
return hasUpdates
}
removeFromContinueListening() {
if (this.hideFromContinueListening) return false
this.hideFromContinueListening = true
return true
}
}
module.exports = MediaProgress