From 7f3468e7d507c94059f5b686537db50b05032793 Mon Sep 17 00:00:00 2001 From: Osama Sayegh Date: Thu, 14 Oct 2021 08:10:13 +0300 Subject: [PATCH] FIX: Decorate posts that are loaded after the initial render in post stream (#14600) To clarify, this problem is not about the topic posts stream, it's about posts streams like the user Activity one in the profile page (or in technical terms anything using the `{{user-stream}}` component). Post decorations are currently applied inside a `didInsertElement` hook of the `{{user-stream}}` component. However, when the user scrolls the component will load more posts but these will be missing decorations because the `didInsertElement` is only fired once at the beginning of the component lifecycle. This PR makes the component keep track of the last decorated post/DOM node, and when new posts are loaded the component fire an event for each new post and pass the post's DOM node with the event. Our plugin API (I noticed this problem when I was working on https://github.com/discourse/discourse-follow/pull/37) Co-authored-by: Robin Ward --- .../discourse/app/components/user-stream.js | 24 ++++++++++++++++++- .../discourse/app/lib/plugin-api.js | 10 ++++---- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/discourse/app/components/user-stream.js b/app/assets/javascripts/discourse/app/components/user-stream.js index 3d1c1e6b9ec..0632ab424ee 100644 --- a/app/assets/javascripts/discourse/app/components/user-stream.js +++ b/app/assets/javascripts/discourse/app/components/user-stream.js @@ -14,6 +14,7 @@ import { schedule } from "@ember/runloop"; export default Component.extend(LoadMore, { tagName: "ul", + _lastDecoratedElement: null, _initialize: on("init", function () { const filter = this.get("stream.filter"); @@ -47,6 +48,7 @@ export default Component.extend(LoadMore, { $(this.element).on("click.discourse-redirect", ".excerpt a", (e) => { return ClickTrack.trackClick(e, this.siteSettings); }); + this._updateLastDecoratedElement(); }), // This view is being removed. Shut down operations @@ -59,6 +61,18 @@ export default Component.extend(LoadMore, { $(this.element).off("click.discourse-redirect", ".excerpt a"); }), + _updateLastDecoratedElement() { + const nodes = this.element.querySelectorAll(".user-stream-item"); + if (nodes.length === 0) { + return; + } + const lastElement = nodes[nodes.length - 1]; + if (lastElement === this._lastDecoratedElement) { + return; + } + this._lastDecoratedElement = lastElement; + }, + actions: { removeBookmark(userAction) { const stream = this.stream; @@ -123,7 +137,15 @@ export default Component.extend(LoadMore, { this.set("loading", true); const stream = this.stream; - stream.findItems().then(() => this.set("loading", false)); + stream.findItems().then(() => { + this.set("loading", false); + let element = this._lastDecoratedElement?.nextElementSibling; + while (element) { + this.trigger("user-stream:new-item-inserted", element); + element = element.nextElementSibling; + } + this._updateLastDecoratedElement(); + }); }, }, }); diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.js b/app/assets/javascripts/discourse/app/lib/plugin-api.js index 7094c0a7b29..b11a07e811c 100644 --- a/app/assets/javascripts/discourse/app/lib/plugin-api.js +++ b/app/assets/javascripts/discourse/app/lib/plugin-api.js @@ -311,12 +311,10 @@ class PluginApi { if (!opts.onlyStream) { decorate(ComposerEditor, "previewRefreshed", callback, opts.id); decorate(DiscourseBanner, "didInsertElement", callback, opts.id); - decorate( - this.container.factoryFor("component:user-stream").class, - "didInsertElement", - callback, - opts.id - ); + ["didInsertElement", "user-stream:new-item-inserted"].forEach((event) => { + const klass = this.container.factoryFor("component:user-stream").class; + decorate(klass, event, callback, opts.id); + }); } }