mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-01-03 00:06:46 +01:00
Merge branch 'master' into LocalizedDateFns
This commit is contained in:
commit
74d8a09f31
@ -820,7 +820,6 @@ export default {
|
|||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
if (!libraryItem) return
|
if (!libraryItem) return
|
||||||
console.log('Got library itemn', libraryItem)
|
|
||||||
this.store.commit('showEReader', libraryItem)
|
this.store.commit('showEReader', libraryItem)
|
||||||
},
|
},
|
||||||
selectBtnClick(evt) {
|
selectBtnClick(evt) {
|
||||||
|
@ -308,6 +308,7 @@
|
|||||||
"LabelPublishYear": "Jahr",
|
"LabelPublishYear": "Jahr",
|
||||||
"LabelRecentlyAdded": "Kürzlich hinzugefügt",
|
"LabelRecentlyAdded": "Kürzlich hinzugefügt",
|
||||||
"LabelRecentSeries": "Aktuelle Serien",
|
"LabelRecentSeries": "Aktuelle Serien",
|
||||||
|
"LabelRecommended": "Recommended",
|
||||||
"LabelRegion": "Region",
|
"LabelRegion": "Region",
|
||||||
"LabelReleaseDate": "Veröffentlichungsdatum",
|
"LabelReleaseDate": "Veröffentlichungsdatum",
|
||||||
"LabelRemoveCover": "Lösche Titelbild",
|
"LabelRemoveCover": "Lösche Titelbild",
|
||||||
|
@ -308,6 +308,7 @@
|
|||||||
"LabelPublishYear": "Publish Year",
|
"LabelPublishYear": "Publish Year",
|
||||||
"LabelRecentlyAdded": "Recently Added",
|
"LabelRecentlyAdded": "Recently Added",
|
||||||
"LabelRecentSeries": "Recent Series",
|
"LabelRecentSeries": "Recent Series",
|
||||||
|
"LabelRecommended": "Recommended",
|
||||||
"LabelRegion": "Region",
|
"LabelRegion": "Region",
|
||||||
"LabelReleaseDate": "Release Date",
|
"LabelReleaseDate": "Release Date",
|
||||||
"LabelRemoveCover": "Remove cover",
|
"LabelRemoveCover": "Remove cover",
|
||||||
|
@ -308,6 +308,7 @@
|
|||||||
"LabelPublishYear": "Publish Year",
|
"LabelPublishYear": "Publish Year",
|
||||||
"LabelRecentlyAdded": "Recently Added",
|
"LabelRecentlyAdded": "Recently Added",
|
||||||
"LabelRecentSeries": "Recent Series",
|
"LabelRecentSeries": "Recent Series",
|
||||||
|
"LabelRecommended": "Recommended",
|
||||||
"LabelRegion": "Region",
|
"LabelRegion": "Region",
|
||||||
"LabelReleaseDate": "Release Date",
|
"LabelReleaseDate": "Release Date",
|
||||||
"LabelRemoveCover": "Remove cover",
|
"LabelRemoveCover": "Remove cover",
|
||||||
|
@ -308,6 +308,7 @@
|
|||||||
"LabelPublishYear": "Année d'Edition",
|
"LabelPublishYear": "Année d'Edition",
|
||||||
"LabelRecentlyAdded": "Derniers Ajouts",
|
"LabelRecentlyAdded": "Derniers Ajouts",
|
||||||
"LabelRecentSeries": "Séries Récentes",
|
"LabelRecentSeries": "Séries Récentes",
|
||||||
|
"LabelRecommended": "Recommended",
|
||||||
"LabelRegion": "Région",
|
"LabelRegion": "Région",
|
||||||
"LabelReleaseDate": "Date de Parution",
|
"LabelReleaseDate": "Date de Parution",
|
||||||
"LabelRemoveCover": "Supprimer la Couverture",
|
"LabelRemoveCover": "Supprimer la Couverture",
|
||||||
|
@ -308,6 +308,7 @@
|
|||||||
"LabelPublishYear": "Godina izdavanja",
|
"LabelPublishYear": "Godina izdavanja",
|
||||||
"LabelRecentlyAdded": "Nedavno dodano",
|
"LabelRecentlyAdded": "Nedavno dodano",
|
||||||
"LabelRecentSeries": "Nedavne serije",
|
"LabelRecentSeries": "Nedavne serije",
|
||||||
|
"LabelRecommended": "Recommended",
|
||||||
"LabelRegion": "Regija",
|
"LabelRegion": "Regija",
|
||||||
"LabelReleaseDate": "Datum izlaska",
|
"LabelReleaseDate": "Datum izlaska",
|
||||||
"LabelRemoveCover": "Remove cover",
|
"LabelRemoveCover": "Remove cover",
|
||||||
|
@ -308,6 +308,7 @@
|
|||||||
"LabelPublishYear": "Anno Pubblicazione",
|
"LabelPublishYear": "Anno Pubblicazione",
|
||||||
"LabelRecentlyAdded": "Aggiunti Recentemente",
|
"LabelRecentlyAdded": "Aggiunti Recentemente",
|
||||||
"LabelRecentSeries": "Serie Recenti",
|
"LabelRecentSeries": "Serie Recenti",
|
||||||
|
"LabelRecommended": "Recommended",
|
||||||
"LabelRegion": "Regione",
|
"LabelRegion": "Regione",
|
||||||
"LabelReleaseDate": "Data Release",
|
"LabelReleaseDate": "Data Release",
|
||||||
"LabelRemoveCover": "Remove cover",
|
"LabelRemoveCover": "Remove cover",
|
||||||
|
@ -308,6 +308,7 @@
|
|||||||
"LabelPublishYear": "Rok publikacji",
|
"LabelPublishYear": "Rok publikacji",
|
||||||
"LabelRecentlyAdded": "Niedawno dodany",
|
"LabelRecentlyAdded": "Niedawno dodany",
|
||||||
"LabelRecentSeries": "Ostatnie serie",
|
"LabelRecentSeries": "Ostatnie serie",
|
||||||
|
"LabelRecommended": "Recommended",
|
||||||
"LabelRegion": "Region",
|
"LabelRegion": "Region",
|
||||||
"LabelReleaseDate": "Data wydania",
|
"LabelReleaseDate": "Data wydania",
|
||||||
"LabelRemoveCover": "Remove cover",
|
"LabelRemoveCover": "Remove cover",
|
||||||
|
@ -308,6 +308,7 @@
|
|||||||
"LabelPublishYear": "发布年份",
|
"LabelPublishYear": "发布年份",
|
||||||
"LabelRecentlyAdded": "最近添加",
|
"LabelRecentlyAdded": "最近添加",
|
||||||
"LabelRecentSeries": "最近添加系列",
|
"LabelRecentSeries": "最近添加系列",
|
||||||
|
"LabelRecommended": "推荐内容",
|
||||||
"LabelRegion": "区域",
|
"LabelRegion": "区域",
|
||||||
"LabelReleaseDate": "发布日期",
|
"LabelReleaseDate": "发布日期",
|
||||||
"LabelRemoveCover": "移除封面",
|
"LabelRemoveCover": "移除封面",
|
||||||
|
@ -192,7 +192,8 @@ class MeController {
|
|||||||
}
|
}
|
||||||
const updatedLocalMediaProgress = []
|
const updatedLocalMediaProgress = []
|
||||||
var numServerProgressUpdates = 0
|
var numServerProgressUpdates = 0
|
||||||
var localMediaProgress = req.body.localMediaProgress || []
|
const updatedServerMediaProgress = []
|
||||||
|
const localMediaProgress = req.body.localMediaProgress || []
|
||||||
|
|
||||||
localMediaProgress.forEach(localProgress => {
|
localMediaProgress.forEach(localProgress => {
|
||||||
if (!localProgress.libraryItemId) {
|
if (!localProgress.libraryItemId) {
|
||||||
@ -205,18 +206,22 @@ class MeController {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var mediaProgress = req.user.getMediaProgress(localProgress.libraryItemId, localProgress.episodeId)
|
let mediaProgress = req.user.getMediaProgress(localProgress.libraryItemId, localProgress.episodeId)
|
||||||
if (!mediaProgress) {
|
if (!mediaProgress) {
|
||||||
// New media progress from mobile
|
// New media progress from mobile
|
||||||
Logger.debug(`[MeController] syncLocalMediaProgress local progress is new - creating ${localProgress.id}`)
|
Logger.debug(`[MeController] syncLocalMediaProgress local progress is new - creating ${localProgress.id}`)
|
||||||
req.user.createUpdateMediaProgress(libraryItem, localProgress, localProgress.episodeId)
|
req.user.createUpdateMediaProgress(libraryItem, localProgress, localProgress.episodeId)
|
||||||
|
mediaProgress = req.user.getMediaProgress(localProgress.libraryItemId, localProgress.episodeId)
|
||||||
|
updatedServerMediaProgress.push(mediaProgress)
|
||||||
numServerProgressUpdates++
|
numServerProgressUpdates++
|
||||||
} else if (mediaProgress.lastUpdate < localProgress.lastUpdate) {
|
} else if (mediaProgress.lastUpdate < localProgress.lastUpdate) {
|
||||||
Logger.debug(`[MeController] syncLocalMediaProgress local progress is more recent - updating ${mediaProgress.id}`)
|
Logger.debug(`[MeController] syncLocalMediaProgress local progress is more recent - updating ${mediaProgress.id}`)
|
||||||
req.user.createUpdateMediaProgress(libraryItem, localProgress, localProgress.episodeId)
|
req.user.createUpdateMediaProgress(libraryItem, localProgress, localProgress.episodeId)
|
||||||
|
mediaProgress = req.user.getMediaProgress(localProgress.libraryItemId, localProgress.episodeId)
|
||||||
|
updatedServerMediaProgress.push(mediaProgress)
|
||||||
numServerProgressUpdates++
|
numServerProgressUpdates++
|
||||||
} else if (mediaProgress.lastUpdate > localProgress.lastUpdate) {
|
} else if (mediaProgress.lastUpdate > localProgress.lastUpdate) {
|
||||||
var updateTimeDifference = mediaProgress.lastUpdate - localProgress.lastUpdate
|
const updateTimeDifference = mediaProgress.lastUpdate - localProgress.lastUpdate
|
||||||
Logger.debug(`[MeController] syncLocalMediaProgress server progress is more recent by ${updateTimeDifference}ms - ${mediaProgress.id}`)
|
Logger.debug(`[MeController] syncLocalMediaProgress server progress is more recent by ${updateTimeDifference}ms - ${mediaProgress.id}`)
|
||||||
|
|
||||||
for (const key in localProgress) {
|
for (const key in localProgress) {
|
||||||
@ -240,7 +245,8 @@ class MeController {
|
|||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
numServerProgressUpdates,
|
numServerProgressUpdates,
|
||||||
localProgressUpdates: updatedLocalMediaProgress
|
localProgressUpdates: updatedLocalMediaProgress, // Array of LocalMediaProgress that were updated from server (server more recent)
|
||||||
|
serverProgressUpdates: updatedServerMediaProgress // Array of MediaProgress that made updates to server (local more recent)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,9 +81,17 @@ class RssFeedManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if feed needs to be updated
|
// Check if feed needs to be updated
|
||||||
if (feed.entityType === 'item') {
|
if (feed.entityType === 'libraryItem') {
|
||||||
const libraryItem = this.db.getLibraryItem(feed.entityId)
|
const libraryItem = this.db.getLibraryItem(feed.entityId)
|
||||||
if (libraryItem && (!feed.entityUpdatedAt || libraryItem.updatedAt > feed.entityUpdatedAt)) {
|
|
||||||
|
let mostRecentlyUpdatedAt = libraryItem.updatedAt
|
||||||
|
if (libraryItem.isPodcast) {
|
||||||
|
libraryItem.media.episodes.forEach((episode) => {
|
||||||
|
if (episode.updatedAt > mostRecentlyUpdatedAt) mostRecentlyUpdatedAt = episode.updatedAt
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libraryItem && (!feed.entityUpdatedAt || mostRecentlyUpdatedAt > feed.entityUpdatedAt)) {
|
||||||
Logger.debug(`[RssFeedManager] Updating RSS feed for item ${libraryItem.id} "${libraryItem.media.metadata.title}"`)
|
Logger.debug(`[RssFeedManager] Updating RSS feed for item ${libraryItem.id} "${libraryItem.media.metadata.title}"`)
|
||||||
feed.updateFromItem(libraryItem)
|
feed.updateFromItem(libraryItem)
|
||||||
await this.db.updateEntity('feed', feed)
|
await this.db.updateEntity('feed', feed)
|
||||||
|
@ -110,13 +110,15 @@ class Feed {
|
|||||||
this.episodes = []
|
this.episodes = []
|
||||||
if (isPodcast) { // PODCAST EPISODES
|
if (isPodcast) { // PODCAST EPISODES
|
||||||
media.episodes.forEach((episode) => {
|
media.episodes.forEach((episode) => {
|
||||||
var feedEpisode = new FeedEpisode()
|
if (episode.updatedAt > this.entityUpdatedAt) this.entityUpdatedAt = episode.updatedAt
|
||||||
|
|
||||||
|
const feedEpisode = new FeedEpisode()
|
||||||
feedEpisode.setFromPodcastEpisode(libraryItem, serverAddress, slug, episode, this.meta)
|
feedEpisode.setFromPodcastEpisode(libraryItem, serverAddress, slug, episode, this.meta)
|
||||||
this.episodes.push(feedEpisode)
|
this.episodes.push(feedEpisode)
|
||||||
})
|
})
|
||||||
} else { // AUDIOBOOK EPISODES
|
} else { // AUDIOBOOK EPISODES
|
||||||
media.tracks.forEach((audioTrack) => {
|
media.tracks.forEach((audioTrack) => {
|
||||||
var feedEpisode = new FeedEpisode()
|
const feedEpisode = new FeedEpisode()
|
||||||
feedEpisode.setFromAudiobookTrack(libraryItem, serverAddress, slug, audioTrack, this.meta)
|
feedEpisode.setFromAudiobookTrack(libraryItem, serverAddress, slug, audioTrack, this.meta)
|
||||||
this.episodes.push(feedEpisode)
|
this.episodes.push(feedEpisode)
|
||||||
})
|
})
|
||||||
@ -144,13 +146,15 @@ class Feed {
|
|||||||
this.episodes = []
|
this.episodes = []
|
||||||
if (isPodcast) { // PODCAST EPISODES
|
if (isPodcast) { // PODCAST EPISODES
|
||||||
media.episodes.forEach((episode) => {
|
media.episodes.forEach((episode) => {
|
||||||
var feedEpisode = new FeedEpisode()
|
if (episode.updatedAt > this.entityUpdatedAt) this.entityUpdatedAt = episode.updatedAt
|
||||||
|
|
||||||
|
const feedEpisode = new FeedEpisode()
|
||||||
feedEpisode.setFromPodcastEpisode(libraryItem, this.serverAddress, this.slug, episode, this.meta)
|
feedEpisode.setFromPodcastEpisode(libraryItem, this.serverAddress, this.slug, episode, this.meta)
|
||||||
this.episodes.push(feedEpisode)
|
this.episodes.push(feedEpisode)
|
||||||
})
|
})
|
||||||
} else { // AUDIOBOOK EPISODES
|
} else { // AUDIOBOOK EPISODES
|
||||||
media.tracks.forEach((audioTrack) => {
|
media.tracks.forEach((audioTrack) => {
|
||||||
var feedEpisode = new FeedEpisode()
|
const feedEpisode = new FeedEpisode()
|
||||||
feedEpisode.setFromAudiobookTrack(libraryItem, this.serverAddress, this.slug, audioTrack, this.meta)
|
feedEpisode.setFromAudiobookTrack(libraryItem, this.serverAddress, this.slug, audioTrack, this.meta)
|
||||||
this.episodes.push(feedEpisode)
|
this.episodes.push(feedEpisode)
|
||||||
})
|
})
|
||||||
|
@ -314,18 +314,18 @@ class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createUpdateMediaProgress(libraryItem, updatePayload, episodeId = null) {
|
createUpdateMediaProgress(libraryItem, updatePayload, episodeId = null) {
|
||||||
var itemProgress = this.mediaProgress.find(li => {
|
const itemProgress = this.mediaProgress.find(li => {
|
||||||
if (episodeId && li.episodeId !== episodeId) return false
|
if (episodeId && li.episodeId !== episodeId) return false
|
||||||
return li.libraryItemId === libraryItem.id
|
return li.libraryItemId === libraryItem.id
|
||||||
})
|
})
|
||||||
if (!itemProgress) {
|
if (!itemProgress) {
|
||||||
var newItemProgress = new MediaProgress()
|
const newItemProgress = new MediaProgress()
|
||||||
|
|
||||||
newItemProgress.setData(libraryItem.id, updatePayload, episodeId)
|
newItemProgress.setData(libraryItem.id, updatePayload, episodeId)
|
||||||
this.mediaProgress.push(newItemProgress)
|
this.mediaProgress.push(newItemProgress)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
var wasUpdated = itemProgress.update(updatePayload)
|
const wasUpdated = itemProgress.update(updatePayload)
|
||||||
|
|
||||||
if (updatePayload.lastUpdate) itemProgress.lastUpdate = updatePayload.lastUpdate // For local to keep update times in sync
|
if (updatePayload.lastUpdate) itemProgress.lastUpdate = updatePayload.lastUpdate // For local to keep update times in sync
|
||||||
return wasUpdated
|
return wasUpdated
|
||||||
|
@ -339,6 +339,14 @@ module.exports = {
|
|||||||
entities: [],
|
entities: [],
|
||||||
category: 'continueSeries'
|
category: 'continueSeries'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'episodes-recently-added',
|
||||||
|
label: 'Newest Episodes',
|
||||||
|
labelStringKey: 'LabelNewestEpisodes',
|
||||||
|
type: 'episode',
|
||||||
|
entities: [],
|
||||||
|
category: 'newestEpisodes'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'recently-added',
|
id: 'recently-added',
|
||||||
label: 'Recently Added',
|
label: 'Recently Added',
|
||||||
@ -347,14 +355,6 @@ module.exports = {
|
|||||||
entities: [],
|
entities: [],
|
||||||
category: 'newestItems'
|
category: 'newestItems'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'listen-again',
|
|
||||||
label: 'Listen Again',
|
|
||||||
labelStringKey: 'LabelListenAgain',
|
|
||||||
type: isPodcastLibrary ? 'episode' : mediaType,
|
|
||||||
entities: [],
|
|
||||||
category: 'recentlyFinished'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'recent-series',
|
id: 'recent-series',
|
||||||
label: 'Recent Series',
|
label: 'Recent Series',
|
||||||
@ -363,6 +363,22 @@ module.exports = {
|
|||||||
entities: [],
|
entities: [],
|
||||||
category: 'newestSeries'
|
category: 'newestSeries'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'recommended',
|
||||||
|
label: 'Recommended',
|
||||||
|
labelStringKey: 'LabelRecommended',
|
||||||
|
type: mediaType,
|
||||||
|
entities: [],
|
||||||
|
category: 'recommended'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'listen-again',
|
||||||
|
label: 'Listen Again',
|
||||||
|
labelStringKey: 'LabelListenAgain',
|
||||||
|
type: isPodcastLibrary ? 'episode' : mediaType,
|
||||||
|
entities: [],
|
||||||
|
category: 'recentlyFinished'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'newest-authors',
|
id: 'newest-authors',
|
||||||
label: 'Newest Authors',
|
label: 'Newest Authors',
|
||||||
@ -370,22 +386,13 @@ module.exports = {
|
|||||||
type: 'authors',
|
type: 'authors',
|
||||||
entities: [],
|
entities: [],
|
||||||
category: 'newestAuthors'
|
category: 'newestAuthors'
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'episodes-recently-added',
|
|
||||||
label: 'Newest Episodes',
|
|
||||||
labelStringKey: 'LabelNewestEpisodes',
|
|
||||||
type: 'episode',
|
|
||||||
entities: [],
|
|
||||||
category: 'newestEpisodes'
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const categories = ['recentlyListened', 'continueSeries', 'newestEpisodes', 'newestItems', 'newestSeries', 'recentlyFinished', 'newestAuthors']
|
|
||||||
const categoryMap = {}
|
const categoryMap = {}
|
||||||
categories.forEach((cat) => {
|
shelves.forEach((shelf) => {
|
||||||
categoryMap[cat] = {
|
categoryMap[shelf.category] = {
|
||||||
category: cat,
|
category: shelf.category,
|
||||||
biggest: 0,
|
biggest: 0,
|
||||||
smallest: 0,
|
smallest: 0,
|
||||||
items: []
|
items: []
|
||||||
@ -395,6 +402,12 @@ module.exports = {
|
|||||||
const seriesMap = {}
|
const seriesMap = {}
|
||||||
const authorMap = {}
|
const authorMap = {}
|
||||||
|
|
||||||
|
// For use with recommended
|
||||||
|
const topGenresListened = {}
|
||||||
|
const topAuthorsListened = {}
|
||||||
|
const topTagsListened = {}
|
||||||
|
const notStartedBooks = []
|
||||||
|
|
||||||
for (const libraryItem of libraryItems) {
|
for (const libraryItem of libraryItems) {
|
||||||
if (libraryItem.addedAt > categoryMap.newestItems.smallest) {
|
if (libraryItem.addedAt > categoryMap.newestItems.smallest) {
|
||||||
|
|
||||||
@ -494,10 +507,28 @@ module.exports = {
|
|||||||
} else if (libraryItem.isBook) {
|
} else if (libraryItem.isBook) {
|
||||||
// Book categories
|
// Book categories
|
||||||
|
|
||||||
|
const mediaProgress = allItemProgress.length ? allItemProgress[0] : null
|
||||||
|
|
||||||
|
// Used for recommended. Tally up most listened to authors/genres/tags
|
||||||
|
if (mediaProgress && (mediaProgress.inProgress || mediaProgress.isFinished)) {
|
||||||
|
libraryItem.media.metadata.authors.forEach((author) => {
|
||||||
|
topAuthorsListened[author.id] = (topAuthorsListened[author.id] || 0) + 1
|
||||||
|
})
|
||||||
|
libraryItem.media.metadata.genres.forEach((genre) => {
|
||||||
|
topGenresListened[genre] = (topGenresListened[genre] || 0) + 1
|
||||||
|
})
|
||||||
|
libraryItem.media.tags.forEach((tag) => {
|
||||||
|
topTagsListened[tag] = (topTagsListened[tag] || 0) + 1
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Insert in random position to add randomization to equal weighted items
|
||||||
|
notStartedBooks.splice(Math.floor(Math.random() * (notStartedBooks.length + 1)), 0, libraryItem)
|
||||||
|
}
|
||||||
|
|
||||||
// Newest series
|
// Newest series
|
||||||
if (libraryItem.media.metadata.series.length) {
|
if (libraryItem.media.metadata.series.length) {
|
||||||
for (const librarySeries of libraryItem.media.metadata.series) {
|
for (const librarySeries of libraryItem.media.metadata.series) {
|
||||||
const mediaProgress = allItemProgress.length ? allItemProgress[0] : null
|
|
||||||
const bookInProgress = mediaProgress && (mediaProgress.inProgress || mediaProgress.isFinished)
|
const bookInProgress = mediaProgress && (mediaProgress.inProgress || mediaProgress.isFinished)
|
||||||
const bookActive = mediaProgress && mediaProgress.inProgress && !mediaProgress.isFinished
|
const bookActive = mediaProgress && mediaProgress.inProgress && !mediaProgress.isFinished
|
||||||
const libraryItemJson = libraryItem.toJSONMinified()
|
const libraryItemJson = libraryItem.toJSONMinified()
|
||||||
@ -602,7 +633,6 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Book listening and finished
|
// Book listening and finished
|
||||||
var mediaProgress = allItemProgress.length ? allItemProgress[0] : null
|
|
||||||
if (mediaProgress) {
|
if (mediaProgress) {
|
||||||
// Handle most recently finished
|
// Handle most recently finished
|
||||||
if (mediaProgress.isFinished) {
|
if (mediaProgress.isFinished) {
|
||||||
@ -612,7 +642,7 @@ module.exports = {
|
|||||||
finishedAt: mediaProgress.finishedAt
|
finishedAt: mediaProgress.finishedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
var indexToPut = categoryMap.recentlyFinished.items.findIndex(i => mediaProgress.finishedAt > i.finishedAt)
|
const indexToPut = categoryMap.recentlyFinished.items.findIndex(i => mediaProgress.finishedAt > i.finishedAt)
|
||||||
if (indexToPut >= 0) {
|
if (indexToPut >= 0) {
|
||||||
categoryMap.recentlyFinished.items.splice(indexToPut, 0, libraryItemObj)
|
categoryMap.recentlyFinished.items.splice(indexToPut, 0, libraryItemObj)
|
||||||
} else {
|
} else {
|
||||||
@ -632,7 +662,7 @@ module.exports = {
|
|||||||
progressLastUpdate: mediaProgress.lastUpdate
|
progressLastUpdate: mediaProgress.lastUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
var indexToPut = categoryMap.recentlyListened.items.findIndex(i => mediaProgress.lastUpdate > i.progressLastUpdate)
|
const indexToPut = categoryMap.recentlyListened.items.findIndex(i => mediaProgress.lastUpdate > i.progressLastUpdate)
|
||||||
if (indexToPut >= 0) {
|
if (indexToPut >= 0) {
|
||||||
categoryMap.recentlyListened.items.splice(indexToPut, 0, libraryItemObj)
|
categoryMap.recentlyListened.items.splice(indexToPut, 0, libraryItemObj)
|
||||||
} else { // Should only happen when array is < max
|
} else { // Should only happen when array is < max
|
||||||
@ -652,9 +682,9 @@ module.exports = {
|
|||||||
|
|
||||||
// For Continue Series - Find next book in series for series that are in progress
|
// For Continue Series - Find next book in series for series that are in progress
|
||||||
for (const seriesId in seriesMap) {
|
for (const seriesId in seriesMap) {
|
||||||
if (seriesMap[seriesId].inProgress && !seriesMap[seriesId].hideFromContinueListening) {
|
seriesMap[seriesId].books = naturalSort(seriesMap[seriesId].books).asc(li => li.seriesSequence)
|
||||||
seriesMap[seriesId].books = naturalSort(seriesMap[seriesId].books).asc(li => li.seriesSequence)
|
|
||||||
|
|
||||||
|
if (seriesMap[seriesId].inProgress && !seriesMap[seriesId].hideFromContinueListening) {
|
||||||
// take the first book unread with the smallest series sequence
|
// take the first book unread with the smallest series sequence
|
||||||
// unless the user is already listening to a book from this series
|
// unless the user is already listening to a book from this series
|
||||||
const hasActiveBook = seriesMap[seriesId].hasActiveBook
|
const hasActiveBook = seriesMap[seriesId].hasActiveBook
|
||||||
@ -683,6 +713,76 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For recommended
|
||||||
|
if (!isPodcastLibrary && notStartedBooks.length) {
|
||||||
|
const genresCount = Object.values(topGenresListened).reduce((a, b) => a + b, 0)
|
||||||
|
const authorsCount = Object.values(topAuthorsListened).reduce((a, b) => a + b, 0)
|
||||||
|
const tagsCount = Object.values(topTagsListened).reduce((a, b) => a + b, 0)
|
||||||
|
|
||||||
|
for (const libraryItem of notStartedBooks) {
|
||||||
|
// dont include books in an unfinished series and books that are not first in an unstarted series
|
||||||
|
let shouldContinue = !libraryItem.media.metadata.series.length
|
||||||
|
libraryItem.media.metadata.series.forEach((se) => {
|
||||||
|
if (seriesMap[se.id]) {
|
||||||
|
if (seriesMap[se.id].inProgress) {
|
||||||
|
shouldContinue = false
|
||||||
|
return
|
||||||
|
} else if (seriesMap[se.id].books[0].id === libraryItem.id) {
|
||||||
|
shouldContinue = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (!shouldContinue) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let totalWeight = 0
|
||||||
|
|
||||||
|
if (authorsCount > 0) {
|
||||||
|
libraryItem.media.metadata.authors.forEach((author) => {
|
||||||
|
if (topAuthorsListened[author.id]) {
|
||||||
|
totalWeight += topAuthorsListened[author.id] / authorsCount
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (genresCount > 0) {
|
||||||
|
libraryItem.media.metadata.genres.forEach((genre) => {
|
||||||
|
if (topGenresListened[genre]) {
|
||||||
|
totalWeight += topGenresListened[genre] / genresCount
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tagsCount > 0) {
|
||||||
|
libraryItem.media.tags.forEach((tag) => {
|
||||||
|
if (topTagsListened[tag]) {
|
||||||
|
totalWeight += topTagsListened[tag] / tagsCount
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!categoryMap.recommended.smallest || totalWeight > categoryMap.recommended.smallest) {
|
||||||
|
const libraryItemObj = {
|
||||||
|
...libraryItem.toJSONMinified(),
|
||||||
|
weight: totalWeight
|
||||||
|
}
|
||||||
|
|
||||||
|
const indexToPut = categoryMap.recommended.items.findIndex(i => totalWeight > i.weight)
|
||||||
|
if (indexToPut >= 0) {
|
||||||
|
categoryMap.recommended.items.splice(indexToPut, 0, libraryItemObj)
|
||||||
|
} else {
|
||||||
|
categoryMap.recommended.items.push(libraryItemObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (categoryMap.recommended.items.length > maxEntitiesPerShelf) {
|
||||||
|
categoryMap.recommended.items.pop()
|
||||||
|
categoryMap.recommended.smallest = categoryMap.recommended.items[categoryMap.recommended.items.length - 1].weight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Sort series books by sequence
|
// Sort series books by sequence
|
||||||
if (categoryMap.newestSeries.items.length) {
|
if (categoryMap.newestSeries.items.length) {
|
||||||
for (const seriesItem of categoryMap.newestSeries.items) {
|
for (const seriesItem of categoryMap.newestSeries.items) {
|
||||||
|
Loading…
Reference in New Issue
Block a user