From f05b984208e312ead39ce0ded560350d0b427ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Thu, 17 Oct 2024 14:51:26 +0200 Subject: [PATCH] DEV: glimmerify discourse-presence (#29235) --- .../components/composer-presence-display.hbs | 51 +++--- .../components/composer-presence-display.js | 172 ++++++++++-------- .../components/topic-presence-display.hbs | 45 +++-- .../components/topic-presence-display.js | 98 +++++----- 4 files changed, 206 insertions(+), 160 deletions(-) diff --git a/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.hbs b/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.hbs index 8b547fd0bfd..848800ff3b8 100644 --- a/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.hbs +++ b/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.hbs @@ -1,23 +1,30 @@ -{{#if this.shouldDisplay}} -
-
- {{#each this.presenceUsers as |user|}} - {{avatar user imageSize="small"}} - {{/each}} +
+ {{#if this.shouldDisplay}} +
+
+ {{#each this.users as |user|}} + + {{avatar user imageSize="small"}} + + {{/each}} +
+ + + {{~#if this.isReply~}} + {{i18n "presence.replying" count=this.users.length}} + {{~else~}} + {{i18n "presence.editing" count=this.users.length}} + {{~/if~}} + + + . + . + . + +
- - - {{~#if this.isReply~}} - {{i18n "presence.replying" count=this.presenceUsers.length}} - {{~else~}} - {{i18n "presence.editing" count=this.presenceUsers.length}} - {{~/if~}} - - - . - . - . - - -
-{{/if}} \ No newline at end of file + {{/if}} +
\ No newline at end of file diff --git a/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.js b/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.js index 81ec9c191c7..80feba20f9d 100644 --- a/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.js +++ b/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.js @@ -1,32 +1,30 @@ -import Component from "@ember/component"; -import { equal, gt, readOnly, union } from "@ember/object/computed"; +import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; +import { action } from "@ember/object"; import { service } from "@ember/service"; -import { tagName } from "@ember-decorators/component"; -import { observes, on } from "@ember-decorators/object"; -import discourseComputed from "discourse-common/utils/decorators"; -@tagName("") -export default class ComposerPresenceDisplay extends Component { +export default class ComposerPresenceDisplayComponent extends Component { @service presence; @service composerPresenceManager; + @service currentUser; + @service siteSettings; - @equal("state", "reply") isReply; - @equal("state", "edit") isEdit; - @equal("state", "whisper") isWhisper; - @union("replyChannel.users", "whisperChannel.users") replyingUsers; - @readOnly("editChannel.users") editingUsers; - @gt("presenceUsers.length", 0) shouldDisplay; + @tracked replyChannel; + @tracked whisperChannel; + @tracked editChannel; - @discourseComputed( - "model.replyingToTopic", - "model.editingPost", - "model.whisper", - "model.composerOpened" - ) - state(replyingToTopic, editingPost, whisper, composerOpen) { - if (!composerOpen) { - return; - } else if (editingPost) { + get isReply() { + return this.state === "reply" || this.state === "whisper"; + } + + get isEdit() { + return this.state === "edit"; + } + + get state() { + const { editingPost, whisper, replyingToTopic } = this.args.model; + + if (editingPost) { return "edit"; } else if (whisper) { return "whisper"; @@ -35,77 +33,105 @@ export default class ComposerPresenceDisplay extends Component { } } - @discourseComputed("model.topic.id", "isReply", "isWhisper") - replyChannelName(topicId, isReply, isWhisper) { - if (topicId && (isReply || isWhisper)) { + get replyChannelName() { + const topicId = this.args.model?.topic?.id; + if (topicId && this.isReply) { return `/discourse-presence/reply/${topicId}`; } } - @discourseComputed("model.topic.id", "isReply", "isWhisper") - whisperChannelName(topicId, isReply, isWhisper) { - if (topicId && this.currentUser.whisperer && (isReply || isWhisper)) { + get whisperChannelName() { + const topicId = this.args.model?.topic?.id; + if (topicId && this.isReply && this.currentUser.whisperer) { return `/discourse-presence/whisper/${topicId}`; } } - @discourseComputed("isEdit", "model.post.id") - editChannelName(isEdit, postId) { - if (isEdit) { + get editChannelName() { + const postId = this.args.model?.post?.id; + if (postId && this.isEdit) { return `/discourse-presence/edit/${postId}`; } } - _setupChannel(channelKey, name) { - if (this[channelKey]?.name !== name) { - this[channelKey]?.unsubscribe(); + get replyUsers() { + return this.replyChannel?.users || []; + } + + get whisperUsers() { + return this.whisperChannel?.users || []; + } + + get replyingUsers() { + return [...this.replyUsers, ...this.whisperUsers]; + } + + get editingUsers() { + return this.editChannel?.users || []; + } + + get users() { + const users = this.isEdit ? this.editingUsers : this.replyingUsers; + return users + .filter((u) => u.id !== this.currentUser.id) + .slice(0, this.siteSettings.presence_max_users_shown); + } + + get shouldDisplay() { + return this.users.length > 0; + } + + @action + setupChannels() { + this.setupReplyChannel(); + this.setupWhisperChannel(); + this.setupEditChannel(); + this.notifyState(); + } + + setupReplyChannel() { + this.setupChannel("replyChannel", this.replyChannelName); + } + + setupWhisperChannel() { + if (this.currentUser.staff) { + this.setupChannel("whisperChannel", this.whisperChannelName); + } + } + + setupEditChannel() { + this.setupChannel("editChannel", this.editChannelName); + } + + setupChannel(key, name) { + if (this[key]?.name !== name) { + this[key]?.unsubscribe(); if (name) { - this.set(channelKey, this.presence.getChannel(name)); - this[channelKey].subscribe(); - } else if (this[channelKey]) { - this.set(channelKey, null); + this[key] = this.presence.getChannel(name); + this[key].subscribe(); } } } - @observes("replyChannelName", "whisperChannelName", "editChannelName") - _setupChannels() { - this._setupChannel("replyChannel", this.replyChannelName); - this._setupChannel("whisperChannel", this.whisperChannelName); - this._setupChannel("editChannel", this.editChannelName); - } + notifyState() { + const { reply, post, topic } = this.args.model; + const raw = this.isEdit ? post?.raw || "" : ""; + const entity = this.isEdit ? post : topic; - _cleanupChannels() { - this._setupChannel("replyChannel", null); - this._setupChannel("whisperChannel", null); - this._setupChannel("editChannel", null); - } - - @discourseComputed("isReply", "replyingUsers.[]", "editingUsers.[]") - presenceUsers(isReply, replyingUsers, editingUsers) { - const users = isReply ? replyingUsers : editingUsers; - return users - ?.filter((u) => u.id !== this.currentUser.id) - ?.slice(0, this.siteSettings.presence_max_users_shown); - } - - @on("didInsertElement") - subscribe() { - this._setupChannels(); - } - - @observes("model.reply", "state", "model.post.id", "model.topic.id") - _contentChanged() { - if (this.model.reply === "") { - return; + if (reply !== raw) { + this.composerPresenceManager.notifyState(this.state, entity?.id); } - const entity = this.state === "edit" ? this.model?.post : this.model?.topic; - this.composerPresenceManager.notifyState(this.state, entity?.id); } - @on("willDestroyElement") - closeComposer() { - this._cleanupChannels(); + willDestroy() { + super.willDestroy(...arguments); + this.unsubscribeFromChannels(); this.composerPresenceManager.leave(); } + + unsubscribeFromChannels() { + this.replyChannel?.unsubscribe(); + this.whisperChannel?.unsubscribe(); + this.editChannel?.unsubscribe(); + } } diff --git a/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.hbs b/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.hbs index 04fdfffd0f0..3da513e1bc4 100644 --- a/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.hbs +++ b/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.hbs @@ -1,21 +1,26 @@ -{{#if this.shouldDisplay}} -
-
- {{#each this.users as |user|}} - - {{avatar user imageSize="small"}} - - {{/each}} +
+ {{#if this.shouldDisplay}} +
+
+ {{#each this.users as |user|}} + + {{avatar user imageSize="small"}} + + {{/each}} +
+ + + {{i18n "presence.replying_to_topic" count=this.users.length}} + + + . + . + . + +
- - - {{i18n "presence.replying_to_topic" count=this.users.length}} - - - . - . - . - - -
-{{/if}} \ No newline at end of file + {{/if}} +
\ No newline at end of file diff --git a/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.js b/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.js index 4cd60b1674f..1018d4b403a 100644 --- a/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.js +++ b/plugins/discourse-presence/assets/javascripts/discourse/components/topic-presence-display.js @@ -1,64 +1,72 @@ -import Component from "@ember/component"; -import { gt, union } from "@ember/object/computed"; +import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; +import { action } from "@ember/object"; import { service } from "@ember/service"; -import { on } from "@ember-decorators/object"; -import discourseComputed from "discourse-common/utils/decorators"; -export default class TopicPresenceDisplay extends Component { +export default class TopicPresenceDisplayComponent extends Component { @service presence; + @service currentUser; - topic = null; - replyChannel = null; - whisperChannel = null; + @tracked replyChannel; + @tracked whisperChannel; - @union("replyUsers", "whisperUsers") users; - @gt("users.length", 0) shouldDisplay; - - @discourseComputed("replyChannel.users.[]") - replyUsers(users) { - return users?.filter((u) => u.id !== this.currentUser.id); + get replyChannelName() { + return `/discourse-presence/reply/${this.args.topic.id}`; } - @discourseComputed("whisperChannel.users.[]") - whisperUsers(users) { - return users?.filter((u) => u.id !== this.currentUser.id); + get whisperChannelName() { + return `/discourse-presence/whisper/${this.args.topic.id}`; } - @discourseComputed("topic.id") - replyChannelName(id) { - return `/discourse-presence/reply/${id}`; + get replyUsers() { + return this.replyChannel?.users || []; } - @discourseComputed("topic.id") - whisperChannelName(id) { - return `/discourse-presence/whisper/${id}`; + get whisperUsers() { + return this.whisperChannel?.users || []; } - didReceiveAttrs() { - super.didReceiveAttrs(...arguments); - - if (this.replyChannel?.name !== this.replyChannelName) { - this.replyChannel?.unsubscribe(); - this.set("replyChannel", this.presence.getChannel(this.replyChannelName)); - this.replyChannel.subscribe(); - } - - if ( - this.currentUser.staff && - this.whisperChannel?.name !== this.whisperChannelName - ) { - this.whisperChannel?.unsubscribe(); - this.set( - "whisperChannel", - this.presence.getChannel(this.whisperChannelName) - ); - this.whisperChannel.subscribe(); - } + get users() { + return [...this.replyUsers, ...this.whisperUsers].filter( + (u) => u.id !== this.currentUser.id + ); } - @on("willDestroyElement") - _destroyed() { + get shouldDisplay() { + return this.users.length > 0; + } + + @action + setupChannels() { + this.setupReplyChannel(); + this.setupWhisperChannel(); + } + + willDestroy() { + super.willDestroy(...arguments); + this.unsubscribeFromChannels(); + } + + unsubscribeFromChannels() { this.replyChannel?.unsubscribe(); this.whisperChannel?.unsubscribe(); } + + setupReplyChannel() { + if (this.replyChannel?.name !== this.replyChannelName) { + this.replyChannel?.unsubscribe(); + this.replyChannel = this.presence.getChannel(this.replyChannelName); + this.replyChannel.subscribe(); + } + } + + setupWhisperChannel() { + if (this.currentUser.staff) { + if (this.whisperChannel?.name !== this.whisperChannelName) { + this.whisperChannel?.unsubscribe(); + this.whisperChannel = this.presence.getChannel(this.whisperChannelName); + this.whisperChannel.subscribe(); + } + } + } }