mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Update:Setup variables to control when a media item is marked as finished. By time remaining or progress percentage #837
This commit is contained in:
		
							parent
							
								
									953ffe889e
								
							
						
					
					
						commit
						9896e4381b
					
				| @ -297,7 +297,6 @@ export default class PlayerHandler { | |||||||
|       if (listeningTimeToAdd > 20) { |       if (listeningTimeToAdd > 20) { | ||||||
|         syncData = { |         syncData = { | ||||||
|           timeListened: listeningTimeToAdd, |           timeListened: listeningTimeToAdd, | ||||||
|           duration: this.getDuration(), |  | ||||||
|           currentTime: this.getCurrentTime() |           currentTime: this.getCurrentTime() | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
| @ -317,7 +316,6 @@ export default class PlayerHandler { | |||||||
|     const listeningTimeToAdd = Math.max(0, Math.floor(this.listeningTimeSinceSync)) |     const listeningTimeToAdd = Math.max(0, Math.floor(this.listeningTimeSinceSync)) | ||||||
|     const syncData = { |     const syncData = { | ||||||
|       timeListened: listeningTimeToAdd, |       timeListened: listeningTimeToAdd, | ||||||
|       duration: this.getDuration(), |  | ||||||
|       currentTime |       currentTime | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -343,9 +343,13 @@ class PlaybackSessionManager { | |||||||
|     const updateResponse = await user.createUpdateMediaProgressFromPayload({ |     const updateResponse = await user.createUpdateMediaProgressFromPayload({ | ||||||
|       libraryItemId: libraryItem.id, |       libraryItemId: libraryItem.id, | ||||||
|       episodeId: session.episodeId, |       episodeId: session.episodeId, | ||||||
|       duration: syncData.duration, |       // duration no longer required (v2.15.1) but used if available
 | ||||||
|  |       duration: syncData.duration || libraryItem.media.duration || 0, | ||||||
|       currentTime: syncData.currentTime, |       currentTime: syncData.currentTime, | ||||||
|       progress: session.progress |       progress: session.progress | ||||||
|  |       // TODO: Add support for passing in these values from library settings
 | ||||||
|  |       // markAsFinishedTimeRemaining: 5,
 | ||||||
|  |       // markAsFinishedPercentageComplete: 95
 | ||||||
|     }) |     }) | ||||||
|     if (updateResponse.mediaProgress) { |     if (updateResponse.mediaProgress) { | ||||||
|       SocketAuthority.clientEmitter(user.id, 'user_item_progress_updated', { |       SocketAuthority.clientEmitter(user.id, 'user_item_progress_updated', { | ||||||
|  | |||||||
| @ -1,4 +1,6 @@ | |||||||
| const { DataTypes, Model } = require('sequelize') | const { DataTypes, Model } = require('sequelize') | ||||||
|  | const Logger = require('../Logger') | ||||||
|  | const { isNullOrNaN } = require('../utils') | ||||||
| 
 | 
 | ||||||
| class MediaProgress extends Model { | class MediaProgress extends Model { | ||||||
|   constructor(values, options) { |   constructor(values, options) { | ||||||
| @ -183,10 +185,16 @@ class MediaProgress extends Model { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   get progress() { | ||||||
|  |     // Value between 0 and 1
 | ||||||
|  |     if (!this.duration) return 0 | ||||||
|  |     return Math.max(0, Math.min(this.currentTime / this.duration, 1)) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   /** |   /** | ||||||
|    * Apply update to media progress |    * Apply update to media progress | ||||||
|    * |    * | ||||||
|    * @param {Object} progress |    * @param {import('./User').ProgressUpdatePayload} progressPayload | ||||||
|    * @returns {Promise<MediaProgress>} |    * @returns {Promise<MediaProgress>} | ||||||
|    */ |    */ | ||||||
|   applyProgressUpdate(progressPayload) { |   applyProgressUpdate(progressPayload) { | ||||||
| @ -219,8 +227,27 @@ class MediaProgress extends Model { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const timeRemaining = this.duration - this.currentTime |     const timeRemaining = this.duration - this.currentTime | ||||||
|     // Set to finished if time remaining is less than 5 seconds
 | 
 | ||||||
|     if (!this.isFinished && this.duration && timeRemaining < 5) { |     // Check if progress is far enough to mark as finished
 | ||||||
|  |     //   - If markAsFinishedPercentageComplete is provided, use that otherwise use markAsFinishedTimeRemaining (default 5 seconds)
 | ||||||
|  |     let shouldMarkAsFinished = false | ||||||
|  |     if (!this.isFinished && this.duration) { | ||||||
|  |       if (!isNullOrNaN(progressPayload.markAsFinishedPercentageComplete)) { | ||||||
|  |         const markAsFinishedPercentageComplete = Number(progressPayload.markAsFinishedPercentageComplete) / 100 | ||||||
|  |         shouldMarkAsFinished = markAsFinishedPercentageComplete <= this.progress | ||||||
|  |         if (shouldMarkAsFinished) { | ||||||
|  |           Logger.debug(`[MediaProgress] Marking media progress as finished because progress (${this.progress}) is greater than ${markAsFinishedPercentageComplete}`) | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         const markAsFinishedTimeRemaining = isNullOrNaN(progressPayload.markAsFinishedTimeRemaining) ? 5 : Number(progressPayload.markAsFinishedTimeRemaining) | ||||||
|  |         shouldMarkAsFinished = timeRemaining <= markAsFinishedTimeRemaining | ||||||
|  |         if (shouldMarkAsFinished) { | ||||||
|  |           Logger.debug(`[MediaProgress] Marking media progress as finished because time remaining (${timeRemaining}) is less than ${markAsFinishedTimeRemaining} seconds`) | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (shouldMarkAsFinished) { | ||||||
|       this.isFinished = true |       this.isFinished = true | ||||||
|       this.finishedAt = this.finishedAt || Date.now() |       this.finishedAt = this.finishedAt || Date.now() | ||||||
|       this.extraData.progress = 1 |       this.extraData.progress = 1 | ||||||
|  | |||||||
| @ -14,6 +14,23 @@ const { DataTypes, Model } = sequelize | |||||||
|  * @property {number} createdAt |  * @property {number} createdAt | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @typedef ProgressUpdatePayload | ||||||
|  |  * @property {string} libraryItemId | ||||||
|  |  * @property {string} [episodeId] | ||||||
|  |  * @property {number} [duration] | ||||||
|  |  * @property {number} [progress] | ||||||
|  |  * @property {number} [currentTime] | ||||||
|  |  * @property {boolean} [isFinished] | ||||||
|  |  * @property {boolean} [hideFromContinueListening] | ||||||
|  |  * @property {string} [ebookLocation] | ||||||
|  |  * @property {number} [ebookProgress] | ||||||
|  |  * @property {string} [finishedAt] | ||||||
|  |  * @property {number} [lastUpdate] | ||||||
|  |  * @property {number} [markAsFinishedTimeRemaining] | ||||||
|  |  * @property {number} [markAsFinishedPercentageComplete] | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| class User extends Model { | class User extends Model { | ||||||
|   constructor(values, options) { |   constructor(values, options) { | ||||||
|     super(values, options) |     super(values, options) | ||||||
| @ -515,19 +532,6 @@ class User extends Model { | |||||||
|   /** |   /** | ||||||
|    * TODO: Uses old model and should account for the different between ebook/audiobook progress |    * TODO: Uses old model and should account for the different between ebook/audiobook progress | ||||||
|    * |    * | ||||||
|    * @typedef ProgressUpdatePayload |  | ||||||
|    * @property {string} libraryItemId |  | ||||||
|    * @property {string} [episodeId] |  | ||||||
|    * @property {number} [duration] |  | ||||||
|    * @property {number} [progress] |  | ||||||
|    * @property {number} [currentTime] |  | ||||||
|    * @property {boolean} [isFinished] |  | ||||||
|    * @property {boolean} [hideFromContinueListening] |  | ||||||
|    * @property {string} [ebookLocation] |  | ||||||
|    * @property {number} [ebookProgress] |  | ||||||
|    * @property {string} [finishedAt] |  | ||||||
|    * @property {number} [lastUpdate] |  | ||||||
|    * |  | ||||||
|    * @param {ProgressUpdatePayload} progressPayload |    * @param {ProgressUpdatePayload} progressPayload | ||||||
|    * @returns {Promise<{ mediaProgress: import('./MediaProgress'), error: [string], statusCode: [number] }>} |    * @returns {Promise<{ mediaProgress: import('./MediaProgress'), error: [string], statusCode: [number] }>} | ||||||
|    */ |    */ | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user