mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Update:Podcast library item covers show number of episodes incomplete #782
This commit is contained in:
		
							parent
							
								
									ddc54c8811
								
							
						
					
					
						commit
						ec998dc1ac
					
				@ -168,7 +168,7 @@ export default {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    async fetchCategories() {
 | 
					    async fetchCategories() {
 | 
				
			||||||
      const categories = await this.$axios
 | 
					      const categories = await this.$axios
 | 
				
			||||||
        .$get(`/api/libraries/${this.currentLibraryId}/personalized?include=rssfeed`)
 | 
					        .$get(`/api/libraries/${this.currentLibraryId}/personalized?include=rssfeed,numEpisodesIncomplete`)
 | 
				
			||||||
        .then((data) => {
 | 
					        .then((data) => {
 | 
				
			||||||
          return data
 | 
					          return data
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
 | 
				
			|||||||
@ -315,10 +315,10 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      const entityPath = this.entityName === 'series-books' ? 'items' : this.entityName
 | 
					      const entityPath = this.entityName === 'series-books' ? 'items' : this.entityName
 | 
				
			||||||
      const sfQueryString = this.currentSFQueryString ? this.currentSFQueryString + '&' : ''
 | 
					      const sfQueryString = this.currentSFQueryString ? this.currentSFQueryString + '&' : ''
 | 
				
			||||||
      const fullQueryString = `?${sfQueryString}limit=${this.booksPerFetch}&page=${page}&minified=1&include=rssfeed`
 | 
					      const fullQueryString = `?${sfQueryString}limit=${this.booksPerFetch}&page=${page}&minified=1&include=rssfeed,numEpisodesIncomplete`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const payload = await this.$axios.$get(`/api/libraries/${this.currentLibraryId}/${entityPath}${fullQueryString}`).catch((error) => {
 | 
					      const payload = await this.$axios.$get(`/api/libraries/${this.currentLibraryId}/${entityPath}${fullQueryString}`).catch((error) => {
 | 
				
			||||||
        console.error('failed to fetch books', error)
 | 
					        console.error('failed to fetch items', error)
 | 
				
			||||||
        return null
 | 
					        return null
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -116,9 +116,14 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <!-- Podcast Num Episodes -->
 | 
					    <!-- Podcast Num Episodes -->
 | 
				
			||||||
    <div v-else-if="numEpisodes && !isHovering && !isSelectionMode" class="absolute rounded-full bg-black bg-opacity-90 box-shadow-md z-10 flex items-center justify-center" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', width: 1.25 * sizeMultiplier + 'rem', height: 1.25 * sizeMultiplier + 'rem' }">
 | 
					    <div v-else-if="!numEpisodesIncomplete && numEpisodes && !isHovering && !isSelectionMode" class="absolute rounded-full bg-black bg-opacity-90 box-shadow-md z-10 flex items-center justify-center" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', width: 1.25 * sizeMultiplier + 'rem', height: 1.25 * sizeMultiplier + 'rem' }">
 | 
				
			||||||
      <p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">{{ numEpisodes }}</p>
 | 
					      <p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">{{ numEpisodes }}</p>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Podcast Num Episodes -->
 | 
				
			||||||
 | 
					    <div v-else-if="numEpisodesIncomplete && !isHovering && !isSelectionMode" class="absolute rounded-full bg-yellow-400 text-black font-semibold box-shadow-md z-10 flex items-center justify-center" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', width: 1.25 * sizeMultiplier + 'rem', height: 1.25 * sizeMultiplier + 'rem' }">
 | 
				
			||||||
 | 
					      <p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">{{ numEpisodesIncomplete }}</p>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -227,9 +232,11 @@ export default {
 | 
				
			|||||||
      return this.media.numTracks || 0 // toJSONMinified
 | 
					      return this.media.numTracks || 0 // toJSONMinified
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    numEpisodes() {
 | 
					    numEpisodes() {
 | 
				
			||||||
      if (!this.isPodcast) return 0
 | 
					 | 
				
			||||||
      return this.media.numEpisodes || 0
 | 
					      return this.media.numEpisodes || 0
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    numEpisodesIncomplete() {
 | 
				
			||||||
 | 
					      return this._libraryItem.numEpisodesIncomplete || 0
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    processingBatch() {
 | 
					    processingBatch() {
 | 
				
			||||||
      return this.store.state.processingBatch
 | 
					      return this.store.state.processingBatch
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
				
			|||||||
@ -198,6 +198,7 @@ class LibraryController {
 | 
				
			|||||||
      include: include.join(',')
 | 
					      include: include.join(',')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    const mediaIsBook = payload.mediaType === 'book'
 | 
					    const mediaIsBook = payload.mediaType === 'book'
 | 
				
			||||||
 | 
					    const mediaIsPodcast = payload.mediaType === 'podcast'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Step 1 - Filter the retrieved library items
 | 
					    // Step 1 - Filter the retrieved library items
 | 
				
			||||||
    let filterSeries = null
 | 
					    let filterSeries = null
 | 
				
			||||||
@ -236,7 +237,6 @@ class LibraryController {
 | 
				
			|||||||
    const sortArray = []
 | 
					    const sortArray = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // When on the series page, sort by sequence only
 | 
					    // When on the series page, sort by sequence only
 | 
				
			||||||
    if (payload.sortBy === 'book.volumeNumber') payload.sortBy = null // TODO: Remove temp fix after mobile release 0.9.60
 | 
					 | 
				
			||||||
    if (filterSeries && !payload.sortBy) {
 | 
					    if (filterSeries && !payload.sortBy) {
 | 
				
			||||||
      sortArray.push({ asc: (li) => li.media.metadata.getSeries(filterSeries).sequence })
 | 
					      sortArray.push({ asc: (li) => li.media.metadata.getSeries(filterSeries).sequence })
 | 
				
			||||||
      // If no series sequence then fallback to sorting by title (or collapsed series name for sub-series)
 | 
					      // If no series sequence then fallback to sorting by title (or collapsed series name for sub-series)
 | 
				
			||||||
@ -360,6 +360,11 @@ class LibraryController {
 | 
				
			|||||||
          json.rssFeed = feedData ? feedData.toJSONMinified() : null
 | 
					          json.rssFeed = feedData ? feedData.toJSONMinified() : null
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // add numEpisodesIncomplete if "include=numEpisodesIncomplete" was put in query string (only for podcasts)
 | 
				
			||||||
 | 
					        if (mediaIsPodcast && include.includes('numepisodesincomplete')) {
 | 
				
			||||||
 | 
					          json.numEpisodesIncomplete = req.user.getNumEpisodesIncompleteForPodcast(li)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (filterSeries) {
 | 
					        if (filterSeries) {
 | 
				
			||||||
          // If filtering by series, make sure to include the series metadata
 | 
					          // If filtering by series, make sure to include the series metadata
 | 
				
			||||||
          json.media.metadata.series = li.media.metadata.getSeries(filterSeries)
 | 
					          json.media.metadata.series = li.media.metadata.getSeries(filterSeries)
 | 
				
			||||||
 | 
				
			|||||||
@ -416,5 +416,23 @@ class User {
 | 
				
			|||||||
    if (!progress) return false
 | 
					    if (!progress) return false
 | 
				
			||||||
    return progress.removeFromContinueListening()
 | 
					    return progress.removeFromContinueListening()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Number of podcast episodes not finished for library item
 | 
				
			||||||
 | 
					   * Note: libraryItem passed in from libraryHelpers is not a LibraryItem class instance
 | 
				
			||||||
 | 
					   * @param {LibraryItem|object} libraryItem 
 | 
				
			||||||
 | 
					   * @returns {number}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  getNumEpisodesIncompleteForPodcast(libraryItem) {
 | 
				
			||||||
 | 
					    if (!libraryItem?.media.episodes) return 0
 | 
				
			||||||
 | 
					    let numEpisodesIncomplete = 0
 | 
				
			||||||
 | 
					    for (const episode of libraryItem.media.episodes) {
 | 
				
			||||||
 | 
					      const mediaProgress = this.getMediaProgress(libraryItem.id, episode.id)
 | 
				
			||||||
 | 
					      if (!mediaProgress?.isFinished) {
 | 
				
			||||||
 | 
					        numEpisodesIncomplete++
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return numEpisodesIncomplete
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
module.exports = User
 | 
					module.exports = User
 | 
				
			||||||
@ -360,6 +360,7 @@ module.exports = {
 | 
				
			|||||||
    const mediaType = library.mediaType
 | 
					    const mediaType = library.mediaType
 | 
				
			||||||
    const isPodcastLibrary = mediaType === 'podcast'
 | 
					    const isPodcastLibrary = mediaType === 'podcast'
 | 
				
			||||||
    const includeRssFeed = include.includes('rssfeed')
 | 
					    const includeRssFeed = include.includes('rssfeed')
 | 
				
			||||||
 | 
					    const includeNumEpisodesIncomplete = include.includes('numepisodesincomplete') // Podcasts only
 | 
				
			||||||
    const hideSingleBookSeries = library.settings.hideSingleBookSeries
 | 
					    const hideSingleBookSeries = library.settings.hideSingleBookSeries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const shelves = [
 | 
					    const shelves = [
 | 
				
			||||||
@ -456,12 +457,18 @@ module.exports = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for (const libraryItem of libraryItems) {
 | 
					    for (const libraryItem of libraryItems) {
 | 
				
			||||||
      if (libraryItem.addedAt > categoryMap['recently-added'].smallest) {
 | 
					      if (libraryItem.addedAt > categoryMap['recently-added'].smallest) {
 | 
				
			||||||
 | 
					        const libraryItemObj = libraryItem.toJSONMinified()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // add numEpisodesIncomplete if "include=numEpisodesIncomplete" was put in query string (only for podcasts)
 | 
				
			||||||
 | 
					        if (includeNumEpisodesIncomplete && libraryItem.isPodcast) {
 | 
				
			||||||
 | 
					          libraryItemObj.numEpisodesIncomplete = user.getNumEpisodesIncompleteForPodcast(libraryItem)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const indexToPut = categoryMap['recently-added'].items.findIndex(i => libraryItem.addedAt > i.addedAt)
 | 
					        const indexToPut = categoryMap['recently-added'].items.findIndex(i => libraryItem.addedAt > i.addedAt)
 | 
				
			||||||
        if (indexToPut >= 0) {
 | 
					        if (indexToPut >= 0) {
 | 
				
			||||||
          categoryMap['recently-added'].items.splice(indexToPut, 0, libraryItem.toJSONMinified())
 | 
					          categoryMap['recently-added'].items.splice(indexToPut, 0, libraryItemObj)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          categoryMap['recently-added'].items.push(libraryItem.toJSONMinified())
 | 
					          categoryMap['recently-added'].items.push(libraryItemObj)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (categoryMap['recently-added'].items.length > maxEntitiesPerShelf) {
 | 
					        if (categoryMap['recently-added'].items.length > maxEntitiesPerShelf) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user