DEV: Don't create AppEvents instance in Eyeline (#14928)

DEV: Don’t create AppEvents instance in Eyeline (#14928)

Use Evented from @ember/object/evented instead.

diff --git a/app/assets/javascripts/discourse/app/lib/eyeline.js b/app/assets/javascripts/discourse/app/lib/eyeline.js
index f2ca4a8..76757e2 100644
--- a/app/assets/javascripts/discourse/app/lib/eyeline.js
+++ b/app/assets/javascripts/discourse/app/lib/eyeline.js
@@ -1,4 +1,5 @@
-import AppEvents from "discourse/services/app-events";
+import EmberObject from "@ember/object";
+import Evented from "@ember/object/evented";
 import { isTesting } from "discourse-common/config/environment";
 
 let _skipUpdate;
@@ -16,84 +17,72 @@ export function configureEyeline(opts) {
 
 configureEyeline();
 
-//  Track visible elements on the screen.
-const Eyeline = function Eyeline(selector) {
-  this.selector = selector;
-  this.appEvents = AppEvents.create();
-};
+// Track visible elements on the screen.
+export default EmberObject.extend(Evented, {
+  init() {
+    this._super(...arguments);
+  },
 
-Eyeline.prototype.on = function (name, cb) {
-  this.appEvents.on(name, cb);
-};
-
-Eyeline.prototype.off = function (name, cb) {
-  this.appEvents.off(name, cb);
-};
-
-Eyeline.prototype.update = function () {
-  if (_skipUpdate) {
-    return;
-  }
-
-  const docViewTop = _rootElement
-    ? $(_rootElement).scrollTop()
-    : $(window).scrollTop();
-  const windowHeight = _rootElement
-    ? $(_rootElement).height()
-    : $(window).height();
-  const docViewBottom = docViewTop + windowHeight;
-  const $elements = $(this.selector);
-  const bottomOffset = _rootElement
-    ? $elements.last().position()
-    : $elements.last().offset();
-
-  let atBottom = false;
-  if (bottomOffset) {
-    atBottom =
-      bottomOffset.top <= docViewBottom && bottomOffset.top >= docViewTop;
-  }
-
-  let { appEvents } = this;
-  return $elements.each((i, elem) => {
-    const $elem = $(elem),
-      elemTop = _rootElement ? $elem.position().top : $elem.offset().top,
-      elemBottom = elemTop + $elem.height();
-
-    let markSeen = false;
-
-    // Make sure the element is visible
-    if (!$elem.is(":visible")) {
-      return true;
-    }
-
-    // It's seen if...
-    // ...the element is vertically within the top and bottom
-    if (elemTop <= docViewBottom && elemTop >= docViewTop) {
-      markSeen = true;
-    }
-
-    // ...the element top is above the top and the bottom is below the bottom (large elements)
-    if (elemTop <= docViewTop && elemBottom >= docViewBottom) {
-      markSeen = true;
-    }
-
-    // ...we're at the bottom and the bottom of the element is visible (large bottom elements)
-    if (atBottom && elemBottom >= docViewTop) {
-      markSeen = true;
-    }
-
-    if (!markSeen) {
-      return true;
-    }
-
-    // If you hit the bottom we mark all the elements as seen. Otherwise, just the first one
-    if (!atBottom) {
-      return false;
-    }
-    if (i === $elements.length - 1) {
-      return appEvents.trigger("sawBottom", { detail: $elem });
+  update() {
+    if (_skipUpdate) {
+      return;
     }
-  });
-};
 
-export default Eyeline;
+    const docViewTop = _rootElement
+      ? $(_rootElement).scrollTop()
+      : $(window).scrollTop();
+    const windowHeight = _rootElement
+      ? $(_rootElement).height()
+      : $(window).height();
+    const docViewBottom = docViewTop + windowHeight;
+    const $elements = $(this.selector);
+    const bottomOffset = _rootElement
+      ? $elements.last().position()
+      : $elements.last().offset();
+    const atBottom =
+      bottomOffset &&
+      bottomOffset.top <= docViewBottom &&
+      bottomOffset.top >= docViewTop;
+
+    return $elements.each((i, elem) => {
+      const $elem = $(elem);
+      const elemTop = _rootElement ? $elem.position().top : $elem.offset().top;
+      const elemBottom = elemTop + $elem.height();
+      let markSeen = false;
+
+      // Make sure the element is visible
+      if (!$elem.is(":visible")) {
+        return true;
+      }
+
+      // It's seen if...
+      // ...the element is vertically within the top and bottom
+      if (elemTop <= docViewBottom && elemTop >= docViewTop) {
+        markSeen = true;
+      }
+
+      // ...the element top is above the top and the bottom is below the bottom (large elements)
+      if (elemTop <= docViewTop && elemBottom >= docViewBottom) {
+        markSeen = true;
+      }
+
+      // ...we're at the bottom and the bottom of the element is visible (large bottom elements)
+      if (atBottom && elemBottom >= docViewTop) {
+        markSeen = true;
+      }
+
+      if (!markSeen) {
+        return true;
+      }
+
+      // If you hit the bottom we mark all the elements as seen. Otherwise, just the first one
+      if (!atBottom) {
+        return false;
+      }
+
+      if (i === $elements.length - 1) {
+        return this.trigger("sawBottom", { detail: $elem });
+      }
+    });
+  },
+});
diff --git a/app/assets/javascripts/discourse/app/mixins/load-more.js b/app/assets/javascripts/discourse/app/mixins/load-more.js
index 4b2f5d4..625227b 100644
--- a/app/assets/javascripts/discourse/app/mixins/load-more.js
+++ b/app/assets/javascripts/discourse/app/mixins/load-more.js
@@ -6,8 +6,7 @@ import { on } from "discourse-common/utils/decorators";
 // Provides the ability to load more items for a view which is scrolled to the bottom.
 export default Mixin.create(Scrolling, {
   scrolled() {
-    const eyeline = this.eyeline;
-    return eyeline && eyeline.update();
+    return this.eyeline?.update();
   },
 
   loadMoreUnlessFull() {
@@ -18,10 +17,14 @@ export default Mixin.create(Scrolling, {
 
   @on("didInsertElement")
   _bindEyeline() {
-    const eyeline = new Eyeline(this.eyelineSelector + ":last");
+    const eyeline = Eyeline.create({
+      selector: `${this.eyelineSelector}:last`,
+    });
+
     this.set("eyeline", eyeline);
     eyeline.on("sawBottom", () => this.send("loadMore"));
     eyeline.update(); // update once to consider current position
+
     this.bindScrolling();
   },
 

GitHub sha: 047432735e47855bd592b98e7dc56350d2eef5e6

This commit appears in #14928 which was approved by martin. It was merged by CvX.