diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-channel.hbs index 715ddb54ec9..117129d0d7d 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel.hbs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel.hbs @@ -42,8 +42,6 @@ {{/each}} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel.js index eedf4da63e2..1f18c64e01a 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel.js @@ -491,16 +491,6 @@ export default class ChatLivePane extends Component { }); } - @action - messageDidEnterViewport(message) { - message.visible = true; - } - - @action - messageDidLeaveViewport(message) { - message.visible = false; - } - @debounce(READ_INTERVAL_MS) updateLastReadMessage() { schedule("afterRender", () => { diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message-info.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-message-info.hbs deleted file mode 100644 index 8ba1a34778b..00000000000 --- a/plugins/chat/assets/javascripts/discourse/components/chat-message-info.hbs +++ /dev/null @@ -1,61 +0,0 @@ -
- {{#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}} -
\ No newline at end of file diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-message.hbs index 2fe527b8786..9006e4ffee6 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-message.hbs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-message.hbs @@ -37,10 +37,8 @@ this.onLongPressCancel }} {{chat/track-message - (hash - didEnterViewport=(fn @messageDidEnterViewport @message) - didLeaveViewport=(fn @messageDidLeaveViewport @message) - ) + (fn (mut @message.visible) true) + (fn (mut @message.visible) false) }} > {{#if this.show}} @@ -54,7 +52,7 @@ {{/if}} {{#if this.deletedAndCollapsed}} -
+
{{else if this.hiddenAndCollapsed}} -
+
+ {{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" ); });