+
{{else}}
-
+
{{/if}}
- {{#unless this.hideUserInfo}}
-
- {{/unless}}
+
{{#if @message.reactions.length}}
- {{#if this.reactionLabel}}
-
- {{replace-emoji this.reactionLabel}}
-
- {{/if}}
-
{{#each @message.reactions as |reaction|}}
{{/each}}
- {{#if this.chat.userCanInteractWithChat}}
- {{#unless this.site.mobileView}}
-
- {{/unless}}
+ {{#if this.shouldRenderOpenEmojiPickerButton}}
+
{{/if}}
{{/if}}
- {{#if @message.error}}
-
- {{#if (eq @message.error "network_error")}}
-
-
- {{i18n "chat.retry_staged_message.title"}}
-
-
- {{i18n "chat.retry_staged_message.action"}}
-
-
- {{else}}
- {{@message.error}}
- {{/if}}
-
- {{/if}}
-
- {{#if this.mentionWarning}}
-
- {{#if this.mentionWarning.invitation_sent}}
- {{d-icon "check"}}
-
- {{i18n
- "chat.mention_warning.invitations_sent"
- count=this.mentionWarning.without_membership.length
- }}
-
- {{else}}
-
-
- {{#if this.mentionWarning.cannot_see}}
-
- {{this.mentionedCannotSeeText}}
-
- {{/if}}
-
- {{#if this.mentionWarning.without_membership}}
-
- {{this.mentionedWithoutMembershipText}}
-
- {{i18n "chat.mention_warning.invite"}}
-
-
- {{/if}}
- {{#if this.mentionWarning.group_mentions_disabled}}
-
- {{this.groupsWithDisabledMentions}}
-
- {{/if}}
-
- {{#if this.mentionWarning.groups_with_too_many_members}}
-
- {{this.groupsWithTooManyMembers}}
-
- {{/if}}
- {{/if}}
-
- {{/if}}
+
+
{{#if this.showThreadIndicator}}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message.js b/plugins/chat/assets/javascripts/discourse/components/chat-message.js
index 0b074707dc6..1fa0d20550d 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-message.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-message.js
@@ -2,7 +2,6 @@ import { action } from "@ember/object";
import Component from "@glimmer/component";
import I18n from "I18n";
import optionalService from "discourse/lib/optional-service";
-import { ajax } from "discourse/lib/ajax";
import { cancel, schedule } from "@ember/runloop";
import { inject as service } from "@ember/service";
import discourseLater from "discourse-common/lib/later";
@@ -101,6 +100,10 @@ export default class ChatMessage extends Component {
);
}
+ get shouldRenderOpenEmojiPickerButton() {
+ return this.chat.userCanInteractWithChat && this.site.desktopView;
+ }
+
@action
expand() {
const recursiveExpand = (message) => {
@@ -386,82 +389,6 @@ export default class ChatMessage extends Component {
);
}
- get mentionWarning() {
- return this.args.message.mentionWarning;
- }
-
- get mentionedCannotSeeText() {
- return this._findTranslatedWarning(
- "chat.mention_warning.cannot_see",
- "chat.mention_warning.cannot_see_multiple",
- {
- username: this.mentionWarning?.cannot_see?.[0]?.username,
- count: this.mentionWarning?.cannot_see?.length,
- }
- );
- }
-
- get mentionedWithoutMembershipText() {
- return this._findTranslatedWarning(
- "chat.mention_warning.without_membership",
- "chat.mention_warning.without_membership_multiple",
- {
- username: this.mentionWarning?.without_membership?.[0]?.username,
- count: this.mentionWarning?.without_membership?.length,
- }
- );
- }
-
- get groupsWithDisabledMentions() {
- return this._findTranslatedWarning(
- "chat.mention_warning.group_mentions_disabled",
- "chat.mention_warning.group_mentions_disabled_multiple",
- {
- group_name: this.mentionWarning?.group_mentions_disabled?.[0],
- count: this.mentionWarning?.group_mentions_disabled?.length,
- }
- );
- }
-
- get groupsWithTooManyMembers() {
- return this._findTranslatedWarning(
- "chat.mention_warning.too_many_members",
- "chat.mention_warning.too_many_members_multiple",
- {
- group_name: this.mentionWarning.groups_with_too_many_members?.[0],
- count: this.mentionWarning.groups_with_too_many_members?.length,
- }
- );
- }
-
- _findTranslatedWarning(oneKey, multipleKey, args) {
- const translationKey = args.count === 1 ? oneKey : multipleKey;
- args.count--;
- return I18n.t(translationKey, args);
- }
-
- @action
- inviteMentioned() {
- const userIds = this.mentionWarning.without_membership.mapBy("id");
-
- ajax(`/chat/${this.args.message.channel.id}/invite`, {
- method: "PUT",
- data: { user_ids: userIds, chat_message_id: this.args.message.id },
- }).then(() => {
- this.args.message.mentionWarning.set("invitationSent", true);
- this._invitationSentTimer = discourseLater(() => {
- this.dismissMentionWarning();
- }, 3000);
- });
-
- return false;
- }
-
- @action
- dismissMentionWarning() {
- this.args.message.mentionWarning = null;
- }
-
#teardownMentionedUsers() {
this.args.message.mentionedUsers.forEach((user) => {
user.stopTrackingStatus();
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-thread.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-thread.hbs
index 24725e3ed9f..ec61c01b0a3 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-thread.hbs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-thread.hbs
@@ -27,8 +27,6 @@
{{/each}}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-thread.js b/plugins/chat/assets/javascripts/discourse/components/chat-thread.js
index 45d968957ed..48ba6eb2d40 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-thread.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-thread.js
@@ -348,16 +348,6 @@ export default class ChatThreadPanel extends Component {
@action
resendStagedMessage() {}
- @action
- messageDidEnterViewport(message) {
- message.visible = true;
- }
-
- @action
- messageDidLeaveViewport(message) {
- message.visible = false;
- }
-
#handleErrors(error) {
switch (error?.jqXHR?.status) {
case 429:
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message-avatar.hbs b/plugins/chat/assets/javascripts/discourse/components/chat/message/avatar.hbs
similarity index 100%
rename from plugins/chat/assets/javascripts/discourse/components/chat-message-avatar.hbs
rename to plugins/chat/assets/javascripts/discourse/components/chat/message/avatar.hbs
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/message/error.hbs b/plugins/chat/assets/javascripts/discourse/components/chat/message/error.hbs
new file mode 100644
index 00000000000..dc9ca63b24a
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/message/error.hbs
@@ -0,0 +1,20 @@
+{{#if @message.error}}
+
+ {{#if (eq @message.error "network_error")}}
+
+
+ {{i18n "chat.retry_staged_message.title"}}
+
+
+ {{i18n "chat.retry_staged_message.action"}}
+
+
+ {{else}}
+ {{@message.error}}
+ {{/if}}
+
+{{/if}}
\ No newline at end of file
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/message/info.hbs b/plugins/chat/assets/javascripts/discourse/components/chat/message/info.hbs
new file mode 100644
index 00000000000..3ccf1f6adb5
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/message/info.hbs
@@ -0,0 +1,63 @@
+{{#if @show}}
+
+ {{#if @message.chatWebhookEvent}}
+ {{#if @message.chatWebhookEvent.username}}
+
+ {{@message.chatWebhookEvent.username}}
+
+ {{/if}}
+
+
+ {{i18n "chat.bot"}}
+
+ {{else}}
+
+ {{this.name}}
+ {{#if this.showStatus}}
+
+
+
+ {{/if}}
+
+ {{/if}}
+
+
+ {{format-chat-date @message}}
+
+
+ {{#if @message.bookmark}}
+
+
+
+ {{/if}}
+
+ {{#if this.isFlagged}}
+
+ {{#if @message.reviewableId}}
+
+ {{d-icon "flag" title="chat.flagged"}}
+
+ {{else}}
+ {{d-icon "flag" title="chat.you_flagged"}}
+ {{/if}}
+
+ {{/if}}
+
+{{/if}}
\ No newline at end of file
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message-info.js b/plugins/chat/assets/javascripts/discourse/components/chat/message/info.js
similarity index 100%
rename from plugins/chat/assets/javascripts/discourse/components/chat-message-info.js
rename to plugins/chat/assets/javascripts/discourse/components/chat/message/info.js
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message-left-gutter.hbs b/plugins/chat/assets/javascripts/discourse/components/chat/message/left-gutter.hbs
similarity index 100%
rename from plugins/chat/assets/javascripts/discourse/components/chat-message-left-gutter.hbs
rename to plugins/chat/assets/javascripts/discourse/components/chat/message/left-gutter.hbs
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message-left-gutter.js b/plugins/chat/assets/javascripts/discourse/components/chat/message/left-gutter.js
similarity index 100%
rename from plugins/chat/assets/javascripts/discourse/components/chat-message-left-gutter.js
rename to plugins/chat/assets/javascripts/discourse/components/chat/message/left-gutter.js
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
new file mode 100644
index 00000000000..705e809fb29
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/message/mention-warning.hbs
@@ -0,0 +1,56 @@
+{{#if this.shouldRender}}
+
+ {{#if this.mentionWarning.invitationSent}}
+
+ {{d-icon "check"}}
+
+ {{i18n
+ "chat.mention_warning.invitations_sent"
+ count=this.mentionWarning.withoutMembership.length
+ }}
+
+
+ {{else}}
+
+
+ {{#if this.mentionWarning.cannotSee}}
+
+ {{this.mentionedCannotSeeText}}
+
+ {{/if}}
+
+ {{#if this.mentionWarning.withoutMembership}}
+
+ {{this.mentionedWithoutMembershipText}}
+
+ {{i18n "chat.mention_warning.invite"}}
+
+
+ {{/if}}
+
+ {{#if this.mentionWarning.groupWithMentionsDisabled}}
+
+ {{this.groupsWithDisabledMentions}}
+
+ {{/if}}
+
+ {{#if this.mentionWarning.groupsWithTooManyMembers}}
+
+ {{this.groupsWithTooManyMembers}}
+
+ {{/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
new file mode 100644
index 00000000000..ae2849da2c4
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/message/mention-warning.js
@@ -0,0 +1,98 @@
+import Component from "@glimmer/component";
+import { action } from "@ember/object";
+import { popupAjaxError } from "discourse/lib/ajax-error";
+import { inject as service } from "@ember/service";
+import I18n from "I18n";
+
+export default class ChatMessageMentionWarning extends Component {
+ @service("chat-api") api;
+
+ @action
+ async onSendInvite() {
+ const userIds = this.mentionWarning.withoutMembership.mapBy("id");
+
+ try {
+ await this.api.invite(this.args.message.channel.id, userIds, {
+ messageId: this.args.message.id,
+ });
+
+ this.mentionWarning.invitationSent = true;
+ } catch (error) {
+ popupAjaxError(error);
+ }
+ }
+
+ @action
+ onDismissInvitationSent() {
+ this.mentionWarning.invitationSent = false;
+ }
+
+ @action
+ onDismissMentionWarning() {
+ this.args.message.mentionWarning = null;
+ }
+
+ get shouldRender() {
+ return (
+ this.mentionWarning &&
+ (this.mentionWarning.groupWithMentionsDisabled?.length ||
+ this.mentionWarning.cannotSee?.length ||
+ this.mentionWarning.withoutMembership?.length ||
+ this.mentionWarning.groupsWithTooManyMembers?.length)
+ );
+ }
+
+ get mentionWarning() {
+ return this.args.message.mentionWarning;
+ }
+
+ get mentionedCannotSeeText() {
+ return this.#findTranslatedWarning(
+ "chat.mention_warning.cannot_see",
+ "chat.mention_warning.cannot_see_multiple",
+ {
+ username: this.mentionWarning?.cannotSee?.[0]?.username,
+ count: this.mentionWarning?.cannotSee?.length,
+ }
+ );
+ }
+
+ get mentionedWithoutMembershipText() {
+ return this.#findTranslatedWarning(
+ "chat.mention_warning.without_membership",
+ "chat.mention_warning.without_membership_multiple",
+ {
+ username: this.mentionWarning?.withoutMembership?.[0]?.username,
+ count: this.mentionWarning?.withoutMembership?.length,
+ }
+ );
+ }
+
+ get groupsWithDisabledMentions() {
+ return this.#findTranslatedWarning(
+ "chat.mention_warning.group_mentions_disabled",
+ "chat.mention_warning.group_mentions_disabled_multiple",
+ {
+ group_name: this.mentionWarning?.groupWithMentionsDisabled?.[0],
+ count: this.mentionWarning?.groupWithMentionsDisabled?.length,
+ }
+ );
+ }
+
+ get groupsWithTooManyMembers() {
+ return this.#findTranslatedWarning(
+ "chat.mention_warning.too_many_members",
+ "chat.mention_warning.too_many_members_multiple",
+ {
+ group_name: this.mentionWarning.groupsWithTooManyMembers?.[0],
+ count: this.mentionWarning.groupsWithTooManyMembers?.length,
+ }
+ );
+ }
+
+ #findTranslatedWarning(oneKey, multipleKey, args) {
+ const translationKey = args.count === 1 ? oneKey : multipleKey;
+ args.count--;
+ return I18n.t(translationKey, args);
+ }
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/styleguide/chat-message-mention-warning.hbs b/plugins/chat/assets/javascripts/discourse/components/styleguide/chat-message-mention-warning.hbs
new file mode 100644
index 00000000000..76a5d861bb2
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/styleguide/chat-message-mention-warning.hbs
@@ -0,0 +1,35 @@
+
">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/chat/assets/javascripts/discourse/components/styleguide/chat-message-mention-warning.js b/plugins/chat/assets/javascripts/discourse/components/styleguide/chat-message-mention-warning.js
new file mode 100644
index 00000000000..4b22bae1138
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/styleguide/chat-message-mention-warning.js
@@ -0,0 +1,75 @@
+import Component from "@glimmer/component";
+import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
+import { action } from "@ember/object";
+import { inject as service } from "@ember/service";
+
+export default class ChatMessageMentionWarning extends Component {
+ @service currentUser;
+
+ constructor() {
+ super(...arguments);
+ this.message = fabricators.message({ user: this.currentUser });
+ }
+
+ @action
+ toggleCannotSee() {
+ if (this.message.mentionWarning?.cannotSee) {
+ this.message.mentionWarning = null;
+ } else {
+ this.message.mentionWarning = fabricators.messageMentionWarning(
+ this.message,
+ {
+ cannot_see: [fabricators.user({ username: "bob" })].map((u) => {
+ return { username: u.username, id: u.id };
+ }),
+ }
+ );
+ }
+ }
+
+ @action
+ toggleGroupWithMentionsDisabled() {
+ if (this.message.mentionWarning?.groupWithMentionsDisabled) {
+ this.message.mentionWarning = null;
+ } else {
+ this.message.mentionWarning = fabricators.messageMentionWarning(
+ this.message,
+ {
+ group_mentions_disabled: [fabricators.group()].mapBy("name"),
+ }
+ );
+ }
+ }
+
+ @action
+ toggleGroupsWithTooManyMembers() {
+ if (this.message.mentionWarning?.groupsWithTooManyMembers) {
+ this.message.mentionWarning = null;
+ } else {
+ this.message.mentionWarning = fabricators.messageMentionWarning(
+ this.message,
+ {
+ groups_with_too_many_members: [
+ fabricators.group(),
+ fabricators.group({ name: "Moderators" }),
+ ].mapBy("name"),
+ }
+ );
+ }
+ }
+ @action
+ toggleWithoutMembership() {
+ if (this.message.mentionWarning?.withoutMembership) {
+ this.message.mentionWarning = null;
+ } else {
+ this.message.mentionWarning = fabricators.messageMentionWarning(
+ this.message,
+ {
+ without_membership: [fabricators.user()].map((u) => {
+ return { username: u.username, id: u.id };
+ }),
+ }
+ );
+ }
+ }
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/styleguide/chat-message.hbs b/plugins/chat/assets/javascripts/discourse/components/styleguide/chat-message.hbs
index cfeffcc007a..58b6f536db6 100644
--- a/plugins/chat/assets/javascripts/discourse/components/styleguide/chat-message.hbs
+++ b/plugins/chat/assets/javascripts/discourse/components/styleguide/chat-message.hbs
@@ -1,11 +1,6 @@
">
-
+
diff --git a/plugins/chat/assets/javascripts/discourse/components/styleguide/organisms/chat.hbs b/plugins/chat/assets/javascripts/discourse/components/styleguide/organisms/chat.hbs
index 34b4dd020db..d37a61138f9 100644
--- a/plugins/chat/assets/javascripts/discourse/components/styleguide/organisms/chat.hbs
+++ b/plugins/chat/assets/javascripts/discourse/components/styleguide/organisms/chat.hbs
@@ -2,4 +2,5 @@
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/plugins/chat/assets/javascripts/discourse/lib/fabricators.js b/plugins/chat/assets/javascripts/discourse/lib/fabricators.js
index dc8aff12369..3b90bd00037 100644
--- a/plugins/chat/assets/javascripts/discourse/lib/fabricators.js
+++ b/plugins/chat/assets/javascripts/discourse/lib/fabricators.js
@@ -13,10 +13,12 @@ import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
import ChatThread from "discourse/plugins/chat/discourse/models/chat-thread";
import ChatThreadPreview from "discourse/plugins/chat/discourse/models/chat-thread-preview";
import ChatDirectMessage from "discourse/plugins/chat/discourse/models/chat-direct-message";
+import ChatMessageMentionWarning from "discourse/plugins/chat/discourse/models/chat-message-mention-warning";
import ChatMessageReaction from "discourse/plugins/chat/discourse/models/chat-message-reaction";
import User from "discourse/models/user";
import Bookmark from "discourse/models/bookmark";
import Category from "discourse/models/category";
+import Group from "discourse/models/group";
let sequence = 0;
@@ -145,6 +147,16 @@ function reactionFabricator(args = {}) {
});
}
+function groupFabricator(args = {}) {
+ return Group.create({
+ name: args.name || "Engineers",
+ });
+}
+
+function messageMentionWarningFabricator(message, args = {}) {
+ return ChatMessageMentionWarning.create(message, args);
+}
+
function uploadFabricator() {
return {
extension: "jpeg",
@@ -175,4 +187,6 @@ export default {
upload: uploadFabricator,
category: categoryFabricator,
directMessage: directMessageFabricator,
+ messageMentionWarning: messageMentionWarningFabricator,
+ group: groupFabricator,
};
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
new file mode 100644
index 00000000000..0aec8f7e16e
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/models/chat-message-mention-warning.js
@@ -0,0 +1,21 @@
+import { tracked } from "@glimmer/tracking";
+
+export default class ChatMessageMentionWarning {
+ static create(message, args = {}) {
+ return new ChatMessageMentionWarning(message, args);
+ }
+
+ @tracked invitationSent = false;
+ @tracked cannotSee;
+ @tracked withoutMembership;
+ @tracked groupsWithTooManyMembers;
+ @tracked groupWithMentionsDisabled;
+
+ constructor(message, args = {}) {
+ this.message = args.message;
+ this.cannotSee = args.cannot_see;
+ this.withoutMembership = args.without_membership;
+ this.groupsWithTooManyMembers = args.groups_with_too_many_members;
+ this.groupWithMentionsDisabled = args.group_mentions_disabled;
+ }
+}
diff --git a/plugins/chat/assets/javascripts/discourse/modifiers/chat/later-fn.js b/plugins/chat/assets/javascripts/discourse/modifiers/chat/later-fn.js
new file mode 100644
index 00000000000..e70651b426b
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/modifiers/chat/later-fn.js
@@ -0,0 +1,21 @@
+import Modifier from "ember-modifier";
+import { registerDestructor } from "@ember/destroyable";
+import { cancel } from "@ember/runloop";
+import discourseLater from "discourse-common/lib/later";
+
+export default class ChatLaterFn extends Modifier {
+ constructor(owner, args) {
+ super(owner, args);
+ registerDestructor(this, (instance) => instance.cleanup());
+ }
+
+ modify(element, [fn, delay]) {
+ this.handler = discourseLater(() => {
+ fn?.(element);
+ }, delay);
+ }
+
+ cleanup() {
+ cancel(this.handler);
+ }
+}
diff --git a/plugins/chat/assets/javascripts/discourse/modifiers/chat/track-message.js b/plugins/chat/assets/javascripts/discourse/modifiers/chat/track-message.js
index 519113ed822..7a67cb08121 100644
--- a/plugins/chat/assets/javascripts/discourse/modifiers/chat/track-message.js
+++ b/plugins/chat/assets/javascripts/discourse/modifiers/chat/track-message.js
@@ -11,9 +11,9 @@ export default class ChatTrackMessage extends Modifier {
registerDestructor(this, (instance) => instance.cleanup());
}
- modify(element, [callbacks = {}]) {
- this.didEnterViewport = callbacks.didEnterViewport;
- this.didLeaveViewport = callbacks.didLeaveViewport;
+ modify(element, [didEnterViewport, didLeaveViewport]) {
+ this.didEnterViewport = didEnterViewport;
+ this.didLeaveViewport = didLeaveViewport;
this.intersectionObserver = new IntersectionObserver(
this._intersectionObserverCallback,
diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-api.js b/plugins/chat/assets/javascripts/discourse/services/chat-api.js
index 059a0dc3edb..d03d7dafef3 100644
--- a/plugins/chat/assets/javascripts/discourse/services/chat-api.js
+++ b/plugins/chat/assets/javascripts/discourse/services/chat-api.js
@@ -460,6 +460,20 @@ export default class ChatApi extends Service {
});
}
+ /**
+ * Invite users to a channel.
+ *
+ * @param {number} channelId - The ID of the channel.
+ * @param {Array} userIds - The IDs of the users to invite.
+ * @param {Array} [messageId] - The ID of a message to highlight when opening the notification.
+ */
+ invite(channelId, userIds, options = {}) {
+ return ajax(`/chat/${channelId}/invite`, {
+ type: "put",
+ data: { user_ids: userIds, chat_message_id: options.messageId },
+ });
+ }
+
get #basePath() {
return "/chat/api";
}
diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-pane-base-subscriptions-manager.js b/plugins/chat/assets/javascripts/discourse/services/chat-pane-base-subscriptions-manager.js
index 970dc9cb009..6967c394557 100644
--- a/plugins/chat/assets/javascripts/discourse/services/chat-pane-base-subscriptions-manager.js
+++ b/plugins/chat/assets/javascripts/discourse/services/chat-pane-base-subscriptions-manager.js
@@ -1,6 +1,6 @@
import Service, { inject as service } from "@ember/service";
-import EmberObject from "@ember/object";
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
+import ChatMessageMentionWarning from "discourse/plugins/chat/discourse/models/chat-message-mention-warning";
import { cloneJSON } from "discourse-common/lib/object";
import { bind } from "discourse-common/utils/decorators";
@@ -200,7 +200,7 @@ export default class ChatPaneBaseSubscriptionsManager extends Service {
handleMentionWarning(data) {
const message = this.messagesManager.findMessage(data.chat_message_id);
if (message) {
- message.mentionWarning = EmberObject.create(data);
+ message.mentionWarning = ChatMessageMentionWarning.create(message, data);
}
}
diff --git a/plugins/chat/assets/stylesheets/common/chat-message-error.scss b/plugins/chat/assets/stylesheets/common/chat-message-error.scss
new file mode 100644
index 00000000000..71a40dc4deb
--- /dev/null
+++ b/plugins/chat/assets/stylesheets/common/chat-message-error.scss
@@ -0,0 +1,40 @@
+.chat-message-error {
+ color: var(--danger-medium);
+
+ &__retry-btn {
+ padding: 0.5em 0;
+ background: none;
+
+ &:hover,
+ &:focus,
+ .-active & {
+ background: none !important;
+ }
+
+ &:focus .retry-staged-message-btn__action {
+ text-decoration: underline;
+ }
+
+ .d-icon,
+ &-title,
+ &:hover .d-icon {
+ color: var(--danger) !important;
+ font-size: var(--font-down-1);
+ }
+
+ .d-icon {
+ margin-right: 0.25em !important;
+ }
+
+ &-action {
+ color: var(--tertiary);
+ font-size: var(--font-down-1);
+ margin-left: 0.25em;
+
+ &:hover {
+ color: var(--tertiary-high);
+ text-decoration: underline;
+ }
+ }
+ }
+}
diff --git a/plugins/chat/assets/stylesheets/common/chat-message-mention-warning.scss b/plugins/chat/assets/stylesheets/common/chat-message-mention-warning.scss
new file mode 100644
index 00000000000..4d69f3c9fd1
--- /dev/null
+++ b/plugins/chat/assets/stylesheets/common/chat-message-mention-warning.scss
@@ -0,0 +1,19 @@
+.chat-message-mention-warning {
+ position: relative;
+ margin-top: 0.25rem;
+ font-size: var(--font-down-1);
+
+ &__dismiss-btn {
+ position: absolute;
+ top: 7px;
+ right: 5px;
+ }
+
+ &__text {
+ margin: 0.25rem 0;
+ }
+
+ &__invite-sent {
+ color: var(--tertiary);
+ }
+}
diff --git a/plugins/chat/assets/stylesheets/common/chat-message.scss b/plugins/chat/assets/stylesheets/common/chat-message.scss
index be73c91a8b5..9aa128ae496 100644
--- a/plugins/chat/assets/stylesheets/common/chat-message.scss
+++ b/plugins/chat/assets/stylesheets/common/chat-message.scss
@@ -1,5 +1,5 @@
-.chat-message-deleted,
-.chat-message-hidden {
+.chat-message-text.-deleted,
+.chat-message-text.-hidden {
margin-left: calc(var(--message-left-width) + 0.75em);
padding: 0;
@@ -18,6 +18,12 @@
}
}
+.chat-message-reaction {
+ > * {
+ pointer-events: none;
+ }
+}
+
.chat-message {
align-items: flex-start;
padding: 0.25em 0.5em 0.25em 0.75em;
@@ -26,10 +32,11 @@
.chat-message-reaction {
@include chat-reaction;
- }
+ will-change: scale;
- .not-mobile-device &.deleted:hover {
- background-color: var(--danger-hover);
+ &:active {
+ transform: scale(0.93);
+ }
}
.chat-message-content {
@@ -87,23 +94,16 @@
display: flex;
flex-wrap: wrap;
- .reaction-users-list {
- position: absolute;
- top: -2px;
- transform: translateY(-100%);
- border: 1px solid var(--primary-low);
- border-radius: 6px;
- padding: 0.5em;
- background: var(--primary-very-low);
- max-width: 300px;
- z-index: 3;
- }
-
.chat-message-react-btn {
vertical-align: top;
padding: 0em 0.25em;
background: none;
border: none;
+ will-change: scale;
+
+ &:active {
+ transform: scale(0.93);
+ }
> * {
pointer-events: none;
@@ -121,32 +121,6 @@
}
}
- .chat-send-error {
- color: var(--danger-medium);
- }
-
- .chat-message-mention-warning {
- position: relative;
- margin-top: 0.25em;
- font-size: var(--font-down-1);
-
- .dismiss-mention-warning {
- position: absolute;
- top: 15px;
- right: 5px;
- cursor: pointer;
- }
-
- .warning-item {
- margin: 0.25em 0;
- }
-
- .invite-link {
- color: var(--tertiary);
- cursor: pointer;
- }
- }
-
.chat-message-avatar .chat-user-avatar .chat-user-avatar-container .avatar,
.chat-emoji-avatar .chat-emoji-avatar-container {
width: 28px;
@@ -256,94 +230,3 @@
display: none;
}
}
-
-.has-full-page-chat .chat-message .onebox:not(img),
-.chat-drawer-container .chat-message .onebox {
- margin: 0.5em 0;
- border-width: 2px;
-
- header {
- margin-bottom: 0.5em;
- }
-
- h3 a,
- h4 a {
- font-size: 14px;
- }
-
- pre {
- display: flex;
- max-height: 150px;
- }
-
- p {
- overflow: hidden;
- }
-}
-
-.chat-drawer-container .chat-message .onebox {
- width: 85%;
- border: 2px solid var(--primary-low);
-
- header {
- margin-bottom: 0.5em;
- }
-
- .onebox-body {
- grid-template-rows: auto auto auto;
- overflow: auto;
- }
-
- h3 {
- @include line-clamp(2);
- font-weight: 500;
- font-size: var(--font-down-1);
- }
-
- p {
- display: none;
- }
-}
-
-.chat-message-reaction {
- > * {
- pointer-events: none;
- }
-}
-
-.retry-staged-message-btn {
- padding: 0.5em 0;
- background: none;
-
- &:hover,
- &:focus,
- .-active & {
- background: none !important;
- }
-
- &:focus .retry-staged-message-btn__action {
- text-decoration: underline;
- }
-
- .d-icon,
- &__title,
- &:hover .d-icon {
- color: var(--danger) !important;
- font-size: var(--font-down-1);
- }
-
- .d-icon {
- margin-right: 0.25em !important;
- }
-
- &__action {
- color: var(--tertiary);
- font-size: var(--font-down-1);
- margin-left: 0.25em;
-
- &:hover {
- color: var(--tertiary-high);
- text-decoration: underline;
- }
- }
-}
diff --git a/plugins/chat/assets/stylesheets/common/chat-onebox.scss b/plugins/chat/assets/stylesheets/common/chat-onebox.scss
index c039e7463d4..f57d41a56ff 100644
--- a/plugins/chat/assets/stylesheets/common/chat-onebox.scss
+++ b/plugins/chat/assets/stylesheets/common/chat-onebox.scss
@@ -28,8 +28,50 @@
}
}
-.chat-transcript {
- .chat-transcript-user-avatar .avatar {
- aspect-ratio: 20 / 20;
+.chat-drawer-container .chat-message .onebox {
+ width: 85%;
+ border: 2px solid var(--primary-low);
+
+ header {
+ margin-bottom: 0.5em;
+ }
+
+ .onebox-body {
+ grid-template-rows: auto auto auto;
+ overflow: auto;
+ }
+
+ h3 {
+ @include line-clamp(2);
+ font-weight: 500;
+ font-size: var(--font-down-1);
+ }
+
+ p {
+ display: none;
+ }
+}
+
+.has-full-page-chat .chat-message .onebox:not(img),
+.chat-drawer-container .chat-message .onebox {
+ margin: 0.5em 0;
+ border-width: 2px;
+
+ header {
+ margin-bottom: 0.5em;
+ }
+
+ h3 a,
+ h4 a {
+ font-size: 14px;
+ }
+
+ pre {
+ display: flex;
+ max-height: 150px;
+ }
+
+ p {
+ overflow: hidden;
}
}
diff --git a/plugins/chat/assets/stylesheets/common/chat-transcript.scss b/plugins/chat/assets/stylesheets/common/chat-transcript.scss
index b66d72fcd68..f5b686efebb 100644
--- a/plugins/chat/assets/stylesheets/common/chat-transcript.scss
+++ b/plugins/chat/assets/stylesheets/common/chat-transcript.scss
@@ -53,6 +53,10 @@
}
}
+ .chat-transcript-user-avatar .avatar {
+ aspect-ratio: 20 / 20;
+ }
+
.chat-transcript-user {
display: flex;
flex-wrap: wrap-reverse;
diff --git a/plugins/chat/assets/stylesheets/common/index.scss b/plugins/chat/assets/stylesheets/common/index.scss
index 1873d414de9..c78eb2c6693 100644
--- a/plugins/chat/assets/stylesheets/common/index.scss
+++ b/plugins/chat/assets/stylesheets/common/index.scss
@@ -58,3 +58,5 @@
@import "chat-thread-unread-indicator";
@import "chat-thread-participants";
@import "channel-summary-modal";
+@import "chat-message-mention-warning";
+@import "chat-message-error";
diff --git a/plugins/chat/spec/system/deleted_message_spec.rb b/plugins/chat/spec/system/deleted_message_spec.rb
index 53ec5a9415a..8ffc7bb152e 100644
--- a/plugins/chat/spec/system/deleted_message_spec.rb
+++ b/plugins/chat/spec/system/deleted_message_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe "Deleted message", type: :system do
last_message = find(".chat-message-container:last-child")
channel_page.delete_message(OpenStruct.new(id: last_message["data-id"]))
- expect(channel_page).to have_deleted_message(
+ expect(channel_page.messages).to have_deleted_message(
OpenStruct.new(id: last_message["data-id"]),
count: 1,
)
@@ -40,12 +40,12 @@ RSpec.describe "Deleted message", type: :system do
.update!(last_read_message_id: message.id)
chat_page.visit_channel(channel_1)
channel_page.delete_message(message)
- expect(channel_page).to have_deleted_message(message, count: 1)
+ expect(channel_page.messages).to have_deleted_message(message, count: 1)
sidebar_component.click_link(channel_2.name)
expect(channel_page).to have_no_loading_skeleton
sidebar_component.click_link(channel_1.name)
- expect(channel_page).to have_deleted_message(message, count: 1)
+ expect(channel_page.messages).to have_deleted_message(message, count: 1)
end
context "when the current user is not admin" do
@@ -72,7 +72,7 @@ RSpec.describe "Deleted message", type: :system do
end
sidebar_component.click_link(channel_1.name)
- expect(channel_page).to have_no_message(id: message.id)
+ expect(channel_page.messages).to have_no_message(id: message.id)
end
end
end
@@ -93,10 +93,9 @@ RSpec.describe "Deleted message", type: :system do
channel_page.delete_message(message_4)
channel_page.delete_message(message_6)
- expect(channel_page).to have_deleted_message(message_1)
- expect(channel_page).to have_deleted_message(message_4, count: 2)
- expect(channel_page).to have_deleted_message(message_6)
- expect(channel_page).to have_no_message(id: message_3.id)
+ expect(channel_page.messages).to have_deleted_messages(message_1, message_6)
+ expect(channel_page.messages).to have_deleted_message(message_4, count: 2)
+ expect(channel_page.messages).to have_no_message(id: message_3.id)
end
end
@@ -129,20 +128,20 @@ RSpec.describe "Deleted message", type: :system do
channel_page.message_thread_indicator(thread.original_message).click
expect(side_panel).to have_open_thread(thread)
- expect(channel_page).to have_message(id: message_1.id)
- expect(channel_page).to have_message(id: message_2.id)
- expect(open_thread).to have_message(thread_id: thread.id, id: message_4.id)
- expect(open_thread).to have_message(thread_id: thread.id, id: message_5.id)
+ expect(channel_page.messages).to have_message(id: message_2.id)
+ expect(channel_page.messages).to have_message(id: message_1.id)
+ expect(open_thread.messages).to have_message(thread_id: thread.id, id: message_4.id)
+ expect(open_thread.messages).to have_message(thread_id: thread.id, id: message_5.id)
Chat::Publisher.publish_bulk_delete!(
channel_1,
[message_1.id, message_2.id, message_4.id, message_5.id].flatten,
)
- expect(channel_page).to have_no_message(id: message_1.id)
- expect(channel_page).to have_deleted_message(message_2, count: 2)
- expect(open_thread).to have_no_message(thread_id: thread.id, id: message_4.id)
- expect(open_thread).to have_deleted_message(message_5, count: 2)
+ expect(channel_page.messages).to have_no_message(id: message_1.id)
+ expect(channel_page.messages).to have_deleted_message(message_2, count: 2)
+ expect(open_thread.messages).to have_no_message(thread_id: thread.id, id: message_4.id)
+ expect(open_thread.messages).to have_deleted_message(message_5, count: 2)
end
end
end
diff --git a/plugins/chat/spec/system/move_message_to_channel_spec.rb b/plugins/chat/spec/system/move_message_to_channel_spec.rb
index 73d9c665831..7757b93fcca 100644
--- a/plugins/chat/spec/system/move_message_to_channel_spec.rb
+++ b/plugins/chat/spec/system/move_message_to_channel_spec.rb
@@ -84,11 +84,11 @@ RSpec.describe "Move message to channel", type: :system do
click_button(I18n.t("js.chat.move_to_channel.confirm_move"))
expect(page).to have_current_path(chat.channel_path(channel_2.slug, channel_2.id))
- expect(channel_page).to have_message(text: message_1.message)
+ expect(channel_page.messages).to have_message(text: message_1.message)
chat_page.visit_channel(channel_1)
- expect(channel_page).to have_deleted_message(message_1)
+ expect(channel_page.messages).to have_deleted_message(message_1)
end
end
end
diff --git a/plugins/chat/spec/system/page_objects/chat/chat_channel.rb b/plugins/chat/spec/system/page_objects/chat/chat_channel.rb
index b50f728da56..fd2437d7c01 100644
--- a/plugins/chat/spec/system/page_objects/chat/chat_channel.rb
+++ b/plugins/chat/spec/system/page_objects/chat/chat_channel.rb
@@ -188,13 +188,6 @@ module PageObjects
check_message_presence(exists: false, text: text, id: id)
end
- def has_deleted_message?(message, count: 1)
- has_css?(
- ".chat-channel .chat-message-container[data-id=\"#{message.id}\"] .chat-message-deleted",
- text: I18n.t("js.chat.deleted", count: count),
- )
- end
-
def check_message_presence(exists: true, text: nil, id: nil)
css_method = exists ? :has_css? : :has_no_css?
if text
diff --git a/plugins/chat/spec/system/page_objects/chat/chat_thread.rb b/plugins/chat/spec/system/page_objects/chat/chat_thread.rb
index 640ffe1c264..fcb023823b0 100644
--- a/plugins/chat/spec/system/page_objects/chat/chat_thread.rb
+++ b/plugins/chat/spec/system/page_objects/chat/chat_thread.rb
@@ -144,13 +144,6 @@ module PageObjects
".chat-thread .chat-messages-container .chat-message-container[data-id=\"#{id}\"]"
end
- def has_deleted_message?(message, count: 1)
- has_css?(
- ".chat-thread .chat-message-container[data-id=\"#{message.id}\"] .chat-message-deleted",
- text: I18n.t("js.chat.deleted", count: count),
- )
- end
-
def open_edit_message(message)
hover_message(message)
click_more_button
diff --git a/plugins/chat/spec/system/page_objects/chat/components/messages.rb b/plugins/chat/spec/system/page_objects/chat/components/messages.rb
index a823eab7590..dbcb02611ae 100644
--- a/plugins/chat/spec/system/page_objects/chat/components/messages.rb
+++ b/plugins/chat/spec/system/page_objects/chat/components/messages.rb
@@ -44,6 +44,14 @@ module PageObjects
messages.all? { |message| has_message?(id: message.id, selected: true) }
end
+ def has_deleted_messages?(*messages)
+ messages.all? { |message| has_message?(id: message.id, deleted: 1) }
+ end
+
+ def has_deleted_message?(message, count: 1)
+ has_message?(id: message.id, deleted: count)
+ end
+
private
def message
diff --git a/plugins/chat/test/javascripts/acceptance/user-status-on-mentions-test.js b/plugins/chat/test/javascripts/acceptance/user-status-on-mentions-test.js
index b21fedb268e..a361f2f3f85 100644
--- a/plugins/chat/test/javascripts/acceptance/user-status-on-mentions-test.js
+++ b/plugins/chat/test/javascripts/acceptance/user-status-on-mentions-test.js
@@ -226,7 +226,7 @@ acceptance("Chat | User status on mentions", function (needs) {
await visit(`/chat/c/-/${channelId}`);
await deleteMessage(".chat-message-content");
- await restoreMessage(".chat-message-deleted");
+ await restoreMessage(".chat-message-text.-deleted");
assertStatusIsRendered(
assert,
@@ -239,7 +239,7 @@ acceptance("Chat | User status on mentions", function (needs) {
await visit(`/chat/c/-/${channelId}`);
await deleteMessage(".chat-message-content");
- await restoreMessage(".chat-message-deleted");
+ await restoreMessage(".chat-message-text.-deleted");
loggedInUser().appEvents.trigger("user-status:changed", {
[mentionedUser1.id]: newStatus,
@@ -254,7 +254,7 @@ acceptance("Chat | User status on mentions", function (needs) {
await visit(`/chat/c/-/${channelId}`);
await deleteMessage(".chat-message-content");
- await restoreMessage(".chat-message-deleted");
+ await restoreMessage(".chat-message-text.-deleted");
loggedInUser().appEvents.trigger("user-status:changed", {
[mentionedUser1.id]: null,
diff --git a/plugins/chat/test/javascripts/components/chat-message-avatar-test.js b/plugins/chat/test/javascripts/components/chat-message-avatar-test.js
index 59a61329262..b9140651efb 100644
--- a/plugins/chat/test/javascripts/components/chat-message-avatar-test.js
+++ b/plugins/chat/test/javascripts/components/chat-message-avatar-test.js
@@ -14,7 +14,7 @@ module("Discourse Chat | Component | chat-message-avatar", function (hooks) {
chat_webhook_event: { emoji: ":heart:" },
});
- await render(hbs``);
+ await render(hbs``);
assert.strictEqual(query(".chat-emoji-avatar .emoji").title, "heart");
});
@@ -24,7 +24,7 @@ module("Discourse Chat | Component | chat-message-avatar", function (hooks) {
user: { username: "discobot" },
});
- await render(hbs``);
+ await render(hbs``);
assert.true(exists('.chat-user-avatar [data-user-card="discobot"]'));
});
diff --git a/plugins/chat/test/javascripts/components/chat-message-info-test.js b/plugins/chat/test/javascripts/components/chat-message-info-test.js
index a99f9db6548..44d42e2f42a 100644
--- a/plugins/chat/test/javascripts/components/chat-message-info-test.js
+++ b/plugins/chat/test/javascripts/components/chat-message-info-test.js
@@ -11,12 +11,16 @@ import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
module("Discourse Chat | Component | chat-message-info", function (hooks) {
setupRenderingTest(hooks);
+ const template = hbs`
+
+ `;
+
test("chat_webhook_event", async function (assert) {
- this.message = ChatMessage.create(fabricators.channel(), {
+ this.message = fabricators.message({
chat_webhook_event: { username: "discobot" },
});
- await render(hbs``);
+ await render(template);
assert.strictEqual(
query(".chat-message-info__username").innerText.trim(),
@@ -29,11 +33,11 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
});
test("user", async function (assert) {
- this.message = ChatMessage.create(fabricators.channel(), {
+ this.message = fabricators.message({
user: { username: "discobot" },
});
- await render(hbs``);
+ await render(template);
assert.strictEqual(
query(".chat-message-info__username").innerText.trim(),
@@ -42,18 +46,18 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
});
test("date", async function (assert) {
- this.message = ChatMessage.create(fabricators.channel(), {
+ this.message = fabricators.message({
user: { username: "discobot" },
created_at: moment(),
});
- await render(hbs``);
+ await render(template);
assert.true(exists(".chat-message-info__date"));
});
test("bookmark (with reminder)", async function (assert) {
- this.message = ChatMessage.create(fabricators.channel(), {
+ this.message = fabricators.message({
user: { username: "discobot" },
bookmark: Bookmark.create({
reminder_at: moment(),
@@ -61,7 +65,7 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
}),
});
- await render(hbs``);
+ await render(template);
assert.true(
exists(".chat-message-info__bookmark .d-icon-discourse-bookmark-clock")
@@ -76,50 +80,48 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
}),
});
- await render(hbs``);
+ await render(template);
assert.true(exists(".chat-message-info__bookmark .d-icon-bookmark"));
});
test("user status", async function (assert) {
const status = { description: "off to dentist", emoji: "tooth" };
- this.message = ChatMessage.create(fabricators.channel(), {
- user: { status },
- });
+ this.message = fabricators.message({ user: { status } });
- await render(hbs``);
+ await render(template);
assert.true(exists(".chat-message-info__status .user-status-message"));
});
- test("reviewable", async function (assert) {
- this.message = ChatMessage.create(fabricators.channel(), {
+ test("flag status", async function (assert) {
+ this.message = fabricators.message({
user: { username: "discobot" },
user_flag_status: 0,
});
- await render(hbs``);
+ await render(template);
- assert.strictEqual(
- query(".chat-message-info__flag > .svg-icon-title").title,
- I18n.t("chat.you_flagged")
- );
+ assert
+ .dom(".chat-message-info__flag > .svg-icon-title")
+ .hasAttribute("title", I18n.t("chat.you_flagged"));
+ });
- this.message = ChatMessage.create(fabricators.channel(), {
+ test("reviewable", async function (assert) {
+ this.message = fabricators.message({
user: { username: "discobot" },
- reviewable_id: 1,
+ user_flag_status: 0,
});
- await render(hbs``);
+ await render(template);
- assert.strictEqual(
- query(".chat-message-info__flag a .svg-icon-title").title,
- I18n.t("chat.flagged")
- );
+ assert
+ .dom(".chat-message-info__flag > .svg-icon-title")
+ .hasAttribute("title", I18n.t("chat.you_flagged"));
});
test("with username classes", async function (assert) {
- this.message = ChatMessage.create(fabricators.channel(), {
+ this.message = fabricators.message({
user: {
username: "discobot",
admin: true,
@@ -129,7 +131,7 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
},
});
- await render(hbs``);
+ await render(template);
assert.dom(".chat-message-info__username.is-staff").exists();
assert.dom(".chat-message-info__username.is-admin").exists();
@@ -139,11 +141,11 @@ module("Discourse Chat | Component | chat-message-info", function (hooks) {
});
test("without username classes", async function (assert) {
- this.message = ChatMessage.create(fabricators.channel(), {
+ this.message = fabricators.message({
user: { username: "discobot" },
});
- await render(hbs``);
+ await render(template);
assert.dom(".chat-message-info__username.is-staff").doesNotExist();
assert.dom(".chat-message-info__username.is-admin").doesNotExist();
diff --git a/plugins/chat/test/javascripts/components/chat-message-left-gutter-test.js b/plugins/chat/test/javascripts/components/chat-message-left-gutter-test.js
new file mode 100644
index 00000000000..26415eb0440
--- /dev/null
+++ b/plugins/chat/test/javascripts/components/chat-message-left-gutter-test.js
@@ -0,0 +1,54 @@
+import { render } from "@ember/test-helpers";
+import { setupRenderingTest } from "discourse/tests/helpers/component-test";
+import hbs from "htmlbars-inline-precompile";
+import { module, test } from "qunit";
+import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
+import I18n from "I18n";
+
+module(
+ "Discourse Chat | Component | Chat::Message::LeftGutter",
+ function (hooks) {
+ setupRenderingTest(hooks);
+
+ const template = hbs`
+
+ `;
+
+ test("default", async function (assert) {
+ this.message = fabricators.message();
+
+ await render(template);
+
+ assert.dom(".chat-message-left-gutter__date").exists();
+ });
+
+ test("with reviewable", async function (assert) {
+ this.message = fabricators.message({ reviewable_id: 1 });
+
+ await render(template);
+
+ assert
+ .dom(".chat-message-left-gutter__flag .svg-icon-title")
+ .hasAttribute("title", I18n.t("chat.flagged"));
+ });
+
+ test("with flag status", async function (assert) {
+ this.message = fabricators.message({ user_flag_status: 0 });
+
+ await render(template);
+
+ assert
+ .dom(".chat-message-left-gutter__flag .svg-icon-title")
+ .hasAttribute("title", I18n.t("chat.you_flagged"));
+ });
+
+ test("bookmark", async function (assert) {
+ this.message = fabricators.message({ bookmark: fabricators.bookmark() });
+
+ await render(template);
+
+ assert.dom(".chat-message-left-gutter__date").exists();
+ assert.dom(".chat-message-left-gutter__bookmark").exists();
+ });
+ }
+);
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
new file mode 100644
index 00000000000..35af421d57f
--- /dev/null
+++ b/plugins/chat/test/javascripts/components/chat-message-mention-warning-test.js
@@ -0,0 +1,102 @@
+import { render } from "@ember/test-helpers";
+import { setupRenderingTest } from "discourse/tests/helpers/component-test";
+import hbs from "htmlbars-inline-precompile";
+import { module, test } from "qunit";
+import fabricators from "discourse/plugins/chat/discourse/lib/fabricators";
+
+module(
+ "Discourse Chat | Component | Chat::Message::MentionWarning",
+ function (hooks) {
+ setupRenderingTest(hooks);
+
+ const template = hbs`
+
+ `;
+
+ test("without memberships", async function (assert) {
+ this.message = fabricators.message();
+ this.message.mentionWarning = fabricators.messageMentionWarning(
+ this.message,
+ {
+ without_membership: [fabricators.user()].map((u) => {
+ return { username: u.username, id: u.id };
+ }),
+ }
+ );
+
+ await render(template);
+
+ assert
+ .dom(".chat-message-mention-warning__text.-without-membership")
+ .exists();
+ });
+
+ test("cannot see channel", async function (assert) {
+ this.message = fabricators.message();
+ this.message.mentionWarning = fabricators.messageMentionWarning(
+ this.message,
+ {
+ cannot_see: [fabricators.user()].map((u) => {
+ return { username: u.username, id: u.id };
+ }),
+ }
+ );
+
+ await render(template);
+
+ assert.dom(".chat-message-mention-warning__text.-cannot-see").exists();
+ });
+
+ test("cannot see channel", async function (assert) {
+ this.message = fabricators.message();
+ this.message.mentionWarning = fabricators.messageMentionWarning(
+ this.message,
+ {
+ cannot_see: [fabricators.user()].map((u) => {
+ return { username: u.username, id: u.id };
+ }),
+ }
+ );
+
+ await render(template);
+
+ assert.dom(".chat-message-mention-warning__text.-cannot-see").exists();
+ });
+
+ test("too many groups", async function (assert) {
+ this.message = fabricators.message();
+ this.message.mentionWarning = fabricators.messageMentionWarning(
+ this.message,
+ {
+ groups_with_too_many_members: [fabricators.group()].mapBy("name"),
+ }
+ );
+
+ await render(template);
+
+ assert
+ .dom(
+ ".chat-message-mention-warning__text.-groups-with-too-many-members"
+ )
+ .exists();
+ });
+
+ test("groups with mentions disabled", async function (assert) {
+ this.message = fabricators.message();
+ this.message.mentionWarning = fabricators.messageMentionWarning(
+ this.message,
+ {
+ group_mentions_disabled: [fabricators.group()].mapBy("name"),
+ }
+ );
+
+ await render(template);
+
+ assert
+ .dom(
+ ".chat-message-mention-warning__text.-groups-with-mentions-disabled"
+ )
+ .exists();
+ });
+ }
+);
diff --git a/plugins/chat/test/javascripts/components/chat-message-test.js b/plugins/chat/test/javascripts/components/chat-message-test.js
index 135788acd74..0d0efb76e96 100644
--- a/plugins/chat/test/javascripts/components/chat-message-test.js
+++ b/plugins/chat/test/javascripts/components/chat-message-test.js
@@ -9,11 +9,7 @@ module("Discourse Chat | Component | chat-message", function (hooks) {
setupRenderingTest(hooks);
const template = hbs`
-
+
`;
test("Message with edits", async function (assert) {
@@ -31,7 +27,7 @@ module("Discourse Chat | Component | chat-message", function (hooks) {
await render(template);
assert.true(
- exists(".chat-message-deleted .chat-message-expand"),
+ exists(".chat-message-text.-deleted .chat-message-expand"),
"has the correct css class and expand button within"
);
});
@@ -41,7 +37,7 @@ module("Discourse Chat | Component | chat-message", function (hooks) {
await render(template);
assert.true(
- exists(".chat-message-hidden .chat-message-expand"),
+ exists(".chat-message-text.-hidden .chat-message-expand"),
"has the correct css class and expand button within"
);
});