DEV: Allow `onStateChange` callbacks for PM topic tracking state. (#14479)

DEV: Allow onStateChange callbacks for PM topic tracking state. (#14479)

The changes here are in anticipation of a private plugin that will soon be merged into Discourse core.

diff --git a/app/assets/javascripts/discourse/app/models/private-message-topic-tracking-state.js b/app/assets/javascripts/discourse/app/models/private-message-topic-tracking-state.js
index 3080a99..2d7e369 100644
--- a/app/assets/javascripts/discourse/app/models/private-message-topic-tracking-state.js
+++ b/app/assets/javascripts/discourse/app/models/private-message-topic-tracking-state.js
@@ -25,6 +25,11 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
     this.statesModificationCounter = 0;
     this.isTracking = false;
     this.newIncoming = [];
+    this.stateChangeCallbacks = {};
+  },
+
+  onStateChange(name, callback) {
+    this.stateChangeCallbacks[name] = callback;
   },
 
   startTracking() {
@@ -34,7 +39,7 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
 
     this._establishChannels();
 
-    this._loadInitialState().finally(() => {
+    return this._loadInitialState().finally(() => {
       this.set("isTracking", true);
     });
   },
@@ -98,7 +103,7 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
     }
 
     topicIds.forEach((topicId) => this.states.delete(topicId));
-    this.incrementProperty("statesModificationCounter");
+    this._afterStateChange();
   },
 
   _userChannel() {
@@ -236,9 +241,14 @@ const PrivateMessageTopicTrackingState = EmberObject.extend({
     this.states.set(topicId, newState);
 
     if (!opts.skipIncrement) {
-      this.incrementProperty("statesModificationCounter");
+      this._afterStateChange();
     }
   },
+
+  _afterStateChange() {
+    this.incrementProperty("statesModificationCounter");
+    Object.values(this.stateChangeCallbacks).forEach((callback) => callback());
+  },
 });
 
 export default PrivateMessageTopicTrackingState;
diff --git a/app/assets/javascripts/discourse/tests/unit/models/private-message-topic-tracking-state-test.js b/app/assets/javascripts/discourse/tests/unit/models/private-message-topic-tracking-state-test.js
new file mode 100644
index 0000000..7d5091c
--- /dev/null
+++ b/app/assets/javascripts/discourse/tests/unit/models/private-message-topic-tracking-state-test.js
@@ -0,0 +1,32 @@
+import { test } from "qunit";
+import { discourseModule } from "discourse/tests/helpers/qunit-helpers";
+import MessageBus from "message-bus-client";
+import PrivateMessageTopicTrackingState from "discourse/models/private-message-topic-tracking-state";
+import User from "discourse/models/user";
+
+discourseModule(
+  "Unit | Model | private-message-topic-tracking-state",
+  function (hooks) {
+    let pmTopicTrackingState;
+
+    hooks.beforeEach(function () {
+      pmTopicTrackingState = PrivateMessageTopicTrackingState.create({
+        messageBus: MessageBus,
+        currentUser: User.create({ id: 1, username: "test" }),
+      });
+    });
+
+    test("modifying state calls onStateChange callbacks", function (assert) {
+      let callbackCalled = false;
+
+      pmTopicTrackingState.onStateChange("testing", () => {
+        callbackCalled = true;
+      });
+
+      pmTopicTrackingState.set("isTracking", true);
+      pmTopicTrackingState.removeTopics([]);
+
+      assert.ok(callbackCalled);
+    });
+  }
+);

GitHub sha: 085eb56ea4decb5b42f1cee07151cc9f28439f4e

This commit appears in #14479 which was approved by eviltrout. It was merged by tgxworld.