diff --git a/plugins/chat/app/services/chat/publisher.rb b/plugins/chat/app/services/chat/publisher.rb
index 5d5a39bdadd..b463dd3b8b8 100644
--- a/plugins/chat/app/services/chat/publisher.rb
+++ b/plugins/chat/app/services/chat/publisher.rb
@@ -393,7 +393,8 @@ module Chat
cannot_chat_users,
without_membership,
too_many_members,
- mentions_disabled
+ mentions_disabled,
+ global_mentions_disabled
)
MessageBus.publish(
"/chat/#{chat_message.chat_channel_id}",
@@ -405,6 +406,7 @@ module Chat
without_membership.map { |u| { username: u.username, id: u.id } }.as_json,
groups_with_too_many_members: too_many_members.map(&:name).as_json,
group_mentions_disabled: mentions_disabled.map(&:name).as_json,
+ global_mentions_disabled: global_mentions_disabled,
},
user_ids: [user_id],
)
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-composer.js b/plugins/chat/assets/javascripts/discourse/components/chat-composer.js
index 246736584e0..0e54b5f6dcf 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-composer.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-composer.js
@@ -98,6 +98,7 @@ export default class ChatComposer extends Component {
this.cancelPersistDraft();
this.composer.textarea.value = this.currentMessage.message;
this.persistDraft();
+ this.captureMentions({ skipDebounce: true });
}
@action
@@ -372,11 +373,14 @@ export default class ChatComposer extends Component {
}
@action
- captureMentions() {
+ captureMentions(opts = { skipDebounce: false }) {
if (this.hasContent) {
this.chatComposerWarningsTracker.trackMentions(
- this.currentMessage.message
+ this.currentMessage,
+ opts.skipDebounce
);
+ } else {
+ this.chatComposerWarningsTracker.reset();
}
}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.hbs
index c02e048596d..52a17d19235 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.hbs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.hbs
@@ -11,6 +11,11 @@
{{#if this.hasTooManyMentions}}
{{this.tooManyMentionsBody}}
{{else}}
+ {{#if this.channelWideMentionDisallowed}}
+ {{i18n
+ "chat.mention_warning.channel_wide_mentions_disallowed"
+ }}
+ {{/if}}
{{#if this.hasUnreachableGroupMentions}}
{{this.unreachableBody}}
{{/if}}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.js b/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.js
index 24592fec121..d7811739ca9 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.js
@@ -21,6 +21,10 @@ export default class ChatMentionWarnings extends Component {
return this.chatComposerWarningsTracker.tooManyMentions;
}
+ get channelWideMentionDisallowed() {
+ return this.chatComposerWarningsTracker.channelWideMentionDisallowed;
+ }
+
get mentionsCount() {
return this.chatComposerWarningsTracker.mentionsCount;
}
@@ -50,6 +54,7 @@ export default class ChatMentionWarnings extends Component {
get show() {
return (
this.hasTooManyMentions ||
+ this.channelWideMentionDisallowed ||
this.hasUnreachableGroupMentions ||
this.hasOverMembersLimitGroupMentions
);
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/message/mention-warning.hbs b/plugins/chat/assets/javascripts/discourse/components/chat/message/mention-warning.hbs
index 705e809fb29..eb4b33e4bee 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat/message/mention-warning.hbs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/message/mention-warning.hbs
@@ -51,6 +51,12 @@
{{this.groupsWithTooManyMembers}}
{{/if}}
+
+ {{#if this.mentionWarning.globalMentionsDisabled}}
+
+ {{i18n "chat.mention_warning.channel_wide_mentions_disallowed"}}
+
+ {{/if}}
{{/if}}
{{/if}}
\ No newline at end of file
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/message/mention-warning.js b/plugins/chat/assets/javascripts/discourse/components/chat/message/mention-warning.js
index ae2849da2c4..5f787646328 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat/message/mention-warning.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/message/mention-warning.js
@@ -38,7 +38,8 @@ export default class ChatMessageMentionWarning extends Component {
(this.mentionWarning.groupWithMentionsDisabled?.length ||
this.mentionWarning.cannotSee?.length ||
this.mentionWarning.withoutMembership?.length ||
- this.mentionWarning.groupsWithTooManyMembers?.length)
+ this.mentionWarning.groupsWithTooManyMembers?.length ||
+ this.mentionWarning.globalMentionsDisabled)
);
}
diff --git a/plugins/chat/assets/javascripts/discourse/models/chat-message-mention-warning.js b/plugins/chat/assets/javascripts/discourse/models/chat-message-mention-warning.js
index 0aec8f7e16e..e837edd4a9b 100644
--- a/plugins/chat/assets/javascripts/discourse/models/chat-message-mention-warning.js
+++ b/plugins/chat/assets/javascripts/discourse/models/chat-message-mention-warning.js
@@ -10,6 +10,7 @@ export default class ChatMessageMentionWarning {
@tracked withoutMembership;
@tracked groupsWithTooManyMembers;
@tracked groupWithMentionsDisabled;
+ @tracked globalMentionsDisabled;
constructor(message, args = {}) {
this.message = args.message;
@@ -17,5 +18,6 @@ export default class ChatMessageMentionWarning {
this.withoutMembership = args.without_membership;
this.groupsWithTooManyMembers = args.groups_with_too_many_members;
this.groupWithMentionsDisabled = args.group_mentions_disabled;
+ this.globalMentionsDisabled = args.global_mentions_disabled;
}
}
diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-composer-warnings-tracker.js b/plugins/chat/assets/javascripts/discourse/services/chat-composer-warnings-tracker.js
index 165d327729d..43a8d4adaad 100644
--- a/plugins/chat/assets/javascripts/discourse/services/chat-composer-warnings-tracker.js
+++ b/plugins/chat/assets/javascripts/discourse/services/chat-composer-warnings-tracker.js
@@ -21,6 +21,7 @@ export default class ChatComposerWarningsTracker extends Service {
@tracked unreachableGroupMentions = [];
@tracked overMembersLimitGroupMentions = [];
@tracked tooManyMentions = false;
+ @tracked channelWideMentionDisallowed = false;
@tracked mentionsCount = 0;
@tracked mentionsTimer = null;
@@ -32,22 +33,37 @@ export default class ChatComposerWarningsTracker extends Service {
}
@bind
- trackMentions(message) {
+ reset() {
+ this.unreachableGroupMentions = [];
+ this.unreachableGroupMentions = [];
+ this.overMembersLimitGroupMentions = [];
+ this.tooManyMentions = false;
+ this.channelWideMentionDisallowed = false;
+ this.mentionsCount = 0;
+ cancel(this.mentionsTimer);
+ }
+
+ @bind
+ trackMentions(currentMessage, skipDebounce) {
+ if (skipDebounce) {
+ return this._trackMentions(currentMessage);
+ }
+
this.mentionsTimer = discourseDebounce(
this,
this._trackMentions,
- message,
+ currentMessage,
MENTION_DEBOUNCE_MS
);
}
@bind
- _trackMentions(message) {
+ _trackMentions(currentMessage) {
if (!this.siteSettings.enable_mentions) {
return;
}
- const mentions = this._extractMentions(message);
+ const mentions = this._extractMentions(currentMessage.message);
this.mentionsCount = mentions?.length;
if (this.mentionsCount > 0) {
@@ -59,6 +75,10 @@ export default class ChatComposerWarningsTracker extends Service {
(mention) => !(mention in this._mentionWarningsSeen)
);
+ this.channelWideMentionDisallowed =
+ !currentMessage.channel.allowChannelWideMentions &&
+ (mentions.includes("here") || mentions.includes("all"));
+
if (newMentions?.length > 0) {
this._recordNewWarnings(newMentions, mentions);
} else {
@@ -67,6 +87,7 @@ export default class ChatComposerWarningsTracker extends Service {
}
} else {
this.tooManyMentions = false;
+ this.channelWideMentionDisallowed = false;
this.unreachableGroupMentions = [];
this.overMembersLimitGroupMentions = [];
}
diff --git a/plugins/chat/config/locales/client.en.yml b/plugins/chat/config/locales/client.en.yml
index e47267add2a..7407013ceb8 100644
--- a/plugins/chat/config/locales/client.en.yml
+++ b/plugins/chat/config/locales/client.en.yml
@@ -146,6 +146,7 @@ en:
group_mentions_disabled_multiple:
one: "%{group_name} and %{count} other group don't allow mentions."
other: "%{group_name} and %{count} other groups don't allow mentions."
+ channel_wide_mentions_disallowed: "@here and @all mentions are disabled in this channel."
too_many_members: "%{group_name} has too many members. No one was notified."
too_many_members_multiple:
one: "%{group_name} and %{count} other group have too many members. No one was notified."
diff --git a/plugins/chat/lib/chat/notifier.rb b/plugins/chat/lib/chat/notifier.rb
index 052d222b4da..32c6c746f8b 100644
--- a/plugins/chat/lib/chat/notifier.rb
+++ b/plugins/chat/lib/chat/notifier.rb
@@ -228,7 +228,7 @@ module Chat
group_mentions_disabled = @parsed_mentions.groups_with_disabled_mentions.to_a
too_many_members = @parsed_mentions.groups_with_too_many_members.to_a
if inaccessible.values.all?(&:blank?) && group_mentions_disabled.empty? &&
- too_many_members.empty?
+ too_many_members.empty? && !global_mentions_disabled
return
end
@@ -239,9 +239,19 @@ module Chat
inaccessible[:welcome_to_join].to_a,
too_many_members,
group_mentions_disabled,
+ global_mentions_disabled,
)
end
+ def global_mentions_disabled
+ return @global_mentions_disabled if defined?(@global_mentions_disabled)
+
+ @global_mentions_disabled =
+ (@parsed_mentions.has_global_mention || @parsed_mentions.has_here_mention) &&
+ !@chat_channel.allow_channel_wide_mentions
+ @global_mentions_disabled
+ end
+
# Filters out users from global, here, group, and direct mentions that are
# ignoring or muting the creator of the message, so they will not receive
# a notification via the Jobs::Chat::NotifyMentioned job and are not prompted for
diff --git a/plugins/chat/spec/lib/chat/notifier_spec.rb b/plugins/chat/spec/lib/chat/notifier_spec.rb
index f892bcca6a4..e0af4a70e7d 100644
--- a/plugins/chat/spec/lib/chat/notifier_spec.rb
+++ b/plugins/chat/spec/lib/chat/notifier_spec.rb
@@ -58,6 +58,22 @@ describe Chat::Notifier do
expect(to_notify[list_key]).to be_empty
end
+ it "will publish a mention warning" do
+ channel.update!(allow_channel_wide_mentions: false)
+ msg = build_cooked_msg(mention, user_1)
+
+ messages =
+ MessageBus.track_publish("/chat/#{channel.id}") do
+ to_notify = described_class.new(msg, msg.created_at).notify_new
+ end
+
+ global_mentions_disabled_message = messages.first
+
+ expect(global_mentions_disabled_message).to be_present
+ expect(global_mentions_disabled_message.data[:type].to_sym).to eq(:mention_warning)
+ expect(global_mentions_disabled_message.data[:global_mentions_disabled]).to eq(true)
+ end
+
it "includes all members of a channel except the sender" do
msg = build_cooked_msg(mention, user_1)
diff --git a/plugins/chat/spec/system/mention_warnings_spec.rb b/plugins/chat/spec/system/mention_warnings_spec.rb
index 530c68c2909..20ce8fd79a8 100644
--- a/plugins/chat/spec/system/mention_warnings_spec.rb
+++ b/plugins/chat/spec/system/mention_warnings_spec.rb
@@ -3,12 +3,13 @@
RSpec.describe "Mentions warnings", type: :system do
fab!(:current_user) { Fabricate(:user) }
fab!(:channel_1) { Fabricate(:chat_channel) }
+ fab!(:channel_2) { Fabricate(:chat_channel) }
let(:chat_page) { PageObjects::Pages::Chat.new }
let(:chat_channel_page) { PageObjects::Pages::ChatChannel.new }
before do
- chat_system_bootstrap(current_user, [channel_1])
+ chat_system_bootstrap(current_user, [channel_1, channel_2])
sign_in(current_user)
end
@@ -69,5 +70,42 @@ RSpec.describe "Mentions warnings", type: :system do
end
end
end
+
+ context "when channel has allow_channel_wide_mentions disabled" do
+ before { channel_1.update(allow_channel_wide_mentions: false) }
+
+ %w[@here @all].each do |mention_text|
+ it "displays a warning" do
+ chat_page.visit_channel(channel_1)
+ chat_channel_page.type_in_composer(mention_text)
+
+ expect(page).to have_css(".chat-mention-warnings")
+ expect(page.find(".chat-mention-warnings-list__simple")).to be_present
+ end
+ end
+
+ it "retains warnings when loading drafts or changing channels with no draft" do
+ Chat::Draft.create!(
+ chat_channel: channel_1,
+ user: current_user,
+ data: { message: "@all" }.to_json,
+ )
+ chat_page.visit_channel(channel_1)
+
+ # Channel 1 has a draft that causes a mention warning. Should appear on load
+ expect(page).to have_css(".chat-mention-warnings")
+ expect(page.find(".chat-mention-warnings-list__simple")).to be_present
+
+ # Channel 2 doesn't have a draft so it should disappear
+ chat_page.visit_channel(channel_2)
+ expect(page).to have_no_css(".chat-mention-warnings")
+
+ # Navigating back to channel 1 will make the mention warnings appear b/c the draft
+ # will trigger the @all mention warning again
+ chat_page.visit_channel(channel_1)
+ expect(page).to have_css(".chat-mention-warnings")
+ expect(page.find(".chat-mention-warnings-list__simple")).to be_present
+ end
+ end
end
end
diff --git a/plugins/chat/test/javascripts/components/chat-message-mention-warning-test.js b/plugins/chat/test/javascripts/components/chat-message-mention-warning-test.js
index 35af421d57f..9159b29410d 100644
--- a/plugins/chat/test/javascripts/components/chat-message-mention-warning-test.js
+++ b/plugins/chat/test/javascripts/components/chat-message-mention-warning-test.js
@@ -98,5 +98,21 @@ module(
)
.exists();
});
+
+ test("displays a warning when global mentions are disabled", async function (assert) {
+ this.message = fabricators.message();
+ this.message.mentionWarning = fabricators.messageMentionWarning(
+ this.message,
+ {
+ global_mentions_disabled: true,
+ }
+ );
+
+ await render(template);
+
+ assert
+ .dom(".chat-message-mention-warning__text.-global-mentions-disabled")
+ .exists();
+ });
}
);