From 95c0b1b688567bc770d65eb308f704a1ebeb31a8 Mon Sep 17 00:00:00 2001 From: Ross Younger Date: Sat, 13 Jan 2024 16:50:41 +1300 Subject: [PATCH 1/3] [newsfeed] getTemplateData: always use the helper function to compute the active item URL --- modules/default/newsfeed/newsfeed.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 27114d8e31..6b8eca6b9a 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -150,7 +150,7 @@ Module.register("newsfeed", { sourceTitle: item.sourceTitle, publishDate: moment(new Date(item.pubdate)).fromNow(), title: item.title, - url: this.getUrlPrefix(item) + item.url, + url: this.getActiveItemURL(), description: item.description, items: items }; From 443001264bf919d76f4bd84d5738a190b7115aef Mon Sep 17 00:00:00 2001 From: Ross Younger Date: Sat, 13 Jan 2024 16:52:41 +1300 Subject: [PATCH 2/3] [newsfeed] getTemplateData: check activeItem index earlier --- modules/default/newsfeed/newsfeed.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index 6b8eca6b9a..aa09e97b38 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -118,6 +118,9 @@ Module.register("newsfeed", { //Override template data and return whats used for the current template getTemplateData () { + if (this.activeItem >= this.newsItems.length) { + this.activeItem = 0; + } // this.config.showFullArticle is a run-time configuration, triggered by optional notifications if (this.config.showFullArticle) { return { @@ -134,9 +137,6 @@ Module.register("newsfeed", { empty: true }; } - if (this.activeItem >= this.newsItems.length) { - this.activeItem = 0; - } const item = this.newsItems[this.activeItem]; const items = this.newsItems.map(function (item) { From 3b92514bdb84f12510f29966297a36a3f8c1b148 Mon Sep 17 00:00:00 2001 From: Ross Younger Date: Sun, 7 Jan 2024 15:21:38 +1300 Subject: [PATCH 3/3] [newsfeed] Suppress unsightly animation cases when there are 0 or 1 live news items --- CHANGELOG.md | 2 ++ modules/default/newsfeed/newsfeed.js | 29 +++++++++++++++++++-- modules/default/newsfeed/newsfeedfetcher.js | 4 ++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca3df69f3d..9904dc1d31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ _This release is scheduled to be released on 2024-04-01._ ### Fixed - Skip changelog requirement when running tests for dependency updates (#3320) +- [newsfeed] Suppress unsightly animation cases when there are 0 or 1 active news items +- [newsfeed] Always compute the feed item URL using the same helper function ### Deleted diff --git a/modules/default/newsfeed/newsfeed.js b/modules/default/newsfeed/newsfeed.js index aa09e97b38..2ecd2ad645 100644 --- a/modules/default/newsfeed/newsfeed.js +++ b/modules/default/newsfeed/newsfeed.js @@ -121,24 +121,30 @@ Module.register("newsfeed", { if (this.activeItem >= this.newsItems.length) { this.activeItem = 0; } + this.activeItemCount = this.newsItems.length; // this.config.showFullArticle is a run-time configuration, triggered by optional notifications if (this.config.showFullArticle) { + this.activeItemHash = this.newsItems[this.activeItem]?.hash; return { url: this.getActiveItemURL() }; } if (this.error) { + this.activeItemHash = undefined; return { error: this.error }; } if (this.newsItems.length === 0) { + this.activeItemHash = undefined; return { empty: true }; } const item = this.newsItems[this.activeItem]; + this.activeItemHash = item.hash; + const items = this.newsItems.map(function (item) { item.publishDate = moment(new Date(item.pubdate)).fromNow(); return item; @@ -312,8 +318,27 @@ Module.register("newsfeed", { if (this.timer) clearInterval(this.timer); this.timer = setInterval(() => { - this.activeItem++; - this.updateDom(this.config.animationSpeed); + + /* + * When animations are enabled, don't update the DOM unless we are actually changing what we are displaying. + * (Animating from a headline to itself is unsightly.) + * Cases: + * + * Number of items | Number of items | Display + * at last update | right now | Behaviour + * ---------------------------------------------------- + * 0 | 0 | do not update + * 0 | >0 | update + * 1 | 0 or >1 | update + * 1 | 1 | update only if item details (hash value) changed + * >1 | any | update + * + * (N.B. We set activeItemCount and activeItemHash in getTemplateData().) + */ + if (this.newsItems.length !== this.activeItemCount || this.activeItemHash !== this.newsItems[0]?.hash) { + this.activeItem++; // this is OK if newsItems.Length==1; getTemplateData will wrap it around + this.updateDom(this.config.animationSpeed); + } // Broadcast NewsFeed if needed if (this.config.broadcastNewsFeeds) { diff --git a/modules/default/newsfeed/newsfeedfetcher.js b/modules/default/newsfeed/newsfeedfetcher.js index 47af15ce63..ea1c7712fd 100644 --- a/modules/default/newsfeed/newsfeedfetcher.js +++ b/modules/default/newsfeed/newsfeedfetcher.js @@ -5,6 +5,7 @@ * MIT Licensed. */ +const crypto = require("node:crypto"); const stream = require("node:stream"); const FeedMe = require("feedme"); const iconv = require("iconv-lite"); @@ -67,7 +68,8 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings description: description, pubdate: pubdate, url: url, - useCorsProxy: useCorsProxy + useCorsProxy: useCorsProxy, + hash: crypto.createHash("sha256").update(`${pubdate} :: ${title} :: ${url}`).digest("hex") }); } else if (logFeedWarnings) { Log.warn("Can't parse feed item:");