mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			157 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const uuidv4 = require("uuid").v4
 | |
| 
 | |
| class MediaProgress {
 | |
|   constructor(progress) {
 | |
|     this.id = null
 | |
|     this.userId = null
 | |
|     this.libraryItemId = null
 | |
|     this.episodeId = null // For podcasts
 | |
| 
 | |
|     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,
 | |
|       userId: this.userId,
 | |
|       libraryItemId: this.libraryItemId,
 | |
|       episodeId: this.episodeId,
 | |
|       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
 | |
|     this.userId = progress.userId
 | |
|     this.libraryItemId = progress.libraryItemId
 | |
|     this.episodeId = progress.episodeId
 | |
|     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
 | |
|   }
 | |
| 
 | |
|   setData(libraryItem, progress, episodeId, userId) {
 | |
|     this.id = uuidv4()
 | |
|     this.userId = userId
 | |
|     this.libraryItemId = libraryItem.id
 | |
|     this.episodeId = episodeId
 | |
| 
 | |
|     // 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) {
 | |
|       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 |