diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel.js
index ce8db2befc0..922901f5637 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-channel.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel.js
@@ -13,6 +13,7 @@ import {
} from "discourse/lib/user-presence";
import discourseDebounce from "discourse-common/lib/debounce";
import { bind } from "discourse-common/utils/decorators";
+import ChatChannelSubscriptionManager from "discourse/plugins/chat/discourse/lib/chat-channel-subscription-manager";
import {
FUTURE,
PAST,
@@ -29,9 +30,6 @@ import {
scrollListToMessage,
} from "discourse/plugins/chat/discourse/lib/scroll-helpers";
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
-// TODO (martin) Remove this when the handleSentMessage logic inside chatChannelPaneSubscriptionsManager
-// is moved over from this file completely.
-import { handleStagedMessage } from "discourse/plugins/chat/discourse/services/chat-pane-base-subscriptions-manager";
import { stackingContextFix } from "../lib/chat-ios-hacks";
export default class ChatChannel extends Component {
@@ -40,7 +38,6 @@ export default class ChatChannel extends Component {
@service chat;
@service chatApi;
@service chatChannelsManager;
- @service chatChannelPaneSubscriptionsManager;
@service chatComposerPresenceManager;
@service chatDraftsManager;
@service chatEmojiPickerManager;
@@ -97,7 +94,7 @@ export default class ChatChannel extends Component {
teardownListeners() {
this.#cancelHandlers();
removeOnPresenceChange(this.onPresenceChangeCallback);
- this.unsubscribeToUpdates(this.args.channel.id);
+ this.subscriptionManager.teardown();
}
@action
@@ -140,7 +137,11 @@ export default class ChatChannel extends Component {
return;
}
- this.subscribeToUpdates(this.args.channel);
+ this.subscriptionManager = new ChatChannelSubscriptionManager(
+ this,
+ this.args.channel,
+ { onNewMessage: this.onNewMessage }
+ );
if (this.args.targetMessageId) {
this.debounceHighlightOrFetchMessage(this.args.targetMessageId);
@@ -149,6 +150,14 @@ export default class ChatChannel extends Component {
}
}
+ @bind
+ onNewMessage(message) {
+ stackingContextFix(this.scrollable, () => {
+ this.messagesManager.addMessages([message]);
+ });
+ this.debouncedUpdateLastReadMessage();
+ }
+
@bind
onPresenceChangeCallback(present) {
if (present) {
@@ -464,36 +473,6 @@ export default class ChatChannel extends Component {
}
}
- @bind
- onMessage(data) {
- switch (data.type) {
- case "sent":
- this.handleSentMessage(data);
- break;
- }
- }
-
- handleSentMessage(data) {
- if (data.chat_message.user.id === this.currentUser.id && data.staged_id) {
- const stagedMessage = handleStagedMessage(
- this.args.channel,
- this.messagesManager,
- data
- );
- if (stagedMessage) {
- return;
- }
- }
-
- const message = ChatMessage.create(this.args.channel, data.chat_message);
- message.manager = this.args.channel.messagesManager;
- stackingContextFix(this.scrollable, () => {
- this.messagesManager.addMessages([message]);
- });
- this.debouncedUpdateLastReadMessage();
- this.args.channel.lastMessage = message;
- }
-
@action
async onSendMessage(message) {
await message.cook();
@@ -620,28 +599,6 @@ export default class ChatChannel extends Component {
});
}
- unsubscribeToUpdates(channelId) {
- if (!channelId) {
- return;
- }
-
- this.chatChannelPaneSubscriptionsManager.unsubscribe();
- this.messageBus.unsubscribe(`/chat/${channelId}`, this.onMessage);
- }
-
- subscribeToUpdates(channel) {
- if (!channel) {
- return;
- }
-
- this.messageBus.subscribe(
- `/chat/${channel.id}`,
- this.onMessage,
- channel.channelMessageBusLastId
- );
- this.chatChannelPaneSubscriptionsManager.subscribe(channel);
- }
-
@action
addAutoFocusEventListener() {
document.addEventListener("keydown", this._autoFocus);
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-drawer/channel.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-drawer/channel.hbs
index 7d80c277f61..ffaf3231c6f 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-drawer/channel.hbs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-drawer/channel.hbs
@@ -17,10 +17,12 @@
>
{{#if this.chat.activeChannel}}
{{#each (array this.chat.activeChannel) as |channel|}}
-
+ {{#if channel}}
+
+ {{/if}}
{{/each}}
{{/if}}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-drawer/thread.gjs b/plugins/chat/assets/javascripts/discourse/components/chat-drawer/thread.gjs
index 4da54ac636a..c5a62a93e76 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-drawer/thread.gjs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-drawer/thread.gjs
@@ -1,4 +1,5 @@
import Component from "@glimmer/component";
+import { array } from "@ember/helper";
import { action } from "@ember/object";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
import didUpdate from "@ember/render-modifiers/modifiers/did-update";
@@ -88,12 +89,14 @@ export default class ChatDrawerThread extends Component {
{{didUpdate this.fetchChannelAndThread @params.channelId}}
{{didUpdate this.fetchChannelAndThread @params.threadId}}
>
- {{#if this.chat.activeChannel.activeThread}}
-
- {{/if}}
+ {{#each (array this.chat.activeChannel.activeThread) as |thread|}}
+ {{#if thread}}
+
+ {{/if}}
+ {{/each}}
{{/if}}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-notice.js b/plugins/chat/assets/javascripts/discourse/components/chat-notice.js
index c8ef101e7bc..e5db96f91f9 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-notice.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-notice.js
@@ -8,11 +8,11 @@ const COMPONENT_DICT = {
};
export default class ChatNotices extends Component {
- @service("chat-channel-pane-subscriptions-manager") subscriptionsManager;
+ @service("chat-channel-notices-manager") noticesManager;
@action
clearNotice() {
- this.subscriptionsManager.clearNotice(this.args.notice);
+ this.noticesManager.clearNotice(this.args.notice);
}
get component() {
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-notices.js b/plugins/chat/assets/javascripts/discourse/components/chat-notices.js
index bb52a2f495f..d1c58356659 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-notices.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-notices.js
@@ -2,10 +2,10 @@ import Component from "@glimmer/component";
import { inject as service } from "@ember/service";
export default class ChatNotices extends Component {
- @service("chat-channel-pane-subscriptions-manager") subscriptionsManager;
+ @service("chat-channel-notices-manager") noticesManager;
get noticesForChannel() {
- return this.subscriptionsManager.notices.filter(
+ return this.noticesManager.notices.filter(
(notice) => notice.channelId === this.args.channel.id
);
}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-thread.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-thread.hbs
index 8446960a181..d15b08148d3 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-thread.hbs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-thread.hbs
@@ -6,7 +6,6 @@
data-id={{@thread.id}}
{{did-insert this.setUploadDropZone}}
{{did-insert this.didUpdateThread}}
- {{did-update this.didUpdateThread @thread.id}}
{{will-destroy this.teardown}}
>
{{#if @includeHeader}}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-thread.js b/plugins/chat/assets/javascripts/discourse/components/chat-thread.js
index f144d9c91fa..3f931e73c5a 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-thread.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-thread.js
@@ -9,6 +9,7 @@ import { resetIdle } from "discourse/lib/desktop-notifications";
import { NotificationLevels } from "discourse/lib/notification-levels";
import discourseDebounce from "discourse-common/lib/debounce";
import { bind } from "discourse-common/utils/decorators";
+import ChatChannelThreadSubscriptionManager from "discourse/plugins/chat/discourse/lib/chat-channel-thread-subscription-manager";
import {
FUTURE,
PAST,
@@ -36,7 +37,6 @@ export default class ChatThread extends Component {
@service chatHistory;
@service chatThreadComposer;
@service chatThreadPane;
- @service chatThreadPaneSubscriptionsManager;
@service currentUser;
@service router;
@service siteSettings;
@@ -85,14 +85,9 @@ export default class ChatThread extends Component {
this.uploadDropZone = element;
}
- @action
- subscribeToUpdates() {
- this.chatThreadPaneSubscriptionsManager.subscribe(this.args.thread);
- }
-
@action
teardown() {
- this.chatThreadPaneSubscriptionsManager.unsubscribe();
+ this.subscriptionManager.teardown();
cancel(this._debouncedFillPaneAttemptHandler);
cancel(this._debounceUpdateLastReadMessageHandler);
}
@@ -166,7 +161,11 @@ export default class ChatThread extends Component {
@action
loadMessages() {
this.fetchMessages();
- this.subscribeToUpdates();
+ this.subscriptionManager = new ChatChannelThreadSubscriptionManager(
+ this,
+ this.args.thread,
+ { onNewMessage: this.onNewMessage }
+ );
}
@action
@@ -296,6 +295,11 @@ export default class ChatThread extends Component {
scrollListToMessage(this.scrollable, message, opts);
}
+ @bind
+ onNewMessage(message) {
+ this.messagesManager.addMessages([message]);
+ }
+
@bind
processMessages(thread, result) {
const messages = result.messages.map((messageData) => {
diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-pane-base-subscriptions-manager.js b/plugins/chat/assets/javascripts/discourse/lib/chat-channel-subscription-manager.js
similarity index 62%
rename from plugins/chat/assets/javascripts/discourse/services/chat-pane-base-subscriptions-manager.js
rename to plugins/chat/assets/javascripts/discourse/lib/chat-channel-subscription-manager.js
index 43692b0c8d0..bcf61be0032 100644
--- a/plugins/chat/assets/javascripts/discourse/services/chat-pane-base-subscriptions-manager.js
+++ b/plugins/chat/assets/javascripts/discourse/lib/chat-channel-subscription-manager.js
@@ -1,82 +1,46 @@
-import Service, { inject as service } from "@ember/service";
+import { tracked } from "@glimmer/tracking";
+import { getOwner, setOwner } from "@ember/application";
+import { inject as service } from "@ember/service";
import { cloneJSON } from "discourse-common/lib/object";
import { bind } from "discourse-common/utils/decorators";
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
+import ChatThreadPreview from "discourse/plugins/chat/discourse/models/chat-thread-preview";
-export function handleStagedMessage(channel, messagesManager, data) {
- const stagedMessage = messagesManager.findStagedMessage(data.staged_id);
-
- if (!stagedMessage) {
- return;
- }
-
- stagedMessage.error = null;
- stagedMessage.id = data.chat_message.id;
- stagedMessage.staged = false;
- stagedMessage.excerpt = data.chat_message.excerpt;
- stagedMessage.channel = channel;
- stagedMessage.createdAt = new Date(data.chat_message.created_at);
-
- return stagedMessage;
-}
-
-/**
- * Handles subscriptions for MessageBus messages sent from Chat::Publisher
- * to the channel and thread panes. There are individual services for
- * each (ChatChannelPaneSubscriptionsManager and ChatThreadPaneSubscriptionsManager)
- * that implement their own logic where necessary. Functions which will
- * always be different between the two raise a "not implemented" error in
- * the base class, and the child class must define the associated function,
- * even if it is a noop in that context.
- *
- * For example, in the thread context there is no need to handle the thread
- * creation event, because the panel will not be open in that case.
- */
-export default class ChatPaneBaseSubscriptionsManager extends Service {
- @service chat;
+export default class ChatChannelSubscriptionManager {
@service currentUser;
+ @service chatChannelNoticesManager;
+ @service messageBus;
- messageBusChannel = null;
- messageBusLastId = null;
+ @tracked channel;
- get messagesManager() {
- return this.model.messagesManager;
- }
+ constructor(context, channel, { onNewMessage } = {}) {
+ setOwner(this, getOwner(context));
- beforeSubscribe() {}
- afterMessage() {}
-
- subscribe(model) {
- this.unsubscribe();
- this.beforeSubscribe(model);
- this.model = model;
-
- if (!this.messageBusChannel) {
- return;
- }
+ this.channel = channel;
+ this.onNewMessage = onNewMessage;
this.messageBus.subscribe(
this.messageBusChannel,
this.onMessage,
- this.messageBusLastId
+ this.channel.channelMessageBusLastId
);
}
- unsubscribe() {
- if (!this.model) {
- return;
- }
-
- this.messageBus.unsubscribe(this.messageBusChannel, this.onMessage);
- this.model = null;
+ get messagesManager() {
+ return this.channel.messagesManager;
}
- handleStagedMessageInternal(channel, data) {
- return handleStagedMessage(channel, this.messagesManager, data);
+ get messageBusChannel() {
+ return `/chat/${this.channel.id}`;
+ }
+
+ teardown() {
+ this.messageBus.unsubscribe(this.messageBusChannel, this.onMessage);
+ this.modelId = null;
}
@bind
- onMessage(busData) {
+ onMessage(busData, _, __, lastMessageBusId) {
switch (busData.type) {
case "sent":
this.handleSentMessage(busData);
@@ -119,11 +83,42 @@ export default class ChatPaneBaseSubscriptionsManager extends Service {
break;
}
- this.afterMessage(this.model, ...arguments);
+ this.channel.channelMessageBusLastId = lastMessageBusId;
}
- handleSentMessage() {
- throw "not implemented";
+ handleSentMessage(data) {
+ if (data.chat_message.user.id === this.currentUser.id && data.staged_id) {
+ const stagedMessage = this.handleStagedMessage(
+ this.channel,
+ this.messagesManager,
+ data
+ );
+ if (stagedMessage) {
+ return;
+ }
+ }
+
+ const message = ChatMessage.create(this.channel, data.chat_message);
+ message.manager = this.channel.messagesManager;
+ this.onNewMessage?.(message);
+ this.channel.lastMessage = message;
+ }
+
+ handleStagedMessage(channel, messagesManager, data) {
+ const stagedMessage = messagesManager.findStagedMessage(data.staged_id);
+
+ if (!stagedMessage) {
+ return;
+ }
+
+ stagedMessage.error = null;
+ stagedMessage.id = data.chat_message.id;
+ stagedMessage.staged = false;
+ stagedMessage.excerpt = data.chat_message.excerpt;
+ stagedMessage.channel = channel;
+ stagedMessage.createdAt = new Date(data.chat_message.created_at);
+
+ return stagedMessage;
}
handleProcessedMessage(data) {
@@ -182,7 +177,10 @@ export default class ChatPaneBaseSubscriptionsManager extends Service {
this.messagesManager.removeMessage(targetMsg);
}
- this._afterDeleteMessage(targetMsg, data);
+ if (this.channel.currentUserMembership.lastReadMessageId === targetMsg.id) {
+ this.channel.currentUserMembership.lastReadMessageId =
+ data.latest_not_deleted_message_id;
+ }
}
handleRestoreMessage(data) {
@@ -211,10 +209,10 @@ export default class ChatPaneBaseSubscriptionsManager extends Service {
}
handleNewThreadCreated(data) {
- this.model.threadsManager
- .find(this.model.id, data.thread_id, { fetchIfNotFound: true })
+ this.channel.threadsManager
+ .find(this.channel.id, data.thread_id, { fetchIfNotFound: true })
.then((thread) => {
- const channelOriginalMessage = this.model.messagesManager.findMessage(
+ const channelOriginalMessage = this.channel.messagesManager.findMessage(
thread.originalMessage.id
);
@@ -224,15 +222,14 @@ export default class ChatPaneBaseSubscriptionsManager extends Service {
});
}
- handleThreadOriginalMessageUpdate() {
- throw "not implemented";
+ handleNotice(data) {
+ this.chatChannelNoticesManager.handleNotice(data);
}
- handleNotice() {
- throw "not implemented";
- }
-
- _afterDeleteMessage() {
- throw "not implemented";
+ handleThreadOriginalMessageUpdate(data) {
+ const message = this.messagesManager.findMessage(data.original_message_id);
+ if (message?.thread) {
+ message.thread.preview = ChatThreadPreview.create(data.preview);
+ }
}
}
diff --git a/plugins/chat/assets/javascripts/discourse/lib/chat-channel-thread-subscription-manager.js b/plugins/chat/assets/javascripts/discourse/lib/chat-channel-thread-subscription-manager.js
new file mode 100644
index 00000000000..4a329c88bba
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/lib/chat-channel-thread-subscription-manager.js
@@ -0,0 +1,215 @@
+import { tracked } from "@glimmer/tracking";
+import { getOwner, setOwner } from "@ember/application";
+import { inject as service } from "@ember/service";
+import { cloneJSON } from "discourse-common/lib/object";
+import { bind } from "discourse-common/utils/decorators";
+import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
+
+export default class ChatChannelThreadSubscriptionManager {
+ @service currentUser;
+ @service messageBus;
+
+ @tracked channel;
+
+ constructor(context, thread, { onNewMessage } = {}) {
+ setOwner(this, getOwner(context));
+
+ this.thread = thread;
+ this.onNewMessage = onNewMessage;
+
+ this.messageBus.subscribe(
+ this.messageBusChannel,
+ this.onMessage,
+ this.thread.channelMessageBusLastId
+ );
+ }
+
+ get messagesManager() {
+ return this.thread.messagesManager;
+ }
+
+ get messageBusChannel() {
+ return `/chat/${this.thread.channel.id}/thread/${this.thread.id}`;
+ }
+
+ teardown() {
+ this.messageBus.unsubscribe(this.messageBusChannel, this.onMessage);
+ }
+
+ @bind
+ onMessage(busData, _, __, lastMessageBusId) {
+ switch (busData.type) {
+ case "sent":
+ this.handleSentMessage(busData);
+ break;
+ case "reaction":
+ this.handleReactionMessage(busData);
+ break;
+ case "processed":
+ this.handleProcessedMessage(busData);
+ break;
+ case "edit":
+ this.handleEditMessage(busData);
+ break;
+ case "refresh":
+ this.handleRefreshMessage(busData);
+ break;
+ case "delete":
+ this.handleDeleteMessage(busData);
+ break;
+ case "bulk_delete":
+ this.handleBulkDeleteMessage(busData);
+ break;
+ case "restore":
+ this.handleRestoreMessage(busData);
+ break;
+ case "self_flagged":
+ this.handleSelfFlaggedMessage(busData);
+ break;
+ case "flag":
+ this.handleFlaggedMessage(busData);
+ break;
+ case "thread_created":
+ this.handleNewThreadCreated(busData);
+ break;
+ }
+
+ this.thread.threadMessageBusLastId = lastMessageBusId;
+ }
+
+ handleSentMessage(data) {
+ if (data.chat_message.user.id === this.currentUser.id && data.staged_id) {
+ const stagedMessage = this.handleStagedMessage(
+ this.thread.channel,
+ this.messagesManager,
+ data
+ );
+ if (stagedMessage) {
+ return;
+ }
+ }
+
+ const message = ChatMessage.create(this.thread.channel, data.chat_message);
+ message.thread = this.thread;
+ message.manager = this.messagesManager;
+ this.onNewMessage?.(message);
+ }
+
+ handleStagedMessage(channel, messagesManager, data) {
+ const stagedMessage = messagesManager.findStagedMessage(data.staged_id);
+
+ if (!stagedMessage) {
+ return;
+ }
+
+ stagedMessage.error = null;
+ stagedMessage.id = data.chat_message.id;
+ stagedMessage.staged = false;
+ stagedMessage.excerpt = data.chat_message.excerpt;
+ stagedMessage.channel = channel;
+ stagedMessage.createdAt = new Date(data.chat_message.created_at);
+
+ return stagedMessage;
+ }
+
+ handleProcessedMessage(data) {
+ const message = this.messagesManager.findMessage(data.chat_message.id);
+ if (message) {
+ message.cooked = data.chat_message.cooked;
+ message.processed = true;
+ }
+ }
+
+ handleReactionMessage(data) {
+ const message = this.messagesManager.findMessage(data.chat_message_id);
+ if (message) {
+ message.react(data.emoji, data.action, data.user, this.currentUser.id);
+ }
+ }
+
+ handleEditMessage(data) {
+ const message = this.messagesManager.findMessage(data.chat_message.id);
+ if (message) {
+ message.excerpt = data.chat_message.excerpt;
+ message.uploads = cloneJSON(data.chat_message.uploads || []);
+ message.edited = data.chat_message.edited;
+ }
+ }
+
+ handleRefreshMessage(data) {
+ const message = this.messagesManager.findMessage(data.chat_message.id);
+ if (message) {
+ message.incrementVersion();
+ }
+ }
+
+ handleBulkDeleteMessage(data) {
+ data.deleted_ids.forEach((deletedId) => {
+ this.handleDeleteMessage({
+ deleted_id: deletedId,
+ deleted_at: data.deleted_at,
+ });
+ });
+ }
+
+ handleDeleteMessage(data) {
+ const deletedId = data.deleted_id;
+ const targetMsg = this.messagesManager.findMessage(deletedId);
+
+ if (!targetMsg) {
+ return;
+ }
+
+ if (this.currentUser.staff || this.currentUser.id === targetMsg.user.id) {
+ targetMsg.deletedAt = data.deleted_at;
+ targetMsg.deletedById = data.deleted_by_id;
+ targetMsg.expanded = false;
+ } else {
+ this.messagesManager.removeMessage(targetMsg);
+ }
+
+ if (this.thread.currentUserMembership?.lastReadMessageId === targetMsg.id) {
+ this.thread.currentUserMembership.lastReadMessageId =
+ data.latest_not_deleted_message_id;
+ }
+ }
+
+ handleRestoreMessage(data) {
+ const message = this.messagesManager.findMessage(data.chat_message.id);
+ if (message) {
+ message.deletedAt = null;
+ } else {
+ const newMessage = ChatMessage.create(this.model, data.chat_message);
+ newMessage.manager = this.messagesManager;
+ this.messagesManager.addMessages([newMessage]);
+ }
+ }
+
+ handleSelfFlaggedMessage(data) {
+ const message = this.messagesManager.findMessage(data.chat_message_id);
+ if (message) {
+ message.userFlagStatus = data.user_flag_status;
+ }
+ }
+
+ handleFlaggedMessage(data) {
+ const message = this.messagesManager.findMessage(data.chat_message_id);
+ if (message) {
+ message.reviewableId = data.reviewable_id;
+ }
+ }
+
+ handleNewThreadCreated(data) {
+ this.thread.threadsManager
+ .find(this.thread.id, data.thread_id, { fetchIfNotFound: true })
+ .then((thread) => {
+ const channelOriginalMessage = this.thread.messagesManager.findMessage(
+ thread.originalMessage.id
+ );
+
+ if (channelOriginalMessage) {
+ channelOriginalMessage.thread = thread;
+ }
+ });
+ }
+}
diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-channel-notices-manager.js b/plugins/chat/assets/javascripts/discourse/services/chat-channel-notices-manager.js
new file mode 100644
index 00000000000..705020c2a46
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/services/chat-channel-notices-manager.js
@@ -0,0 +1,16 @@
+import { tracked } from "@glimmer/tracking";
+import Service from "@ember/service";
+import { TrackedArray } from "@ember-compat/tracked-built-ins";
+import ChatNotice from "../models/chat-notice";
+
+export default class ChatChannelNoticesManager extends Service {
+ @tracked notices = new TrackedArray();
+
+ handleNotice(data) {
+ this.notices.pushObject(ChatNotice.create(data));
+ }
+
+ clearNotice(notice) {
+ this.notices.removeObject(notice);
+ }
+}
diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-channel-pane-subscriptions-manager.js b/plugins/chat/assets/javascripts/discourse/services/chat-channel-pane-subscriptions-manager.js
deleted file mode 100644
index f97cddc0610..00000000000
--- a/plugins/chat/assets/javascripts/discourse/services/chat-channel-pane-subscriptions-manager.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { tracked } from "@glimmer/tracking";
-import { inject as service } from "@ember/service";
-import { TrackedArray } from "@ember-compat/tracked-built-ins";
-import ChatNotice from "../models/chat-notice";
-import ChatThreadPreview from "../models/chat-thread-preview";
-import ChatPaneBaseSubscriptionsManager from "./chat-pane-base-subscriptions-manager";
-
-export default class ChatChannelPaneSubscriptionsManager extends ChatPaneBaseSubscriptionsManager {
- @service chat;
- @service currentUser;
-
- @tracked notices = new TrackedArray();
-
- beforeSubscribe(model) {
- this.messageBusChannel = `/chat/${model.id}`;
- this.messageBusLastId = model.channelMessageBusLastId;
- }
-
- afterMessage(model, _, __, lastMessageBusId) {
- model.channelMessageBusLastId = lastMessageBusId;
- }
-
- handleSentMessage() {
- return;
- }
-
- handleNotice(data) {
- this.notices.pushObject(ChatNotice.create(data));
- }
-
- clearNotice(notice) {
- this.notices.removeObject(notice);
- }
-
- handleThreadOriginalMessageUpdate(data) {
- const message = this.messagesManager.findMessage(data.original_message_id);
- if (message?.thread) {
- message.thread.preview = ChatThreadPreview.create(data.preview);
- }
- }
-
- _afterDeleteMessage(targetMsg, data) {
- if (this.model.currentUserMembership.lastReadMessageId === targetMsg.id) {
- this.model.currentUserMembership.lastReadMessageId =
- data.latest_not_deleted_message_id;
- }
- }
-}
diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-thread-pane-subscriptions-manager.js b/plugins/chat/assets/javascripts/discourse/services/chat-thread-pane-subscriptions-manager.js
deleted file mode 100644
index 365c478b1aa..00000000000
--- a/plugins/chat/assets/javascripts/discourse/services/chat-thread-pane-subscriptions-manager.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
-import ChatPaneBaseSubscriptionsManager from "./chat-pane-base-subscriptions-manager";
-
-export default class ChatThreadPaneSubscriptionsManager extends ChatPaneBaseSubscriptionsManager {
- beforeSubscribe(model) {
- this.messageBusChannel = `/chat/${model.channel.id}/thread/${model.id}`;
- this.messageBusLastId = model.threadMessageBusLastId;
- }
-
- afterMessage(model, _, __, lastMessageBusId) {
- model.threadMessageBusLastId = lastMessageBusId;
- }
-
- handleSentMessage(data) {
- if (data.chat_message.user.id === this.currentUser.id && data.staged_id) {
- const stagedMessage = this.handleStagedMessageInternal(
- this.model.channel,
- data
- );
- if (stagedMessage) {
- return;
- }
- }
-
- const message = ChatMessage.create(this.model.channel, data.chat_message);
- message.thread = this.model;
- message.manager = this.messagesManager;
- this.messagesManager.addMessages([message]);
- }
-
- // NOTE: noop, there is nothing to do when a thread original message
- // is updated inside the thread panel (for now).
- handleThreadOriginalMessageUpdate() {
- return;
- }
-
- // NOTE: We don't yet handle notices inside of threads so do nothing.
- handleNotice() {
- return;
- }
-
- _afterDeleteMessage(targetMsg, data) {
- if (this.model.currentUserMembership?.lastReadMessageId === targetMsg.id) {
- this.model.currentUserMembership.lastReadMessageId =
- data.latest_not_deleted_message_id;
- }
- }
-}
diff --git a/plugins/chat/assets/javascripts/discourse/templates/chat-channel-thread.hbs b/plugins/chat/assets/javascripts/discourse/templates/chat-channel-thread.hbs
index df4708f87a0..920a6676e4c 100644
--- a/plugins/chat/assets/javascripts/discourse/templates/chat-channel-thread.hbs
+++ b/plugins/chat/assets/javascripts/discourse/templates/chat-channel-thread.hbs
@@ -1,5 +1,7 @@
-
\ No newline at end of file
+{{#each (array this.model) as |thread|}}
+
+{{/each}}
\ No newline at end of file
diff --git a/plugins/chat/test/javascripts/components/chat-notices-test.js b/plugins/chat/test/javascripts/components/chat-notices-test.js
index 617d34d6ae1..12fdd84127a 100644
--- a/plugins/chat/test/javascripts/components/chat-notices-test.js
+++ b/plugins/chat/test/javascripts/components/chat-notices-test.js
@@ -12,9 +12,7 @@ module("Discourse Chat | Component | chat-notice", function (hooks) {
test("displays all notices for a channel", async function (assert) {
this.channel = fabricators.channel();
- this.manager = this.container.lookup(
- "service:chatChannelPaneSubscriptionsManager"
- );
+ this.manager = this.container.lookup("service:chatChannelNoticesManager");
this.manager.handleNotice({
channel_id: this.channel.id,
text_content: "hello",
@@ -40,9 +38,7 @@ module("Discourse Chat | Component | chat-notice", function (hooks) {
test("Notices can be cleared", async function (assert) {
this.channel = fabricators.channel();
- this.manager = this.container.lookup(
- "service:chatChannelPaneSubscriptionsManager"
- );
+ this.manager = this.container.lookup("service:chatChannelNoticesManager");
this.manager.handleNotice({
channel_id: this.channel.id,
text_content: "hello",
@@ -66,9 +62,7 @@ module("Discourse Chat | Component | chat-notice", function (hooks) {
});
test("MentionWithoutMembership notice renders", async function (assert) {
this.channel = fabricators.channel();
- this.manager = this.container.lookup(
- "service:chatChannelPaneSubscriptionsManager"
- );
+ this.manager = this.container.lookup("service:chatChannelNoticesManager");
const text = "Joffrey can't chat, hermano";
this.manager.handleNotice({
channel_id: this.channel.id,