mirror of
https://github.com/discourse/discourse.git
synced 2026-08-19 01:14:56 -05:00
FEATURE: Initial chat thread indicator and disabling echo mode in channels (#21047)
This commit introduces a new thread indicator for channels with `threading_enabled` set to true and the `enable_exp` site setting set to true. In addition, in the main channel stream we now hide all messages that are linked to threads except for the original message, disabling the concept of an "echo mode" for now, we may revisit this in future. We also remove the jigsaw puzzle "Open Thread" button for message actions, since the thread indicator can just be used instead. This also stops the `Chat::Publisher` from sending any messages related to chat messages that are linked to a thread, unless that chat message is the OM of the thread. A subsequent PR will link up all MessageBus events within the thread panel, and for the message indicators. Another subsequent PR will add the excerpt of the latest message in each thread, as well as the avatars of the users messaging in the thread. Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
This commit is contained in:
co-authored by
Joffrey JAFFEUX
parent
f0435844df
commit
584a17c948
@@ -35,7 +35,10 @@
|
||||
@value={{readonly this.value}}
|
||||
@input={{action "onTextareaInput" value="target.value"}}
|
||||
@type="text"
|
||||
@class="chat-composer-input"
|
||||
@class={{concat-class
|
||||
"chat-composer-input"
|
||||
(concat "chat-composer-input--" @context)
|
||||
}}
|
||||
@disabled={{this.disableComposer}}
|
||||
@autocorrect="on"
|
||||
@autocapitalize="sentences"
|
||||
|
||||
@@ -550,6 +550,19 @@ export default class ChatLivePane extends Component {
|
||||
case "flag":
|
||||
this.handleFlaggedMessage(data);
|
||||
break;
|
||||
case "thread_created":
|
||||
this.handleThreadCreated(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleThreadCreated(data) {
|
||||
const message = this.args.channel.messagesManager.findMessage(
|
||||
data.chat_message.id
|
||||
);
|
||||
if (message) {
|
||||
message.threadId = data.chat_message.thread_id;
|
||||
message.threadReplyCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -773,7 +786,14 @@ export default class ChatLivePane extends Component {
|
||||
stagedMessage.inReplyTo = this.chatChannelComposer.replyToMsg;
|
||||
}
|
||||
|
||||
this.args.channel.messagesManager.addMessages([stagedMessage]);
|
||||
if (stagedMessage.inReplyTo) {
|
||||
if (!this.args.channel.threadingEnabled) {
|
||||
this.args.channel.messagesManager.addMessages([stagedMessage]);
|
||||
}
|
||||
} else {
|
||||
this.args.channel.messagesManager.addMessages([stagedMessage]);
|
||||
}
|
||||
|
||||
if (!this.args.channel.messagesManager.canLoadMoreFuture) {
|
||||
this.scrollToLatestMessage();
|
||||
}
|
||||
|
||||
@@ -50,15 +50,6 @@
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.messageInteractor.canOpenThread}}
|
||||
<DButton
|
||||
@class="btn-flat chat-message-thread-btn"
|
||||
@action={{this.messageInteractor.openThread}}
|
||||
@icon="puzzle-piece"
|
||||
@title="chat.threads.open"
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.messageInteractor.secondaryButtons.length}}
|
||||
<DropdownSelectBox
|
||||
@class="more-buttons"
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<LinkTo
|
||||
@route="chat.channel.thread"
|
||||
@models={{@message.threadRouteModels}}
|
||||
class="chat-message-thread-indicator"
|
||||
>
|
||||
<span class="chat-message-thread-indicator__replies-count">
|
||||
{{i18n "chat.thread.replies" count=@message.threadReplyCount}}
|
||||
</span>
|
||||
<span class="chat-message-thread-indicator__view-thread">
|
||||
{{i18n "chat.thread.view_thread"}}
|
||||
</span>
|
||||
</LinkTo>
|
||||
@@ -0,0 +1,3 @@
|
||||
import Component from "@glimmer/component";
|
||||
|
||||
export default class ChatMessageThreadIndicator extends Component {}
|
||||
@@ -21,6 +21,7 @@
|
||||
(if @message.highlighted "highlighted")
|
||||
}}
|
||||
data-id={{@message.id}}
|
||||
data-thread-id={{@message.threadId}}
|
||||
{{chat/track-message
|
||||
(hash
|
||||
didEnterViewport=(fn @messageDidEnterViewport @message)
|
||||
@@ -61,6 +62,7 @@
|
||||
(if @message.staged "chat-message-staged")
|
||||
(if @message.deletedAt "deleted")
|
||||
(if (and @message.inReplyTo (not this.hideReplyToInfo)) "is-reply")
|
||||
(if this.showThreadIndicator "is-threaded")
|
||||
(if this.hideUserInfo "user-info-hidden")
|
||||
(if @message.error "errored")
|
||||
(if @message.bookmark "chat-message-bookmarked")
|
||||
@@ -189,6 +191,10 @@
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#if this.showThreadIndicator}}
|
||||
<ChatMessageThreadIndicator @message={{@message}} />
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { isTesting } from "discourse-common/config/environment";
|
||||
import { action } from "@ember/object";
|
||||
import Component from "@glimmer/component";
|
||||
import I18n from "I18n";
|
||||
import optionalService from "discourse/lib/optional-service";
|
||||
import { action } from "@ember/object";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { cancel, schedule } from "@ember/runloop";
|
||||
import { inject as service } from "@ember/service";
|
||||
@@ -260,7 +260,21 @@ export default class ChatMessage extends Component {
|
||||
return (
|
||||
this.args.context === MESSAGE_CONTEXT_THREAD ||
|
||||
this.args.message?.inReplyTo?.id ===
|
||||
this.args.message?.previousMessage?.id
|
||||
this.args.message?.previousMessage?.id ||
|
||||
this.threadingEnabled
|
||||
);
|
||||
}
|
||||
|
||||
get threadingEnabled() {
|
||||
return this.args.channel?.threadingEnabled && this.args.message?.threadId;
|
||||
}
|
||||
|
||||
get showThreadIndicator() {
|
||||
return (
|
||||
this.args.context !== MESSAGE_CONTEXT_THREAD &&
|
||||
this.threadingEnabled &&
|
||||
this.args.message?.threadId !==
|
||||
this.args.message?.previousMessage?.threadId
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,14 +120,6 @@ export default class ChatMessageInteractor {
|
||||
);
|
||||
}
|
||||
|
||||
get canOpenThread() {
|
||||
return (
|
||||
this.context !== MESSAGE_CONTEXT_THREAD &&
|
||||
this.message.channel?.threadingEnabled &&
|
||||
this.message?.threadId
|
||||
);
|
||||
}
|
||||
|
||||
get canRebakeMessage() {
|
||||
return (
|
||||
this.currentUser?.staff &&
|
||||
@@ -212,14 +204,6 @@ export default class ChatMessageInteractor {
|
||||
});
|
||||
}
|
||||
|
||||
if (this.canOpenThread) {
|
||||
buttons.push({
|
||||
id: "openThread",
|
||||
name: I18n.t("chat.threads.open"),
|
||||
icon: "puzzle-piece",
|
||||
});
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
@@ -364,15 +348,6 @@ export default class ChatMessageInteractor {
|
||||
this.composer.editButtonClicked(this.message.id);
|
||||
}
|
||||
|
||||
@action
|
||||
openThread() {
|
||||
this.router.transitionTo(
|
||||
"chat.channel.thread",
|
||||
...this.message.channel.routeModels,
|
||||
this.message.threadId
|
||||
);
|
||||
}
|
||||
|
||||
@action
|
||||
openEmojiPicker(_, { target }) {
|
||||
const pickerState = {
|
||||
|
||||
@@ -31,6 +31,7 @@ export default class ChatMessage {
|
||||
@tracked excerpt;
|
||||
@tracked message;
|
||||
@tracked threadId;
|
||||
@tracked threadReplyCount;
|
||||
@tracked reactions;
|
||||
@tracked reviewableId;
|
||||
@tracked user;
|
||||
@@ -59,6 +60,7 @@ export default class ChatMessage {
|
||||
this.availableFlags = args.availableFlags || args.available_flags;
|
||||
this.hidden = args.hidden;
|
||||
this.threadId = args.threadId || args.thread_id;
|
||||
this.threadReplyCount = args.threadReplyCount || args.thread_reply_count;
|
||||
this.channelId = args.channelId || args.chat_channel_id;
|
||||
this.chatWebhookEvent = args.chatWebhookEvent || args.chat_webhook_event;
|
||||
this.createdAt = args.createdAt || args.created_at;
|
||||
@@ -81,6 +83,10 @@ export default class ChatMessage {
|
||||
this.bookmark = args.bookmark ? Bookmark.create(args.bookmark) : null;
|
||||
}
|
||||
|
||||
get threadRouteModels() {
|
||||
return [...this.channel.routeModels, this.threadId];
|
||||
}
|
||||
|
||||
get read() {
|
||||
return this.channel.currentUserMembership?.last_read_message_id >= this.id;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user