mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-31 02:17:01 -04:00 
			
		
		
		
	Add:RSS feed icon over library item covers when feed is open #893
This commit is contained in:
		
							parent
							
								
									2cb4f972d7
								
							
						
					
					
						commit
						24a142e718
					
				| @ -78,6 +78,10 @@ | |||||||
|       </div> |       </div> | ||||||
|     </ui-tooltip> |     </ui-tooltip> | ||||||
| 
 | 
 | ||||||
|  |     <div v-if="rssFeed && !isSelectionMode && !isHovering" class="absolute text-success top-0 left-0 z-10" :style="{ padding: 0.375 * sizeMultiplier + 'rem' }"> | ||||||
|  |       <span class="material-icons" :style="{ fontSize: sizeMultiplier * 1.5 + 'rem' }">rss_feed</span> | ||||||
|  |     </div> | ||||||
|  | 
 | ||||||
|     <!-- Series sequence --> |     <!-- Series sequence --> | ||||||
|     <div v-if="seriesSequence && !isHovering && !isSelectionMode" class="absolute rounded-lg bg-black bg-opacity-90 box-shadow-md z-10" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', padding: `${0.1 * sizeMultiplier}rem ${0.25 * sizeMultiplier}rem` }"> |     <div v-if="seriesSequence && !isHovering && !isSelectionMode" class="absolute rounded-lg bg-black bg-opacity-90 box-shadow-md z-10" :style="{ top: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', padding: `${0.1 * sizeMultiplier}rem ${0.25 * sizeMultiplier}rem` }"> | ||||||
|       <p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">#{{ seriesSequence }}</p> |       <p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">#{{ seriesSequence }}</p> | ||||||
| @ -444,6 +448,10 @@ export default { | |||||||
|       if (!this.isAlternativeBookshelfView && !this.isAuthorBookshelfView) return 0 |       if (!this.isAlternativeBookshelfView && !this.isAuthorBookshelfView) return 0 | ||||||
|       else if (!this.displaySortLine) return 3 * this.sizeMultiplier |       else if (!this.displaySortLine) return 3 * this.sizeMultiplier | ||||||
|       return 4.25 * this.sizeMultiplier |       return 4.25 * this.sizeMultiplier | ||||||
|  |     }, | ||||||
|  |     rssFeed() { | ||||||
|  |       if (this.booksInSeries) return null | ||||||
|  |       return this.store.getters['feeds/getFeedForItem'](this.libraryItemId) | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|  | |||||||
| @ -361,11 +361,11 @@ export default { | |||||||
|       download.status = this.$constants.DownloadStatus.EXPIRED |       download.status = this.$constants.DownloadStatus.EXPIRED | ||||||
|       this.$store.commit('downloads/addUpdateDownload', download) |       this.$store.commit('downloads/addUpdateDownload', download) | ||||||
|     }, |     }, | ||||||
|     showErrorToast(message) { |     rssFeedOpen(data) { | ||||||
|       this.$toast.error(message) |       this.$store.commit('feeds/addFeed', data) | ||||||
|     }, |     }, | ||||||
|     showSuccessToast(message) { |     rssFeedClosed(data) { | ||||||
|       this.$toast.success(message) |       this.$store.commit('feeds/removeFeed', data) | ||||||
|     }, |     }, | ||||||
|     backupApplied() { |     backupApplied() { | ||||||
|       // Force refresh |       // Force refresh | ||||||
| @ -437,9 +437,9 @@ export default { | |||||||
|       this.socket.on('abmerge_killed', this.abmergeKilled) |       this.socket.on('abmerge_killed', this.abmergeKilled) | ||||||
|       this.socket.on('abmerge_expired', this.abmergeExpired) |       this.socket.on('abmerge_expired', this.abmergeExpired) | ||||||
| 
 | 
 | ||||||
|       // Toast Listeners |       // Feed Listeners | ||||||
|       this.socket.on('show_error_toast', this.showErrorToast) |       this.socket.on('rss_feed_open', this.rssFeedOpen) | ||||||
|       this.socket.on('show_success_toast', this.showSuccessToast) |       this.socket.on('rss_feed_closed', this.rssFeedClosed) | ||||||
| 
 | 
 | ||||||
|       this.socket.on('backup_applied', this.backupApplied) |       this.socket.on('backup_applied', this.backupApplied) | ||||||
|     }, |     }, | ||||||
|  | |||||||
| @ -124,9 +124,10 @@ export default { | |||||||
| 
 | 
 | ||||||
|       location.reload() |       location.reload() | ||||||
|     }, |     }, | ||||||
|     setUser({ user, userDefaultLibraryId, serverSettings, Source }) { |     setUser({ user, userDefaultLibraryId, serverSettings, Source, feeds }) { | ||||||
|       this.$store.commit('setServerSettings', serverSettings) |       this.$store.commit('setServerSettings', serverSettings) | ||||||
|       this.$store.commit('setSource', Source) |       this.$store.commit('setSource', Source) | ||||||
|  |       this.$store.commit('feeds/setFeeds', feeds) | ||||||
| 
 | 
 | ||||||
|       if (serverSettings.chromecastEnabled) { |       if (serverSettings.chromecastEnabled) { | ||||||
|         console.log('Chromecast enabled import script') |         console.log('Chromecast enabled import script') | ||||||
|  | |||||||
							
								
								
									
										28
									
								
								client/store/feeds.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								client/store/feeds.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | 
 | ||||||
|  | export const state = () => ({ | ||||||
|  |   feeds: [] | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | export const getters = { | ||||||
|  |   getFeedForItem: state => id => { | ||||||
|  |     return state.feeds.find(feed => feed.id === id) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const actions = { | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const mutations = { | ||||||
|  |   addFeed(state, feed) { | ||||||
|  |     var index = state.feeds.findIndex(f => f.id === feed.id) | ||||||
|  |     if (index >= 0) state.feeds.splice(index, 1, feed) | ||||||
|  |     else state.feeds.push(feed) | ||||||
|  |   }, | ||||||
|  |   removeFeed(state, feed) { | ||||||
|  |     state.feeds = state.feeds.filter(f => f.id !== feed.id) | ||||||
|  |   }, | ||||||
|  |   setFeeds(state, feeds) { | ||||||
|  |     state.feeds = feeds || [] | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -114,16 +114,17 @@ class Auth { | |||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   getUserLoginResponsePayload(user) { |   getUserLoginResponsePayload(user, feeds) { | ||||||
|     return { |     return { | ||||||
|       user: user.toJSONForBrowser(), |       user: user.toJSONForBrowser(), | ||||||
|       userDefaultLibraryId: user.getDefaultLibraryId(this.db.libraries), |       userDefaultLibraryId: user.getDefaultLibraryId(this.db.libraries), | ||||||
|       serverSettings: this.db.serverSettings.toJSONForBrowser(), |       serverSettings: this.db.serverSettings.toJSONForBrowser(), | ||||||
|  |       feeds, | ||||||
|       Source: global.Source |       Source: global.Source | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   async login(req, res) { |   async login(req, res, feeds) { | ||||||
|     var username = (req.body.username || '').toLowerCase() |     var username = (req.body.username || '').toLowerCase() | ||||||
|     var password = req.body.password || '' |     var password = req.body.password || '' | ||||||
| 
 | 
 | ||||||
| @ -142,14 +143,14 @@ class Auth { | |||||||
|       if (password) { |       if (password) { | ||||||
|         return res.status(401).send('Invalid root password (hint: there is none)') |         return res.status(401).send('Invalid root password (hint: there is none)') | ||||||
|       } else { |       } else { | ||||||
|         return res.json(this.getUserLoginResponsePayload(user)) |         return res.json(this.getUserLoginResponsePayload(user, feeds)) | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Check password match
 |     // Check password match
 | ||||||
|     var compare = await bcrypt.compare(password, user.pash) |     var compare = await bcrypt.compare(password, user.pash) | ||||||
|     if (compare) { |     if (compare) { | ||||||
|       res.json(this.getUserLoginResponsePayload(user)) |       res.json(this.getUserLoginResponsePayload(user, feeds)) | ||||||
|     } else { |     } else { | ||||||
|       Logger.debug(`[Auth] Failed login attempt ${req.rateLimit.current} of ${req.rateLimit.limit}`) |       Logger.debug(`[Auth] Failed login attempt ${req.rateLimit.current} of ${req.rateLimit.limit}`) | ||||||
|       if (req.rateLimit.remaining <= 2) { |       if (req.rateLimit.remaining <= 2) { | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ const Author = require('./objects/entities/Author') | |||||||
| const Series = require('./objects/entities/Series') | const Series = require('./objects/entities/Series') | ||||||
| const ServerSettings = require('./objects/settings/ServerSettings') | const ServerSettings = require('./objects/settings/ServerSettings') | ||||||
| const PlaybackSession = require('./objects/PlaybackSession') | const PlaybackSession = require('./objects/PlaybackSession') | ||||||
|  | const Feed = require('./objects/Feed') | ||||||
| 
 | 
 | ||||||
| class Db { | class Db { | ||||||
|   constructor() { |   constructor() { | ||||||
|  | |||||||
| @ -230,7 +230,7 @@ class Server { | |||||||
|     ] |     ] | ||||||
|     dyanimicRoutes.forEach((route) => app.get(route, (req, res) => res.sendFile(Path.join(distPath, 'index.html')))) |     dyanimicRoutes.forEach((route) => app.get(route, (req, res) => res.sendFile(Path.join(distPath, 'index.html')))) | ||||||
| 
 | 
 | ||||||
|     app.post('/login', this.getLoginRateLimiter(), (req, res) => this.auth.login(req, res)) |     app.post('/login', this.getLoginRateLimiter(), (req, res) => this.auth.login(req, res, this.rssFeedManager.feedsArray)) | ||||||
|     app.post('/logout', this.authMiddleware.bind(this), this.logout.bind(this)) |     app.post('/logout', this.authMiddleware.bind(this), this.logout.bind(this)) | ||||||
|     app.post('/init', (req, res) => { |     app.post('/init', (req, res) => { | ||||||
|       if (this.db.hasRootUser) { |       if (this.db.hasRootUser) { | ||||||
|  | |||||||
| @ -239,12 +239,7 @@ class MiscController { | |||||||
|       Logger.error('Invalid user in authorize') |       Logger.error('Invalid user in authorize') | ||||||
|       return res.sendStatus(401) |       return res.sendStatus(401) | ||||||
|     } |     } | ||||||
|     const userResponse = { |     const userResponse = this.auth.getUserLoginResponsePayload(req.user, this.rssFeedManager.feedsArray) | ||||||
|       user: req.user, |  | ||||||
|       userDefaultLibraryId: req.user.getDefaultLibraryId(this.db.libraries), |  | ||||||
|       serverSettings: this.db.serverSettings.toJSONForBrowser(), |  | ||||||
|       Source: global.Source |  | ||||||
|     } |  | ||||||
|     res.json(userResponse) |     res.json(userResponse) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -11,6 +11,10 @@ class RssFeedManager { | |||||||
|     this.feeds = {} |     this.feeds = {} | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   get feedsArray() { | ||||||
|  |     return Object.values(this.feeds) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   async init() { |   async init() { | ||||||
|     var feedObjects = await this.db.getAllEntities('feed') |     var feedObjects = await this.db.getAllEntities('feed') | ||||||
|     if (feedObjects && feedObjects.length) { |     if (feedObjects && feedObjects.length) { | ||||||
| @ -91,7 +95,7 @@ class RssFeedManager { | |||||||
| 
 | 
 | ||||||
|     Logger.debug(`[RssFeedManager] Opened RSS feed ${feed.feedUrl}`) |     Logger.debug(`[RssFeedManager] Opened RSS feed ${feed.feedUrl}`) | ||||||
|     await this.db.insertEntity('feed', feed) |     await this.db.insertEntity('feed', feed) | ||||||
|     this.emitter('rss_feed_open', { entityType: feed.entityType, entityId: feed.entityId, feedUrl: feed.feedUrl }) |     this.emitter('rss_feed_open', { id: feed.id, entityType: feed.entityType, entityId: feed.entityId, feedUrl: feed.feedUrl }) | ||||||
|     return feed |     return feed | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -105,7 +109,7 @@ class RssFeedManager { | |||||||
|     if (!this.feeds[id]) return |     if (!this.feeds[id]) return | ||||||
|     var feed = this.feeds[id] |     var feed = this.feeds[id] | ||||||
|     await this.db.removeEntity('feed', id) |     await this.db.removeEntity('feed', id) | ||||||
|     this.emitter('rss_feed_closed', { entityType: feed.entityType, entityId: feed.entityId, feedUrl: feed.feedUrl }) |     this.emitter('rss_feed_closed', { id: feed.id, entityType: feed.entityType, entityId: feed.entityId, feedUrl: feed.feedUrl }) | ||||||
|     delete this.feeds[id] |     delete this.feeds[id] | ||||||
|     Logger.info(`[RssFeedManager] Closed RSS feed "${feed.feedUrl}"`) |     Logger.info(`[RssFeedManager] Closed RSS feed "${feed.feedUrl}"`) | ||||||
|   } |   } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user