From ec998dc1ac4a72b4e080d30573bdd46ff4e7e4a1 Mon Sep 17 00:00:00 2001 From: advplyr Date: Sat, 15 Jul 2023 14:45:08 -0500 Subject: [PATCH] Update:Podcast library item covers show number of episodes incomplete #782 --- client/components/app/BookShelfCategorized.vue | 2 +- client/components/app/LazyBookshelf.vue | 4 ++-- client/components/cards/LazyBookCard.vue | 11 +++++++++-- server/controllers/LibraryController.js | 7 ++++++- server/objects/user/User.js | 18 ++++++++++++++++++ server/utils/libraryHelpers.js | 11 +++++++++-- 6 files changed, 45 insertions(+), 8 deletions(-) diff --git a/client/components/app/BookShelfCategorized.vue b/client/components/app/BookShelfCategorized.vue index dddb972d..b0d19df5 100644 --- a/client/components/app/BookShelfCategorized.vue +++ b/client/components/app/BookShelfCategorized.vue @@ -168,7 +168,7 @@ export default { }, async fetchCategories() { const categories = await this.$axios - .$get(`/api/libraries/${this.currentLibraryId}/personalized?include=rssfeed`) + .$get(`/api/libraries/${this.currentLibraryId}/personalized?include=rssfeed,numEpisodesIncomplete`) .then((data) => { return data }) diff --git a/client/components/app/LazyBookshelf.vue b/client/components/app/LazyBookshelf.vue index 00157ce5..9206952e 100644 --- a/client/components/app/LazyBookshelf.vue +++ b/client/components/app/LazyBookshelf.vue @@ -315,10 +315,10 @@ export default { const entityPath = this.entityName === 'series-books' ? 'items' : this.entityName 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) => { - console.error('failed to fetch books', error) + console.error('failed to fetch items', error) return null }) diff --git a/client/components/cards/LazyBookCard.vue b/client/components/cards/LazyBookCard.vue index 8b86dad0..8045f504 100644 --- a/client/components/cards/LazyBookCard.vue +++ b/client/components/cards/LazyBookCard.vue @@ -116,9 +116,14 @@ -
+

{{ numEpisodes }}

+ + +
+

{{ numEpisodesIncomplete }}

+
@@ -227,9 +232,11 @@ export default { return this.media.numTracks || 0 // toJSONMinified }, numEpisodes() { - if (!this.isPodcast) return 0 return this.media.numEpisodes || 0 }, + numEpisodesIncomplete() { + return this._libraryItem.numEpisodesIncomplete || 0 + }, processingBatch() { return this.store.state.processingBatch }, diff --git a/server/controllers/LibraryController.js b/server/controllers/LibraryController.js index ac4b2f75..b0271f59 100644 --- a/server/controllers/LibraryController.js +++ b/server/controllers/LibraryController.js @@ -198,6 +198,7 @@ class LibraryController { include: include.join(',') } const mediaIsBook = payload.mediaType === 'book' + const mediaIsPodcast = payload.mediaType === 'podcast' // Step 1 - Filter the retrieved library items let filterSeries = null @@ -236,7 +237,6 @@ class LibraryController { const sortArray = [] // 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) { 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) @@ -360,6 +360,11 @@ class LibraryController { 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 filtering by series, make sure to include the series metadata json.media.metadata.series = li.media.metadata.getSeries(filterSeries) diff --git a/server/objects/user/User.js b/server/objects/user/User.js index ae665e3b..fe1c79e2 100644 --- a/server/objects/user/User.js +++ b/server/objects/user/User.js @@ -416,5 +416,23 @@ class User { if (!progress) return false 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 \ No newline at end of file diff --git a/server/utils/libraryHelpers.js b/server/utils/libraryHelpers.js index 7c4f9cf6..aec74982 100644 --- a/server/utils/libraryHelpers.js +++ b/server/utils/libraryHelpers.js @@ -360,6 +360,7 @@ module.exports = { const mediaType = library.mediaType const isPodcastLibrary = mediaType === 'podcast' const includeRssFeed = include.includes('rssfeed') + const includeNumEpisodesIncomplete = include.includes('numepisodesincomplete') // Podcasts only const hideSingleBookSeries = library.settings.hideSingleBookSeries const shelves = [ @@ -456,12 +457,18 @@ module.exports = { for (const libraryItem of libraryItems) { 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) if (indexToPut >= 0) { - categoryMap['recently-added'].items.splice(indexToPut, 0, libraryItem.toJSONMinified()) + categoryMap['recently-added'].items.splice(indexToPut, 0, libraryItemObj) } else { - categoryMap['recently-added'].items.push(libraryItem.toJSONMinified()) + categoryMap['recently-added'].items.push(libraryItemObj) } if (categoryMap['recently-added'].items.length > maxEntitiesPerShelf) {