From 24a142e718e01a11769c222b64e5f02e28a31e75 Mon Sep 17 00:00:00 2001 From: advplyr Date: Fri, 5 Aug 2022 19:23:18 -0500 Subject: [PATCH] Add:RSS feed icon over library item covers when feed is open #893 --- client/components/cards/LazyBookCard.vue | 8 +++++++ client/layouts/default.vue | 14 ++++++------ client/pages/login.vue | 3 ++- client/store/feeds.js | 28 ++++++++++++++++++++++++ server/Auth.js | 9 ++++---- server/Db.js | 1 + server/Server.js | 2 +- server/controllers/MiscController.js | 7 +----- server/managers/RssFeedManager.js | 8 +++++-- 9 files changed, 59 insertions(+), 21 deletions(-) create mode 100644 client/store/feeds.js diff --git a/client/components/cards/LazyBookCard.vue b/client/components/cards/LazyBookCard.vue index 9d6028b4..8ae16dae 100644 --- a/client/components/cards/LazyBookCard.vue +++ b/client/components/cards/LazyBookCard.vue @@ -78,6 +78,10 @@ +
+ rss_feed +
+

#{{ seriesSequence }}

@@ -444,6 +448,10 @@ export default { if (!this.isAlternativeBookshelfView && !this.isAuthorBookshelfView) return 0 else if (!this.displaySortLine) return 3 * this.sizeMultiplier return 4.25 * this.sizeMultiplier + }, + rssFeed() { + if (this.booksInSeries) return null + return this.store.getters['feeds/getFeedForItem'](this.libraryItemId) } }, methods: { diff --git a/client/layouts/default.vue b/client/layouts/default.vue index 9e5ab945..903e1dac 100644 --- a/client/layouts/default.vue +++ b/client/layouts/default.vue @@ -361,11 +361,11 @@ export default { download.status = this.$constants.DownloadStatus.EXPIRED this.$store.commit('downloads/addUpdateDownload', download) }, - showErrorToast(message) { - this.$toast.error(message) + rssFeedOpen(data) { + this.$store.commit('feeds/addFeed', data) }, - showSuccessToast(message) { - this.$toast.success(message) + rssFeedClosed(data) { + this.$store.commit('feeds/removeFeed', data) }, backupApplied() { // Force refresh @@ -437,9 +437,9 @@ export default { this.socket.on('abmerge_killed', this.abmergeKilled) this.socket.on('abmerge_expired', this.abmergeExpired) - // Toast Listeners - this.socket.on('show_error_toast', this.showErrorToast) - this.socket.on('show_success_toast', this.showSuccessToast) + // Feed Listeners + this.socket.on('rss_feed_open', this.rssFeedOpen) + this.socket.on('rss_feed_closed', this.rssFeedClosed) this.socket.on('backup_applied', this.backupApplied) }, diff --git a/client/pages/login.vue b/client/pages/login.vue index cf604a57..50a6fd56 100644 --- a/client/pages/login.vue +++ b/client/pages/login.vue @@ -124,9 +124,10 @@ export default { location.reload() }, - setUser({ user, userDefaultLibraryId, serverSettings, Source }) { + setUser({ user, userDefaultLibraryId, serverSettings, Source, feeds }) { this.$store.commit('setServerSettings', serverSettings) this.$store.commit('setSource', Source) + this.$store.commit('feeds/setFeeds', feeds) if (serverSettings.chromecastEnabled) { console.log('Chromecast enabled import script') diff --git a/client/store/feeds.js b/client/store/feeds.js new file mode 100644 index 00000000..281f5dd4 --- /dev/null +++ b/client/store/feeds.js @@ -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 || [] + } +} \ No newline at end of file diff --git a/server/Auth.js b/server/Auth.js index 68bc0933..a8fd043e 100644 --- a/server/Auth.js +++ b/server/Auth.js @@ -114,16 +114,17 @@ class Auth { }) } - getUserLoginResponsePayload(user) { + getUserLoginResponsePayload(user, feeds) { return { user: user.toJSONForBrowser(), userDefaultLibraryId: user.getDefaultLibraryId(this.db.libraries), serverSettings: this.db.serverSettings.toJSONForBrowser(), + feeds, Source: global.Source } } - async login(req, res) { + async login(req, res, feeds) { var username = (req.body.username || '').toLowerCase() var password = req.body.password || '' @@ -142,14 +143,14 @@ class Auth { if (password) { return res.status(401).send('Invalid root password (hint: there is none)') } else { - return res.json(this.getUserLoginResponsePayload(user)) + return res.json(this.getUserLoginResponsePayload(user, feeds)) } } // Check password match var compare = await bcrypt.compare(password, user.pash) if (compare) { - res.json(this.getUserLoginResponsePayload(user)) + res.json(this.getUserLoginResponsePayload(user, feeds)) } else { Logger.debug(`[Auth] Failed login attempt ${req.rateLimit.current} of ${req.rateLimit.limit}`) if (req.rateLimit.remaining <= 2) { diff --git a/server/Db.js b/server/Db.js index 5893eef5..c9911089 100644 --- a/server/Db.js +++ b/server/Db.js @@ -10,6 +10,7 @@ const Author = require('./objects/entities/Author') const Series = require('./objects/entities/Series') const ServerSettings = require('./objects/settings/ServerSettings') const PlaybackSession = require('./objects/PlaybackSession') +const Feed = require('./objects/Feed') class Db { constructor() { diff --git a/server/Server.js b/server/Server.js index bfa543a9..ac06ea26 100644 --- a/server/Server.js +++ b/server/Server.js @@ -230,7 +230,7 @@ class Server { ] 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('/init', (req, res) => { if (this.db.hasRootUser) { diff --git a/server/controllers/MiscController.js b/server/controllers/MiscController.js index e179e14a..f0b71d51 100644 --- a/server/controllers/MiscController.js +++ b/server/controllers/MiscController.js @@ -239,12 +239,7 @@ class MiscController { Logger.error('Invalid user in authorize') return res.sendStatus(401) } - const userResponse = { - user: req.user, - userDefaultLibraryId: req.user.getDefaultLibraryId(this.db.libraries), - serverSettings: this.db.serverSettings.toJSONForBrowser(), - Source: global.Source - } + const userResponse = this.auth.getUserLoginResponsePayload(req.user, this.rssFeedManager.feedsArray) res.json(userResponse) } diff --git a/server/managers/RssFeedManager.js b/server/managers/RssFeedManager.js index e7ef9708..a1160cda 100644 --- a/server/managers/RssFeedManager.js +++ b/server/managers/RssFeedManager.js @@ -11,6 +11,10 @@ class RssFeedManager { this.feeds = {} } + get feedsArray() { + return Object.values(this.feeds) + } + async init() { var feedObjects = await this.db.getAllEntities('feed') if (feedObjects && feedObjects.length) { @@ -91,7 +95,7 @@ class RssFeedManager { Logger.debug(`[RssFeedManager] Opened RSS feed ${feed.feedUrl}`) 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 } @@ -105,7 +109,7 @@ class RssFeedManager { if (!this.feeds[id]) return var feed = this.feeds[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] Logger.info(`[RssFeedManager] Closed RSS feed "${feed.feedUrl}"`) }