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,