This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/plugins/discourse-presence/assets/javascripts/discourse/components/composer-presence-display.js
David Taylor a6230b8138
UX: Improve composer presence-display positioning (#15235)
Previously the discourse-presence plugin was using a `position: absolute` hack to display the 'replying...' users in the top right of the composer. This commit adds a more suitable plugin outlet, and updates the discourse-presence styling so it slots into the flex-box layout at the top of the composer
2021-12-08 16:18:49 +00:00

115 lines
3.2 KiB
JavaScript

import discourseComputed, {
observes,
on,
} from "discourse-common/utils/decorators";
import { equal, gt, readOnly, union } from "@ember/object/computed";
import Component from "@ember/component";
import { inject as service } from "@ember/service";
export default Component.extend({
tagName: "",
presence: service(),
composerPresenceManager: service(),
@discourseComputed(
"model.replyingToTopic",
"model.editingPost",
"model.whisper",
"model.composerOpened"
)
state(replyingToTopic, editingPost, whisper, composerOpen) {
if (!composerOpen) {
return;
} else if (editingPost) {
return "edit";
} else if (whisper) {
return "whisper";
} else if (replyingToTopic) {
return "reply";
}
},
isReply: equal("state", "reply"),
isEdit: equal("state", "edit"),
isWhisper: equal("state", "whisper"),
@discourseComputed("model.topic.id", "isReply", "isWhisper")
replyChannelName(topicId, isReply, isWhisper) {
if (topicId && (isReply || isWhisper)) {
return `/discourse-presence/reply/${topicId}`;
}
},
@discourseComputed("model.topic.id", "isReply", "isWhisper")
whisperChannelName(topicId, isReply, isWhisper) {
if (topicId && this.currentUser.staff && (isReply || isWhisper)) {
return `/discourse-presence/whisper/${topicId}`;
}
},
@discourseComputed("isEdit", "model.post.id")
editChannelName(isEdit, postId) {
if (isEdit) {
return `/discourse-presence/edit/${postId}`;
}
},
_setupChannel(channelKey, name) {
if (this[channelKey]?.name !== name) {
this[channelKey]?.unsubscribe();
if (name) {
this.set(channelKey, this.presence.getChannel(name));
this[channelKey].subscribe();
} else if (this[channelKey]) {
this.set(channelKey, null);
}
}
},
@observes("replyChannelName", "whisperChannelName", "editChannelName")
_setupChannels() {
this._setupChannel("replyChannel", this.replyChannelName);
this._setupChannel("whisperChannel", this.whisperChannelName);
this._setupChannel("editChannel", this.editChannelName);
},
_cleanupChannels() {
this._setupChannel("replyChannel", null);
this._setupChannel("whisperChannel", null);
this._setupChannel("editChannel", null);
},
replyingUsers: union("replyChannel.users", "whisperChannel.users"),
editingUsers: readOnly("editChannel.users"),
@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);
},
shouldDisplay: gt("presenceUsers.length", 0),
@on("didInsertElement")
subscribe() {
this._setupChannels();
},
@observes("model.reply", "state", "model.post.id", "model.topic.id")
_contentChanged() {
if (this.model.reply === "") {
return;
}
const entity = this.state === "edit" ? this.model?.post : this.model?.topic;
this.composerPresenceManager.notifyState(this.state, entity?.id);
},
@on("willDestroyElement")
closeComposer() {
this._cleanupChannels();
this.composerPresenceManager.leave();
},
});