From 1ce12ae7188af3322c0dea101bb7c60b4b6a3a71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Wed, 4 Dec 2024 12:21:55 +0100 Subject: [PATCH] DEV: Deleted the "ChatComposerPresenceManager"... (#30098) ...since it was mostly duplicating the work the "ComposerPresenceManager" was doing. So now the #chat composer uses the same "presence manager" as the composer, benefiting from the "hide presence" checks, with the only difference that the "keep alive" timeout is 5s for chat and 10s for topics/posts. --- .../discourse/components/chat-channel.gjs | 1 - .../discourse/components/chat-composer.js | 9 ++- .../discourse/components/chat-thread.gjs | 1 - .../chat-composer-presence-manager.js | 54 ----------------- .../components/composer-presence-display.gjs | 56 ++++++++--------- .../components/topic-presence-display.gjs | 37 +++++++----- .../services/composer-presence-manager.js | 60 +++++++------------ 7 files changed, 79 insertions(+), 139 deletions(-) delete mode 100644 plugins/chat/assets/javascripts/discourse/services/chat-composer-presence-manager.js diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel.gjs b/plugins/chat/assets/javascripts/discourse/components/chat-channel.gjs index 98a1caaf077..bdaab6a9d9d 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel.gjs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel.gjs @@ -54,7 +54,6 @@ export default class ChatChannel extends Component { @service chat; @service chatApi; @service chatChannelsManager; - @service chatComposerPresenceManager; @service chatDraftsManager; @service chatEmojiPickerManager; @service chatStateManager; diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-composer.js b/plugins/chat/assets/javascripts/discourse/components/chat-composer.js index 718950e8f26..6fb08faee38 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-composer.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-composer.js @@ -30,13 +30,15 @@ import { chatComposerButtons } from "discourse/plugins/chat/discourse/lib/chat-c import ChatMessageInteractor from "discourse/plugins/chat/discourse/lib/chat-message-interactor"; import TextareaInteractor from "discourse/plugins/chat/discourse/lib/textarea-interactor"; +const CHAT_PRESENCE_KEEP_ALIVE = 5 * 1000; // 5 seconds + export default class ChatComposer extends Component { @service capabilities; @service site; @service siteSettings; @service store; @service chat; - @service chatComposerPresenceManager; + @service composerPresenceManager; @service chatComposerWarningsTracker; @service appEvents; @service chatEmojiReactionStore; @@ -256,9 +258,10 @@ export default class ChatComposer extends Component { return; } - this.chatComposerPresenceManager.notifyState( + this.composerPresenceManager.notifyState( this.presenceChannelName, - !this.draft.editing && this.hasContent + !this.draft.editing && this.hasContent, + CHAT_PRESENCE_KEEP_ALIVE ); } diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-thread.gjs b/plugins/chat/assets/javascripts/discourse/components/chat-thread.gjs index d58797bcc83..b5020270b96 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-thread.gjs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-thread.gjs @@ -46,7 +46,6 @@ export default class ChatThread extends Component { @service capabilities; @service chat; @service chatApi; - @service chatComposerPresenceManager; @service chatHistory; @service chatDraftsManager; @service chatThreadComposer; diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-composer-presence-manager.js b/plugins/chat/assets/javascripts/discourse/services/chat-composer-presence-manager.js deleted file mode 100644 index bba9c23e5b8..00000000000 --- a/plugins/chat/assets/javascripts/discourse/services/chat-composer-presence-manager.js +++ /dev/null @@ -1,54 +0,0 @@ -import { cancel, debounce } from "@ember/runloop"; -import Service, { service } from "@ember/service"; -import { isTesting } from "discourse-common/config/environment"; - -const KEEP_ALIVE_DURATION_SECONDS = 10; - -// This service is loosely based on discourse-presence's ComposerPresenceManager service -// It is a singleton which receives notifications each time the value of the chat composer changes -// This service ensures that a single browser can only be 'replying' to a single chatChannel at -// one time, and automatically 'leaves' the channel if the composer value hasn't changed for 10 seconds -export default class ChatComposerPresenceManager extends Service { - @service presence; - - willDestroy() { - this.leave(); - } - - notifyState(channelName, replying) { - if (!replying) { - this.leave(); - return; - } - - if (this._channelName !== channelName) { - this._enter(channelName); - this._channelName = channelName; - } - - if (!isTesting()) { - this._autoLeaveTimer = debounce( - this, - this.leave, - KEEP_ALIVE_DURATION_SECONDS * 1000 - ); - } - } - - leave() { - this._presentChannel?.leave(); - this._presentChannel = null; - this._channelName = null; - if (this._autoLeaveTimer) { - cancel(this._autoLeaveTimer); - this._autoLeaveTimer = null; - } - } - - _enter(channelName) { - this.leave(); - - this._presentChannel = this.presence.getChannel(channelName); - this._presentChannel.enter(); - } -} diff --git a/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.gjs b/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.gjs index c4a90414c36..7da31830ce8 100644 --- a/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.gjs +++ b/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.gjs @@ -18,60 +18,58 @@ export default class ComposerPresenceDisplay extends Component { @tracked editChannel; setupReplyChannel = helperFn((_, on) => { - const topic = this.args.model.topic; + const { topic } = this.args.model; + if (!topic || !this.isReply) { return; } - const replyChannel = this.presence.getChannel( - `/discourse-presence/reply/${topic.id}` - ); - replyChannel.subscribe(); + const name = `/discourse-presence/reply/${topic.id}`; + const replyChannel = this.presence.getChannel(name); this.replyChannel = replyChannel; + replyChannel.subscribe(); on.cleanup(() => replyChannel.unsubscribe()); }); setupWhisperChannel = helperFn((_, on) => { - if ( - !this.args.model.topic || - !this.isReply || - !this.currentUser.staff || - !this.currentUser.whisperer - ) { + const { topic } = this.args.model; + const { whisperer } = this.currentUser; + + if (!topic || !this.isReply || !whisperer) { return; } - const whisperChannel = this.presence.getChannel( - `/discourse-presence/whisper/${this.args.model.topic.id}` - ); - whisperChannel.subscribe(); + const name = `/discourse-presence/whisper/${topic.id}`; + const whisperChannel = this.presence.getChannel(name); this.whisperChannel = whisperChannel; + whisperChannel.subscribe(); on.cleanup(() => whisperChannel.unsubscribe()); }); setupEditChannel = helperFn((_, on) => { - if (!this.args.model.post || !this.isEdit) { + const { post } = this.args.model; + + if (!post || !this.isEdit) { return; } - const editChannel = this.presence.getChannel( - `/discourse-presence/edit/${this.args.model.post.id}` - ); - editChannel.subscribe(); + const name = `/discourse-presence/edit/${post.id}`; + const editChannel = this.presence.getChannel(name); this.editChannel = editChannel; + editChannel.subscribe(); on.cleanup(() => editChannel.unsubscribe()); }); notifyState = helperFn((_, on) => { - const { topic, post, reply } = this.args.model; - const raw = this.isEdit ? post?.raw || "" : ""; + const { topic, post, replyDirty } = this.args.model; const entity = this.isEdit ? post : topic; - if (reply !== raw) { - this.composerPresenceManager.notifyState(this.state, entity?.id); + if (entity) { + const name = `/discourse-presence/${this.state}/${entity.id}`; + this.composerPresenceManager.notifyState(name, replyDirty); } on.cleanup(() => this.composerPresenceManager.leave()); @@ -85,12 +83,15 @@ export default class ComposerPresenceDisplay extends Component { return this.state === "edit"; } + @cached get state() { - if (this.args.model.editingPost) { + const { editingPost, whisper, replyingToTopic } = this.args.model; + + if (editingPost) { return "edit"; - } else if (this.args.model.whisper) { + } else if (whisper) { return "whisper"; - } else if (this.args.model.replyingToTopic) { + } else if (replyingToTopic) { return "reply"; } } @@ -98,6 +99,7 @@ export default class ComposerPresenceDisplay extends Component { @cached get users() { let users; + if (this.isEdit) { users = this.editChannel?.users || []; } else { diff --git a/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.gjs b/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.gjs index 0431b6928b7..e85890bb6bf 100644 --- a/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.gjs +++ b/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.gjs @@ -15,26 +15,33 @@ export default class TopicPresenceDisplay extends Component { @tracked whisperChannel; setupReplyChannel = helperFn((_, on) => { - const replyChannel = this.presence.getChannel( - `/discourse-presence/reply/${this.args.topic.id}` - ); - replyChannel.subscribe(); - this.replyChannel = replyChannel; + const { topic } = this.args; - on.cleanup(() => replyChannel.unsubscribe()); - }); - - setupWhisperChannels = helperFn((_, on) => { - if (!this.currentUser.staff) { + if (!topic) { return; } - const whisperChannel = this.presence.getChannel( - `/discourse-presence/whisper/${this.args.topic.id}` - ); - whisperChannel.subscribe(); + const name = `/discourse-presence/reply/${topic.id}`; + const replyChannel = this.presence.getChannel(name); + this.replyChannel = replyChannel; + + replyChannel.subscribe(); + on.cleanup(() => replyChannel.unsubscribe()); + }); + + setupWhisperChannel = helperFn((_, on) => { + const { topic } = this.args; + const { whisperer } = this.currentUser; + + if (!topic || !whisperer) { + return; + } + + const name = `/discourse-presence/whisper/${topic.id}`; + const whisperChannel = this.presence.getChannel(name); this.whisperChannel = whisperChannel; + whisperChannel.subscribe(); on.cleanup(() => whisperChannel.unsubscribe()); }); @@ -50,7 +57,7 @@ export default class TopicPresenceDisplay extends Component {