diff --git a/plugins/chat/app/controllers/chat/api/chatables_controller.rb b/plugins/chat/app/controllers/chat/api/chatables_controller.rb index c58a4796456..8454b74be9a 100644 --- a/plugins/chat/app/controllers/chat/api/chatables_controller.rb +++ b/plugins/chat/app/controllers/chat/api/chatables_controller.rb @@ -42,7 +42,7 @@ class Chat::Api::ChatablesController < Chat::ApiController direct_message_channels = if users.count > 0 # FIXME: investigate the cost of this query - Chat::Channel + Chat::DirectMessageChannel .includes(chatable: :users) .joins(direct_message: :direct_message_users) .group(1) diff --git a/plugins/chat/app/serializers/chat/direct_message_serializer.rb b/plugins/chat/app/serializers/chat/direct_message_serializer.rb index 6cc97f22c8a..95aa9fca6e8 100644 --- a/plugins/chat/app/serializers/chat/direct_message_serializer.rb +++ b/plugins/chat/app/serializers/chat/direct_message_serializer.rb @@ -2,6 +2,8 @@ module Chat class DirectMessageSerializer < ApplicationSerializer + attributes :id + has_many :users, serializer: Chat::UserWithCustomFieldsAndStatusSerializer, embed: :objects def users diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-modal-inner.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-modal-inner.js index 5519e771f2e..17d9420f1d1 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-modal-inner.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-modal-inner.js @@ -40,7 +40,7 @@ export default Component.extend(ModalFunctionality, { .createChannelArchive(this.chatChannel.id, this._data()) .then(() => { this.flash(I18n.t("chat.channel_archive.process_started"), "success"); - this.chatChannel.set("status", CHANNEL_STATUSES.archived); + this.chatChannel.status = CHANNEL_STATUSES.archived; discourseLater(() => { this.closeModal(); diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-status.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-status.hbs index e09696ee388..745fb8907b6 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-status.hbs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-status.hbs @@ -1,18 +1,25 @@ -{{#if (and this.channel.archive_failed this.currentUser.admin)}} -
-
- {{this.channelArchiveFailedMessage}} -
+{{#if this.shouldRender}} + {{#if @channel.archive.failed}} +
+
+ {{this.channelArchiveFailedMessage}} +
-
- +
+ +
-
-{{else if (and this.channel.archive_completed this.currentUser.admin)}} -
- {{this.channelArchiveCompletedMessage}} -
+ {{else if @channel.archive.completed}} +
+ {{this.channelArchiveCompletedMessage}} +
+ {{/if}} {{/if}} \ No newline at end of file diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-status.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-status.js index 0f23a725e3d..edfd1bbf7f6 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-status.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-archive-status.js @@ -1,61 +1,53 @@ -import Component from "@ember/component"; +import Component from "@glimmer/component"; import { htmlSafe } from "@ember/template"; import I18n from "I18n"; import { popupAjaxError } from "discourse/lib/ajax-error"; import getURL from "discourse-common/lib/get-url"; import { action } from "@ember/object"; -import discourseComputed from "discourse-common/utils/decorators"; import { inject as service } from "@ember/service"; +import { isPresent } from "@ember/utils"; -export default Component.extend({ - channel: null, - tagName: "", - chatApi: service(), +export default class ChatChannelArchiveStatus extends Component { + @service chatApi; + @service currentUser; - @discourseComputed( - "channel.status", - "channel.archived_messages", - "channel.total_messages", - "channel.archive_failed" - ) - channelArchiveFailedMessage() { - const translationKey = !this.channel.archive_topic_id + get shouldRender() { + return this.currentUser.admin && isPresent(this.args.channel.archive); + } + + get channelArchiveFailedMessage() { + const archive = this.args.channel.archive; + const translationKey = !archive.topicId ? "chat.channel_status.archive_failed_no_topic" : "chat.channel_status.archive_failed"; return htmlSafe( I18n.t(translationKey, { - completed: this.channel.archived_messages, - total: this.channel.total_messages, - topic_url: this._getTopicUrl(), + completed: archive.messages, + total: archive.totalMessages, + topic_url: this.#getTopicUrl(), }) ); - }, + } - @discourseComputed( - "channel.status", - "channel.archived_messages", - "channel.total_messages", - "channel.archive_completed" - ) - channelArchiveCompletedMessage() { + get channelArchiveCompletedMessage() { return htmlSafe( I18n.t("chat.channel_status.archive_completed", { - topic_url: this._getTopicUrl(), + topic_url: this.#getTopicUrl(), }) ); - }, + } @action retryArchive() { return this.chatApi - .createChannelArchive(this.channel.id) + .createChannelArchive(this.args.channel.id) .catch(popupAjaxError); - }, + } - _getTopicUrl() { - if (!this.channel.archive_topic_id) { + get #getTopicUrl() { + if (!this.args.channel.archive.topicId) { return ""; } - return getURL(`/t/-/${this.channel.archive_topic_id}`); - }, -}); + return getURL(`/t/-/${this.args.channel.archive.topicId}`); + } +} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-leave-btn.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-channel-leave-btn.hbs index 90e409770e9..19fa80d7a42 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-leave-btn.hbs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-leave-btn.hbs @@ -1,8 +1,8 @@ -{{#unless this.site.mobileView}} +{{#if this.shouldRender}} -{{/unless}} \ No newline at end of file +{{/if}} \ No newline at end of file diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-leave-btn.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-leave-btn.js index 3347b5e2369..b585b366355 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-leave-btn.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-leave-btn.js @@ -1,25 +1,19 @@ -import discourseComputed from "discourse-common/utils/decorators"; -import Component from "@ember/component"; -import { equal } from "@ember/object/computed"; +import Component from "@glimmer/component"; import { inject as service } from "@ember/service"; -import { CHATABLE_TYPES } from "discourse/plugins/chat/discourse/models/chat-channel"; +import { isPresent } from "@ember/utils"; +export default class ChatChannelLeaveBtn extends Component { + @service chat; + @service site; -export default Component.extend({ - tagName: "", - channel: null, - chat: service(), + get shouldRender() { + return !this.site.mobileView && isPresent(this.args.channel); + } - isDirectMessageRow: equal( - "channel.chatable_type", - CHATABLE_TYPES.directMessageChannel - ), - - @discourseComputed("isDirectMessageRow") - leaveChatTitleKey(isDirectMessageRow) { - if (isDirectMessageRow) { + get leaveChatTitleKey() { + if (this.args.channel.isDirectMessageChannel) { return "chat.direct_messages.leave"; } else { return "chat.leave"; } - }, -}); + } +} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-row.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-row.js index 3fe267f6f63..9d697bfa30d 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-row.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-row.js @@ -19,7 +19,7 @@ export default class ChatChannelRow extends Component { } get channelHasUnread() { - return this.args.channel.currentUserMembership.unread_count > 0; + return this.args.channel.currentUserMembership.unreadCount > 0; } get #firstDirectMessageUser() { diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-selection-row.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-selection-row.js index 07d4e9b6c53..540676a2e90 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-selection-row.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-selection-row.js @@ -5,9 +5,11 @@ import { action } from "@ember/object"; export default Component.extend({ tagName: "", - @discourseComputed("model", "model.focused") - rowClassNames(model, focused) { - return `chat-channel-selection-row ${focused ? "focused" : ""} ${ + isFocused: false, + + @discourseComputed("model", "isFocused") + rowClassNames(model, isFocused) { + return `chat-channel-selection-row ${isFocused ? "focused" : ""} ${ this.model.user ? "user-row" : "channel-row" }`; }, diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-selector-modal-inner.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-channel-selector-modal-inner.hbs index 0eb18b0b4b2..fbb197de19c 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-selector-modal-inner.hbs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-selector-modal-inner.hbs @@ -18,6 +18,7 @@ {{#each this.channels as |channel|}} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-selector-modal-inner.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-selector-modal-inner.js index 935354ea2bf..19cf7f873b0 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-selector-modal-inner.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-selector-modal-inner.js @@ -1,6 +1,5 @@ import Component from "@ember/component"; import { action } from "@ember/object"; -import ChatChannel from "discourse/plugins/chat/discourse/models/chat-channel"; import { ajax } from "discourse/lib/ajax"; import { bind } from "discourse-common/utils/decorators"; import { schedule } from "@ember/runloop"; @@ -9,6 +8,8 @@ import { popupAjaxError } from "discourse/lib/ajax-error"; import discourseDebounce from "discourse-common/lib/debounce"; import { INPUT_DELAY } from "discourse-common/config/environment"; import { isPresent } from "@ember/utils"; +import ChatChannel from "discourse/plugins/chat/discourse/models/chat-channel"; +import User from "discourse/models/user"; export default Component.extend({ chat: service(), @@ -19,6 +20,7 @@ export default Component.extend({ loading: false, chatChannelsManager: service(), router: service(), + focusedRow: null, didInsertElement() { this._super(...arguments); @@ -53,19 +55,16 @@ export default Component.extend({ } else { channel = this.channels.find((c) => c.user && c.id === id); } - channel?.set("focused", true); - this.channels.forEach((c) => { - if (c !== channel) { - c.set("focused", false); - } - }); + if (channel) { + this.set("focusedRow", channel); + } } }, @bind onKeyUp(e) { if (e.key === "Enter") { - let focusedChannel = this.channels.find((c) => c.focused); + let focusedChannel = this.channels.find((c) => c === this.focusedRow); this.switchChannel(focusedChannel); e.preventDefault(); } else if (e.key === "ArrowDown") { @@ -78,16 +77,17 @@ export default Component.extend({ }, arrowNavigateChannels(direction) { - const indexOfFocused = this.channels.findIndex((c) => c.focused); + const indexOfFocused = this.channels.findIndex( + (c) => c === this.focusedRow + ); if (indexOfFocused > -1) { const nextIndex = direction === "down" ? 1 : -1; const nextChannel = this.channels[indexOfFocused + nextIndex]; if (nextChannel) { - this.channels[indexOfFocused].set("focused", false); - nextChannel.set("focused", true); + this.set("focusedRow", nextChannel); } } else { - this.channels[0].set("focused", true); + this.set("focusedRow", this.channels[0]); } schedule("afterRender", () => { @@ -100,7 +100,7 @@ export default Component.extend({ @action switchChannel(channel) { - if (channel.user) { + if (channel instanceof User) { return this.fetchOrCreateChannelForUser(channel).then((response) => { const newChannel = this.chatChannelsManager.store(response.channel); return this.chatChannelsManager.follow(newChannel).then((c) => { @@ -145,21 +145,21 @@ export default Component.extend({ .then((searchModel) => { if (this.searchIndex === thisSearchIndex) { this.set("searchModel", searchModel); - const channels = searchModel.public_channels.concat( - searchModel.direct_message_channels, - searchModel.users - ); - channels.forEach((c) => { - if (c.username) { - c.user = true; // This is used by the `chat-channel-selection-row` component - } - }); + let channels = searchModel.public_channels + .concat(searchModel.direct_message_channels, searchModel.users) + .map((c) => { + if ( + c.chatable_type === "DirectMessage" || + c.chatable_type === "Category" + ) { + return ChatChannel.create(c); + } + + return User.create(c); + }); + this.setProperties({ - channels: channels.map((channel) => { - return channel.user - ? ChatChannel.create(channel) - : this.chatChannelsManager.store(channel); - }), + channels, loading: false, }); this.focusFirstChannel(this.channels); @@ -188,8 +188,11 @@ export default Component.extend({ }, focusFirstChannel(channels) { - channels.forEach((c) => c.set("focused", false)); - channels[0]?.set("focused", true); + if (channels[0]) { + this.set("focusedRow", channels[0]); + } else { + this.set("focusedRow", null); + } }, getChannelsWithFilter(filter, opts = { excludeActiveChannel: true }) { diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.hbs index a611dd59bde..a27c3aec80d 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.hbs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings-view.hbs @@ -12,7 +12,7 @@ @value={{this.channel.currentUserMembership.muted}} @valueProperty="value" @class="channel-settings-view__muted-selector" - @onChange={{action (fn this.saveNotificationSettings "muted")}} + @onChange={{fn this.saveNotificationSettings "muted" "muted"}} />
@@ -22,17 +22,19 @@
@@ -42,17 +44,19 @@
@@ -74,16 +78,16 @@

@@ -102,12 +106,12 @@ { - [ - "muted", - "desktop_notification_level", - "mobile_notification_level", - ].forEach((property) => { - if ( - result.membership[property] !== - this.channel.currentUserMembership[property] - ) { - this.channel.currentUserMembership[property] = - result.membership[property]; - } - }); + this.channel.currentUserMembership[frontendKey] = + result.membership[backendKey]; }); } @@ -125,7 +113,7 @@ export default class ChatChannelSettingsView extends Component { @action onToggleAutoJoinUsers() { - if (!this.channel.auto_join_users) { + if (!this.channel.autoJoinUsers) { this.onEnableAutoJoinUsers(); } else { this.onDisableAutoJoinUsers(); @@ -134,43 +122,61 @@ export default class ChatChannelSettingsView extends Component { @action onToggleChannelWideMentions() { + const newValue = !this.channel.allowChannelWideMentions; + if (this.channel.allowChannelWideMentions === newValue) { + return; + } + return this._updateChannelProperty( this.channel, "allow_channel_wide_mentions", - !this.channel.allow_channel_wide_mentions - ); + newValue + ).then((result) => { + this.channel.allowChannelWideMentions = + result.channel.allow_channel_wide_mentions; + }); } onDisableAutoJoinUsers() { - return this._updateChannelProperty(this.channel, "auto_join_users", false); + if (this.channel.autoJoinUsers === false) { + return; + } + + return this._updateChannelProperty( + this.channel, + "auto_join_users", + false + ).then((result) => { + this.channel.autoJoinUsers = result.channel.auto_join_users; + }); } onEnableAutoJoinUsers() { + if (this.channel.autoJoinUsers === true) { + return; + } + this.dialog.confirm({ message: I18n.t("chat.settings.auto_join_users_warning", { category: this.channel.chatable.name, }), didConfirm: () => - this._updateChannelProperty(this.channel, "auto_join_users", true), + this._updateChannelProperty(this.channel, "auto_join_users", true).then( + (result) => { + this.channel.autoJoinUsers = result.channel.auto_join_users; + } + ), }); } _updateChannelProperty(channel, property, value) { - if (channel[property] === value) { - return Promise.resolve(); - } - const payload = {}; payload[property] = value; - return this.chatApi - .updateChannel(channel.id, payload) - .then((result) => { - channel.set(property, result.channel[property]); - }) - .catch((event) => { - if (event.jqXHR?.responseJSON?.errors) { - this.flash(event.jqXHR.responseJSON.errors.join("\n"), "error"); - } - }); + + return this.chatApi.updateChannel(channel.id, payload).catch((event) => { + if (event.jqXHR?.responseJSON?.errors) { + this.flash(event.jqXHR.responseJSON.errors.join("\n"), "error"); + } + }); } } diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.hbs index a693205e067..041dc04f742 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.hbs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.hbs @@ -1,21 +1,21 @@ -{{#if this.channel.isDraft}} +{{#if @channel.isDraft}}

- {{this.channel.title}} + {{@channel.title}} {{#if (has-block)}} {{yield}} {{/if}}
{{else}} - {{#if this.channel.isDirectMessageChannel}} + {{#if @channel.isDirectMessageChannel}}
{{#if this.multiDm}} - {{this.channel.chatable.users.length}} + {{@channel.chatable.users.length}} {{else}} - + {{/if}}
@@ -24,12 +24,12 @@ {{#if this.multiDm}} {{this.usernames}} {{else}} - {{#let this.channel.chatable.users.firstObject as |user|}} + {{#let @channel.chatable.users.firstObject as |user|}} {{user.username}} {{#if this.showUserStatus}} {{/if}} @@ -48,19 +48,19 @@ {{yield}} {{/if}}
- {{else if this.channel.isCategoryChannel}} + {{else if @channel.isCategoryChannel}}
{{d-icon "d-chat"}} - {{#if this.channel.chatable.read_restricted}} + {{#if @channel.chatable.read_restricted}} {{d-icon "lock" class="chat-channel-title__restricted-category-icon"}} {{/if}} - {{replace-emoji this.channel.title}} + {{replace-emoji @channel.title}} {{#if (has-block)}} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.js index 6bb9dba438a..3fd41b2b9ac 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.js @@ -1,33 +1,24 @@ -import Component from "@ember/component"; +import Component from "@glimmer/component"; import { htmlSafe } from "@ember/template"; -import { computed } from "@ember/object"; -import { gt, reads } from "@ember/object/computed"; export default class ChatChannelTitle extends Component { - tagName = ""; - channel = null; + get users() { + return this.args.channel.chatable.users; + } - @reads("channel.chatable.users.[]") users; - @gt("users.length", 1) multiDm; + get multiDm() { + return this.users.length > 1; + } - @computed("users") get usernames() { return this.users.mapBy("username").join(", "); } - @computed("channel.chatable.color") get channelColorStyle() { - return htmlSafe(`color: #${this.channel.chatable.color}`); + return htmlSafe(`color: #${this.args.channel.chatable.color}`); } - @computed( - "channel.chatable.users.length", - "channel.chatable.users.@each.status" - ) get showUserStatus() { - return !!( - this.channel.chatable.users.length === 1 && - this.channel.chatable.users[0].status - ); + return !!(this.users.length === 1 && this.users[0].status); } } diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-unread-indicator.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-channel-unread-indicator.hbs index e459ff02215..208dc3d7674 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-unread-indicator.hbs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-unread-indicator.hbs @@ -1,16 +1,16 @@ -{{#if (gt @channel.currentUserMembership.unread_count 0)}} +{{#if (gt @channel.currentUserMembership.unreadCount 0)}}
-
{{@channel.currentUserMembership.unread_count}}
+
{{@channel.currentUserMembership.unreadCount}}
{{/if}} \ No newline at end of file diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel.js index 9384cd05da5..f524241464a 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel.js @@ -165,7 +165,7 @@ export default class ChatLivePane extends Component { findArgs["targetMessageId"] = this.requestedTargetMessageId; } else if (fetchingFromLastRead) { findArgs["targetMessageId"] = - this.args.channel.currentUserMembership.last_read_message_id; + this.args.channel.currentUserMembership.lastReadMessageId; } return this.chatApi @@ -346,7 +346,7 @@ export default class ChatLivePane extends Component { if ( !foundFirstNew && messageData.id > - this.args.channel.currentUserMembership.last_read_message_id && + this.args.channel.currentUserMembership.lastReadMessageId && !channel.messages.some((m) => m.newest) ) { foundFirstNew = true; @@ -444,7 +444,7 @@ export default class ChatLivePane extends Component { } const lastReadId = - this.args.channel.currentUserMembership?.last_read_message_id; + this.args.channel.currentUserMembership?.lastReadMessageId; let lastUnreadVisibleMessage = this.args.channel.visibleMessages.findLast( (message) => !lastReadId || message.id > lastReadId ); diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-composer.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-composer.hbs index 6ef7b22d5bc..6bf6f972012 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-composer.hbs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-composer.hbs @@ -93,7 +93,7 @@ {{#if this.shouldRenderReplyingIndicator}}
- +
{{/if}} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-draft-channel-screen.js b/plugins/chat/assets/javascripts/discourse/components/chat-draft-channel-screen.js index c5627fd1ba1..6d80fdc7331 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-draft-channel-screen.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-draft-channel-screen.js @@ -3,6 +3,7 @@ import { inject as service } from "@ember/service"; import Component from "@ember/component"; import { action } from "@ember/object"; import { cloneJSON } from "discourse-common/lib/object"; + export default class ChatDraftChannelScreen extends Component { @service chat; @service router; @@ -20,7 +21,7 @@ export default class ChatDraftChannelScreen extends Component { @action onSwitchFromDraftChannel(channel) { - channel.set("isDraft", false); + channel.isDraft = false; } _fetchPreviewedChannel(users) { @@ -29,20 +30,16 @@ export default class ChatDraftChannelScreen extends Component { return this.chat .getDmChannelForUsernames(users.mapBy("username")) .then((response) => { - this.set( - "previewedChannel", - ChatChannel.create( - Object.assign({}, response.channel, { isDraft: true }) - ) - ); + const channel = ChatChannel.create(response.channel); + channel.isDraft = true; + this.set("previewedChannel", channel); }) .catch((error) => { if (error?.jqXHR?.status === 404) { this.set( "previewedChannel", - ChatChannel.create({ - chatable: { users: cloneJSON(users) }, - isDraft: true, + ChatChannel.createDirectMessageChannelDraft({ + users: cloneJSON(users), }) ); } diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.hbs index 5805cca0cdf..1ae711500fd 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.hbs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.hbs @@ -1,10 +1,21 @@ -
- {{#if this.shouldDisplay}} - {{this.text}} - - . - . - . - - {{/if}} -
\ No newline at end of file +{{#if @channel}} +
+ {{#if this.shouldRender}} + {{this.text}} + + . + . + . + + {{/if}} +
+{{/if}} \ No newline at end of file diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.js b/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.js index 6c46c2e9101..014ba799321 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.js @@ -1,89 +1,93 @@ import { isBlank, isPresent } from "@ember/utils"; -import Component from "@ember/component"; +import Component from "@glimmer/component"; import { inject as service } from "@ember/service"; -import discourseComputed from "discourse-common/utils/decorators"; import I18n from "I18n"; -import { fmt } from "discourse/lib/computed"; -import { next } from "@ember/runloop"; +import { action } from "@ember/object"; +import { tracked } from "@glimmer/tracking"; -export default Component.extend({ - tagName: "", - presence: service(), - presenceChannel: null, - chatChannel: null, +export default class ChatReplyingIndicator extends Component { + @service currentUser; + @service presence; - @discourseComputed("presenceChannel.users.[]") - usernames(users) { - return users - ?.filter((u) => u.id !== this.currentUser.id) - ?.mapBy("username"); - }, + @tracked presenceChannel = null; + @tracked users = []; - @discourseComputed("usernames.[]") - text(usernames) { - if (isBlank(usernames)) { + @action + async subscribe() { + this.presenceChannel = this.presence.getChannel(this.channelName); + this.presenceChannel.on("change", this.handlePresenceChange); + await this.presenceChannel.subscribe(); + } + + @action + async resubscribe() { + await this.teardown(); + await this.subscribe(); + } + + @action + handlePresenceChange(presenceChannel) { + this.users = presenceChannel.users || []; + } + + @action + async handleDraft() { + if (this.args.channel.isDraft) { + await this.teardown(); + } else { + await this.resubscribe(); + } + } + + @action + async teardown() { + if (this.presenceChannel) { + await this.presenceChannel.unsubscribe(); + } + } + + get usernames() { + return this.users + .filter((u) => u.id !== this.currentUser.id) + .mapBy("username"); + } + + get text() { + if (isBlank(this.usernames)) { return; } - if (usernames.length === 1) { + if (this.usernames.length === 1) { return I18n.t("chat.replying_indicator.single_user", { - username: usernames[0], + username: this.usernames[0], }); } - if (usernames.length < 4) { - const lastUsername = usernames.pop(); - const commaSeparatedUsernames = usernames.join( - I18n.t("word_connector.comma") - ); + if (this.usernames.length < 4) { + const lastUsername = this.usernames[this.usernames.length - 1]; + const commaSeparatedUsernames = this.usernames + .slice(0, this.usernames.length - 1) + .join(I18n.t("word_connector.comma")); return I18n.t("chat.replying_indicator.multiple_users", { commaSeparatedUsernames, lastUsername, }); } - const commaSeparatedUsernames = usernames + const commaSeparatedUsernames = this.usernames .slice(0, 2) .join(I18n.t("word_connector.comma")); return I18n.t("chat.replying_indicator.many_users", { commaSeparatedUsernames, - count: usernames.length - 2, + count: this.usernames.length - 2, }); - }, + } - @discourseComputed("usernames.[]") - shouldDisplay(usernames) { - return isPresent(usernames); - }, + get shouldRender() { + return isPresent(this.usernames); + } - channelName: fmt("chatChannel.id", "/chat-reply/%@"), - - didReceiveAttrs() { - this._super(...arguments); - - if (!this.chatChannel || this.chatChannel.isDraft) { - this.presenceChannel?.unsubscribe(); - return; - } - - if (this.presenceChannel?.name !== this.channelName) { - this.presenceChannel?.unsubscribe(); - - next(() => { - if (this.isDestroyed || this.isDestroying) { - return; - } - - const presenceChannel = this.presence.getChannel(this.channelName); - this.set("presenceChannel", presenceChannel); - presenceChannel.subscribe(); - }); - } - }, - - willDestroyElement() { - this._super(...arguments); - - this.presenceChannel?.unsubscribe(); - }, -}); + get channelName() { + return `/chat-reply/${this.args.channel.id}`; + } +} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-selection-manager.js b/plugins/chat/assets/javascripts/discourse/components/chat-selection-manager.js index f346cf02e59..2bff51427d7 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-selection-manager.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-selection-manager.js @@ -75,14 +75,14 @@ export default class ChatSelectionManager extends Component { const openOpts = {}; if (this.chatChannel.isCategoryChannel) { - openOpts.categoryId = this.chatChannel.chatable_id; + openOpts.categoryId = this.chatChannel.chatableId; } if (this.site.mobileView) { // go to the relevant chatable (e.g. category) and open the // composer to insert text - if (this.chatChannel.chatable_url) { - this.router.transitionTo(this.chatChannel.chatable_url); + if (this.chatChannel.chatableUrl) { + this.router.transitionTo(this.chatChannel.chatableUrl); } await composer.focusComposer({ diff --git a/plugins/chat/assets/javascripts/discourse/components/direct-message-creator.js b/plugins/chat/assets/javascripts/discourse/components/direct-message-creator.js index b70382d4274..0e1c0871a5c 100644 --- a/plugins/chat/assets/javascripts/discourse/components/direct-message-creator.js +++ b/plugins/chat/assets/javascripts/discourse/components/direct-message-creator.js @@ -8,7 +8,7 @@ import { INPUT_DELAY } from "discourse-common/config/environment"; import { inject as service } from "@ember/service"; import { schedule } from "@ember/runloop"; import { gt, not } from "@ember/object/computed"; -import { createDirectMessageChannelDraft } from "discourse/plugins/chat/discourse/models/chat-channel"; +import ChatChannel from "discourse/plugins/chat/discourse/models/chat-channel"; export default Component.extend({ tagName: "", @@ -29,7 +29,7 @@ export default Component.extend({ this.set("users", []); this.set("selectedUsers", []); - this.set("channel", createDirectMessageChannelDraft()); + this.set("channel", ChatChannel.createDirectMessageChannelDraft()); }, didInsertElement() { diff --git a/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js b/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js index 4c81da24112..ff336af6d7d 100644 --- a/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js +++ b/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js @@ -154,7 +154,7 @@ export default { } const highlightable = [`@${this.currentUser.username}`]; - if (chatChannel.allow_channel_wide_mentions) { + if (chatChannel.allowChannelWideMentions) { highlightable.push(...MENTION_KEYWORDS.map((k) => `@${k}`)); } diff --git a/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js b/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js index b1b6a84fb3b..440c89643cd 100644 --- a/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js +++ b/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js @@ -88,13 +88,13 @@ export default { } get suffixValue() { - return this.channel.currentUserMembership.unread_count > 0 + return this.channel.currentUserMembership.unreadCount > 0 ? "circle" : ""; } get suffixCSSClass() { - return this.channel.currentUserMembership.unread_mentions > 0 + return this.channel.currentUserMembership.unreadMentions > 0 ? "urgent" : "unread"; } @@ -282,7 +282,7 @@ export default { } get suffixValue() { - return this.channel.currentUserMembership.unread_count > 0 + return this.channel.currentUserMembership.unreadCount > 0 ? "circle" : ""; } diff --git a/plugins/chat/assets/javascripts/discourse/models/chat-channel-archive.js b/plugins/chat/assets/javascripts/discourse/models/chat-channel-archive.js new file mode 100644 index 00000000000..5626dc0b5a9 --- /dev/null +++ b/plugins/chat/assets/javascripts/discourse/models/chat-channel-archive.js @@ -0,0 +1,21 @@ +import { tracked } from "@glimmer/tracking"; + +export default class ChatChannelArchive { + static create(args = {}) { + return new ChatChannelArchive(args); + } + + @tracked failed; + @tracked completed; + @tracked messages; + @tracked topicId; + @tracked totalMessages; + + constructor(args = {}) { + this.failed = args.archive_failed; + this.completed = args.archive_completed; + this.messages = args.archived_messages; + this.topicId = args.archive_topic_id; + this.totalMessages = args.total_messages; + } +} diff --git a/plugins/chat/assets/javascripts/discourse/models/chat-channel.js b/plugins/chat/assets/javascripts/discourse/models/chat-channel.js index 234214a1a6d..c40f00c0c72 100644 --- a/plugins/chat/assets/javascripts/discourse/models/chat-channel.js +++ b/plugins/chat/assets/javascripts/discourse/models/chat-channel.js @@ -1,5 +1,3 @@ -import RestModel from "discourse/models/rest"; -import User from "discourse/models/user"; import UserChatChannelMembership from "discourse/plugins/chat/discourse/models/user-chat-channel-membership"; import { ajax } from "discourse/lib/ajax"; import { escapeExpression } from "discourse/lib/utilities"; @@ -10,6 +8,9 @@ import ChatMessagesManager from "discourse/plugins/chat/discourse/lib/chat-messa import { getOwner } from "discourse-common/lib/get-owner"; import guid from "pretty-text/guid"; import ChatThread from "discourse/plugins/chat/discourse/models/chat-thread"; +import ChatDirectMessage from "discourse/plugins/chat/discourse/models/chat-direct-message"; +import ChatChannelArchive from "discourse/plugins/chat/discourse/models/chat-channel-archive"; +import Category from "discourse/models/category"; export const CHATABLE_TYPES = { directMessageChannel: "DirectMessage", @@ -49,25 +50,79 @@ const READONLY_STATUSES = [ CHANNEL_STATUSES.archived, ]; -export default class ChatChannel extends RestModel { +export default class ChatChannel { + static create(args = {}) { + return new ChatChannel(args); + } + + static createDirectMessageChannelDraft(args = {}) { + const channel = ChatChannel.create({ + chatable_type: CHATABLE_TYPES.directMessageChannel, + chatable: { + users: args.users || [], + }, + }); + channel.isDraft = true; + return channel; + } + @tracked currentUserMembership = null; @tracked isDraft = false; @tracked title; + @tracked slug; @tracked description; - @tracked chatableType; @tracked status; - @tracked activeThread; + @tracked activeThread = null; @tracked lastMessageSentAt; @tracked canDeleteOthers; @tracked canDeleteSelf; @tracked canFlag; @tracked canModerate; @tracked userSilenced; - @tracked draft; + @tracked draft = null; + @tracked meta; + @tracked chatableType; + @tracked chatableUrl; + @tracked autoJoinUsers = false; + @tracked allowChannelWideMentions = true; + @tracked membershipsCount = 0; + @tracked archive; threadsManager = new ChatThreadsManager(getOwner(this)); messagesManager = new ChatMessagesManager(getOwner(this)); + constructor(args = {}) { + this.id = args.id; + this.chatableId = args.chatable_id; + this.chatableUrl = args.chatable_url; + this.chatableType = args.chatable_type; + this.membershipsCount = args.memberships_count; + this.meta = args.meta; + this.slug = args.slug; + this.title = args.title; + this.status = args.status; + this.canDeleteSelf = args.can_delete_self; + this.canDeleteOthers = args.can_delete_others; + this.canFlag = args.can_flag; + this.userSilenced = args.user_silenced; + this.canModerate = args.can_moderate; + this.description = args.description; + this.lastMessageSentAt = args.last_message_sent_at; + this.threadingEnabled = args.threading_enabled; + this.autoJoinUsers = args.auto_join_users; + this.allowChannelWideMentions = args.allow_channel_wide_mentions; + this.chatable = this.isDirectMessageChannel + ? ChatDirectMessage.create(args) + : Category.create(args.chatable); + this.currentUserMembership = UserChatChannelMembership.create( + args.current_user_membership + ); + + if (args.archive_completed || args.archive_failed) { + this.archive = ChatChannelArchive.create(args); + } + } + findIndexOfMessage(id) { return this.messagesManager.findIndexOfMessage(id); } @@ -223,14 +278,14 @@ export default class ChatChannel extends RestModel { updateMembership(membership) { this.currentUserMembership.following = membership.following; - this.currentUserMembership.last_read_message_id = + this.currentUserMembership.lastReadMessage_id = membership.last_read_message_id; - this.currentUserMembership.desktop_notification_level = + this.currentUserMembership.desktopNotificationLevel = membership.desktop_notification_level; - this.currentUserMembership.mobile_notification_level = + this.currentUserMembership.mobileNotificationLevel = membership.mobile_notification_level; - this.currentUserMembership.unread_count = membership.unread_count; - this.currentUserMembership.unread_mentions = membership.unread_mentions; + this.currentUserMembership.unreadCount = membership.unread_count; + this.currentUserMembership.unreadMentions = membership.unread_mentions; this.currentUserMembership.muted = membership.muted; } @@ -239,7 +294,7 @@ export default class ChatChannel extends RestModel { return; } - if (this.currentUserMembership.last_read_message_id >= messageId) { + if (this.currentUserMembership.lastReadMessageId >= messageId) { return; } @@ -250,59 +305,3 @@ export default class ChatChannel extends RestModel { }); } } - -ChatChannel.reopenClass({ - create(args) { - args = args || {}; - - this._initUserModels(args); - this._initUserMembership(args); - - this._remapKey(args, "chatable_type", "chatableType"); - this._remapKey(args, "memberships_count", "membershipsCount"); - this._remapKey(args, "last_message_sent_at", "lastMessageSentAt"); - this._remapKey(args, "threading_enabled", "threadingEnabled"); - - return this._super(args); - }, - - _remapKey(obj, oldKey, newKey) { - delete Object.assign(obj, { [newKey]: obj[oldKey] })[oldKey]; - }, - - _initUserModels(args) { - if (args.chatable?.users?.length) { - for (let i = 0; i < args.chatable?.users?.length; i++) { - const userData = args.chatable.users[i]; - args.chatable.users[i] = User.create(userData); - } - } - }, - - _initUserMembership(args) { - if (args.currentUserMembership instanceof UserChatChannelMembership) { - return; - } - - args.currentUserMembership = UserChatChannelMembership.create( - args.current_user_membership || { - following: false, - muted: false, - unread_count: 0, - unread_mentions: 0, - } - ); - - delete args.current_user_membership; - }, -}); - -export function createDirectMessageChannelDraft() { - return ChatChannel.create({ - isDraft: true, - chatable_type: CHATABLE_TYPES.directMessageChannel, - chatable: { - users: [], - }, - }); -} diff --git a/plugins/chat/assets/javascripts/discourse/models/chat-direct-message.js b/plugins/chat/assets/javascripts/discourse/models/chat-direct-message.js new file mode 100644 index 00000000000..38e28e3cbd7 --- /dev/null +++ b/plugins/chat/assets/javascripts/discourse/models/chat-direct-message.js @@ -0,0 +1,26 @@ +import User from "discourse/models/user"; +import { tracked } from "@glimmer/tracking"; + +export default class ChatDirectMessage { + static create(args = {}) { + return new ChatDirectMessage(args); + } + + @tracked id; + @tracked users = null; + + constructor(args = {}) { + this.id = args.chatable.id; + this.users = this.#initUsers(args.chatable.users || []); + } + + #initUsers(users) { + return users.map((user) => { + if (!user || user instanceof User) { + return user; + } + + return User.create(user); + }); + } +} diff --git a/plugins/chat/assets/javascripts/discourse/models/chat-message.js b/plugins/chat/assets/javascripts/discourse/models/chat-message.js index 07c3310d27b..dd79233b143 100644 --- a/plugins/chat/assets/javascripts/discourse/models/chat-message.js +++ b/plugins/chat/assets/javascripts/discourse/models/chat-message.js @@ -166,7 +166,7 @@ export default class ChatMessage { } get read() { - return this.channel.currentUserMembership?.last_read_message_id >= this.id; + return this.channel.currentUserMembership?.lastReadMessageId >= this.id; } get firstMessageOfTheDayAt() { diff --git a/plugins/chat/assets/javascripts/discourse/models/user-chat-channel-membership.js b/plugins/chat/assets/javascripts/discourse/models/user-chat-channel-membership.js index 84a7d55cf98..ece9dd5d6cc 100644 --- a/plugins/chat/assets/javascripts/discourse/models/user-chat-channel-membership.js +++ b/plugins/chat/assets/javascripts/discourse/models/user-chat-channel-membership.js @@ -1,28 +1,36 @@ -import RestModel from "discourse/models/rest"; import { tracked } from "@glimmer/tracking"; import User from "discourse/models/user"; -export default class UserChatChannelMembership extends RestModel { + +export default class UserChatChannelMembership { + static create(args = {}) { + return new UserChatChannelMembership(args); + } + @tracked following = false; @tracked muted = false; - @tracked unread_count = 0; - @tracked unread_mentions = 0; - @tracked desktop_notification_level = null; - @tracked mobile_notification_level = null; - @tracked last_read_message_id = null; -} + @tracked unreadCount = 0; + @tracked unreadMentions = 0; + @tracked desktopNotificationLevel = null; + @tracked mobileNotificationLevel = null; + @tracked lastReadMessageId = null; + @tracked user = null; -UserChatChannelMembership.reopenClass({ - create(args) { - args = args || {}; - this._initUser(args); - return this._super(args); - }, + constructor(args = {}) { + this.following = args.following; + this.muted = args.muted; + this.unreadCount = args.unread_count; + this.unreadMentions = args.unread_mentions; + this.desktopNotificationLevel = args.desktop_notification_level; + this.mobileNotificationLevel = args.mobile_notification_level; + this.lastReadMessageId = args.last_read_message_id; + this.user = this.#initUserModel(args.user); + } - _initUser(args) { - if (!args.user || args.user instanceof User) { - return; + #initUserModel(user) { + if (!user || user instanceof User) { + return user; } - args.user = User.create(args.user); - }, -}); + return User.create(user); + } +} diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-channels-manager.js b/plugins/chat/assets/javascripts/discourse/services/chat-channels-manager.js index d96cd1baebf..f81b3fbf7f7 100644 --- a/plugins/chat/assets/javascripts/discourse/services/chat-channels-manager.js +++ b/plugins/chat/assets/javascripts/discourse/services/chat-channels-manager.js @@ -61,11 +61,10 @@ export default class ChatChannelsManager extends Service { return this.chatApi.followChannel(model.id).then((membership) => { model.currentUserMembership.following = membership.following; model.currentUserMembership.muted = membership.muted; - model.currentUserMembership.desktop_notification_level = - membership.desktop_notification_level; - model.currentUserMembership.mobile_notification_level = - membership.mobile_notification_level; - + model.currentUserMembership.desktopNotificationLevel = + membership.desktopNotificationLevel; + model.currentUserMembership.mobileNotificationLevel = + membership.mobileNotificationLevel; return model; }); } else { @@ -97,7 +96,7 @@ export default class ChatChannelsManager extends Service { get unreadCount() { let count = 0; this.publicMessageChannels.forEach((channel) => { - count += channel.currentUserMembership.unread_count || 0; + count += channel.currentUserMembership.unreadCount || 0; }); return count; } @@ -106,9 +105,9 @@ export default class ChatChannelsManager extends Service { let count = 0; this.channels.forEach((channel) => { if (channel.isDirectMessageChannel) { - count += channel.currentUserMembership.unread_count || 0; + count += channel.currentUserMembership.unreadCount || 0; } - count += channel.currentUserMembership.unread_mentions || 0; + count += channel.currentUserMembership.unreadMentions || 0; }); return count; } @@ -159,8 +158,8 @@ export default class ChatChannelsManager extends Service { #sortDirectMessageChannels(channels) { return channels.sort((a, b) => { - const unreadCountA = a.currentUserMembership.unread_count || 0; - const unreadCountB = b.currentUserMembership.unread_count || 0; + const unreadCountA = a.currentUserMembership.unreadCount || 0; + const unreadCountB = b.currentUserMembership.unreadCount || 0; if (unreadCountA === unreadCountB) { return new Date(a.lastMessageSentAt) > new Date(b.lastMessageSentAt) ? -1 diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-subscriptions-manager.js b/plugins/chat/assets/javascripts/discourse/services/chat-subscriptions-manager.js index 3c90c23291b..07a96d4854c 100644 --- a/plugins/chat/assets/javascripts/discourse/services/chat-subscriptions-manager.js +++ b/plugins/chat/assets/javascripts/discourse/services/chat-subscriptions-manager.js @@ -2,6 +2,7 @@ import Service, { inject as service } from "@ember/service"; import I18n from "I18n"; import { bind } from "discourse-common/utils/decorators"; import { CHANNEL_STATUSES } from "discourse/plugins/chat/discourse/models/chat-channel"; +import ChatChannelArchive from "../models/chat-channel-archive"; export default class ChatSubscriptionsManager extends Service { @service store; @@ -125,13 +126,7 @@ export default class ChatSubscriptionsManager extends Service { return; } - channel.setProperties({ - archive_failed: busData.archive_failed, - archive_completed: busData.archive_completed, - archived_messages: busData.archived_messages, - archive_topic_id: busData.archive_topic_id, - total_messages: busData.total_messages, - }); + channel.archive = ChatChannelArchive.create(busData); }); } @@ -139,8 +134,8 @@ export default class ChatSubscriptionsManager extends Service { _onNewMentions(busData) { this.chatChannelsManager.find(busData.channel_id).then((channel) => { const membership = channel.currentUserMembership; - if (busData.message_id > membership?.last_read_message_id) { - membership.unread_mentions = (membership.unread_mentions || 0) + 1; + if (busData.message_id > membership?.lastReadMessageId) { + membership.unreadMentions = (membership.unreadMentions || 0) + 1; } }); } @@ -186,20 +181,18 @@ export default class ChatSubscriptionsManager extends Service { this.chatChannelsManager.find(busData.channel_id).then((channel) => { if (busData.user_id === this.currentUser.id) { // User sent message, update tracking state to no unread - channel.currentUserMembership.last_read_message_id = busData.message_id; + channel.currentUserMembership.lastReadMessageId = busData.message_id; } else { // Ignored user sent message, update tracking state to no unread if (this.currentUser.ignored_users.includes(busData.username)) { - channel.currentUserMembership.last_read_message_id = - busData.message_id; + channel.currentUserMembership.lastReadMessageId = busData.message_id; } else { // Message from other user. Increment trackings state if ( busData.message_id > - (channel.currentUserMembership.last_read_message_id || 0) + (channel.currentUserMembership.lastReadMessageId || 0) ) { - channel.currentUserMembership.unread_count = - channel.currentUserMembership.unread_count + 1; + channel.currentUserMembership.unreadCount++; } } } @@ -256,11 +249,10 @@ export default class ChatSubscriptionsManager extends Service { @bind _updateChannelTrackingData(channelId, trackingData) { this.chatChannelsManager.find(channelId).then((channel) => { - channel.currentUserMembership.last_read_message_id = + channel.currentUserMembership.lastReadMessageId = trackingData.last_read_message_id; - channel.currentUserMembership.unread_count = trackingData.unread_count; - channel.currentUserMembership.unread_mentions = - trackingData.mention_count; + channel.currentUserMembership.unreadCount = trackingData.unread_count; + channel.currentUserMembership.unreadMentions = trackingData.mention_count; }); } @@ -289,7 +281,7 @@ export default class ChatSubscriptionsManager extends Service { channel.isDirectMessageChannel && !channel.currentUserMembership.following ) { - channel.currentUserMembership.unread_count = 1; + channel.currentUserMembership.unreadCount = 1; } this.chatChannelsManager.follow(channel); @@ -341,9 +333,7 @@ export default class ChatSubscriptionsManager extends Service { .find(busData.chat_channel_id, { fetchIfNotFound: false }) .then((channel) => { if (channel) { - channel.setProperties({ - memberships_count: busData.memberships_count, - }); + channel.membershipsCount = busData.memberships_count; this.appEvents.trigger("chat:refresh-channel-members"); } }); @@ -353,11 +343,9 @@ export default class ChatSubscriptionsManager extends Service { _onChannelEdits(busData) { this.chatChannelsManager.find(busData.chat_channel_id).then((channel) => { if (channel) { - channel.setProperties({ - title: busData.name, - description: busData.description, - slug: busData.slug, - }); + channel.title = busData.name; + channel.description = busData.description; + channel.slug = busData.slug; } }); } @@ -365,15 +353,15 @@ export default class ChatSubscriptionsManager extends Service { @bind _onChannelStatus(busData) { this.chatChannelsManager.find(busData.chat_channel_id).then((channel) => { - channel.set("status", busData.status); + channel.status = busData.status; // it is not possible for the user to set their last read message id // if the channel has been archived, because all the messages have // been deleted. we don't want them seeing the blue dot anymore so // just completely reset the unreads if (busData.status === CHANNEL_STATUSES.archived) { - channel.currentUserMembership.unread_count = 0; - channel.currentUserMembership.unread_mentions = 0; + channel.currentUserMembership.unreadCount = 0; + channel.currentUserMembership.unreadMentions = 0; } }); } diff --git a/plugins/chat/assets/javascripts/discourse/services/chat.js b/plugins/chat/assets/javascripts/discourse/services/chat.js index 090a2ea5645..a49416a4130 100644 --- a/plugins/chat/assets/javascripts/discourse/services/chat.js +++ b/plugins/chat/assets/javascripts/discourse/services/chat.js @@ -283,7 +283,7 @@ export default class Chat extends Service { const membership = channel.currentUserMembership; if (channel.isDirectMessageChannel) { - if (!dmChannelWithUnread && membership.unread_count > 0) { + if (!dmChannelWithUnread && membership.unreadCount > 0) { dmChannelWithUnread = channel.id; } else if (!dmChannel) { dmChannel = channel.id; @@ -292,7 +292,7 @@ export default class Chat extends Service { if (membership.unread_mentions > 0) { publicChannelWithMention = channel.id; return; // <- We have a public channel with a mention. Break and return this. - } else if (!publicChannelWithUnread && membership.unread_count > 0) { + } else if (!publicChannelWithUnread && membership.unreadCount > 0) { publicChannelWithUnread = channel.id; } else if ( !defaultChannel && diff --git a/plugins/chat/spec/system/channel_selector_modal_spec.rb b/plugins/chat/spec/system/channel_selector_modal_spec.rb index 0b133238d94..9a6cfa13db5 100644 --- a/plugins/chat/spec/system/channel_selector_modal_spec.rb +++ b/plugins/chat/spec/system/channel_selector_modal_spec.rb @@ -20,6 +20,7 @@ RSpec.describe "Channel selector modal", type: :system, js: true do find("body").send_keys([key_modifier, "k"]) find("#chat-channel-selector-input").fill_in(with: channel_1.title) find(".chat-channel-selection-row[data-id='#{channel_1.id}']").click + channel_page.send_message("Hello world") expect(channel_page).to have_message(text: "Hello world") @@ -33,6 +34,7 @@ RSpec.describe "Channel selector modal", type: :system, js: true do find("body").send_keys([key_modifier, "k"]) find("#chat-channel-selector-input").fill_in(with: user_1.username) find(".chat-channel-selection-row[data-id='#{user_1.id}']").click + channel_page.send_message("Hello world") expect(channel_page).to have_message(text: "Hello world") @@ -69,7 +71,6 @@ RSpec.describe "Channel selector modal", type: :system, js: true do fab!(:channel_1) { Fabricate(:private_category_channel, group: group_1) } it "it doesn’t include limited access channel" do - chat_page.visit_channel(channel_1) find("body").send_keys([key_modifier, "k"]) find("#chat-channel-selector-input").fill_in(with: channel_1.title) diff --git a/plugins/chat/spec/system/drawer_spec.rb b/plugins/chat/spec/system/drawer_spec.rb index e85004efa27..0ebb40685d0 100644 --- a/plugins/chat/spec/system/drawer_spec.rb +++ b/plugins/chat/spec/system/drawer_spec.rb @@ -126,11 +126,11 @@ RSpec.describe "Drawer", type: :system, js: true do session.quit end - expect(page).to have_content("onlyonce", count: 1) + expect(page).to have_content("onlyonce", count: 1, wait: 20) chat_page.visit_channel(channel_2) - expect(page).to have_content("onlyonce", count: 0) + expect(page).to have_content("onlyonce", count: 0, wait: 20) end end end diff --git a/plugins/chat/test/javascripts/components/chat-channel-card-test.js b/plugins/chat/test/javascripts/components/chat-channel-card-test.js index a2f818a3127..aff694db1c2 100644 --- a/plugins/chat/test/javascripts/components/chat-channel-card-test.js +++ b/plugins/chat/test/javascripts/components/chat-channel-card-test.js @@ -10,15 +10,13 @@ module("Discourse Chat | Component | chat-channel-card", function (hooks) { setupRenderingTest(hooks); hooks.beforeEach(function () { - this.set("channel", fabricators.chatChannel()); - this.channel.set( - "description", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - ); + this.channel = fabricators.chatChannel(); + this.channel.description = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; }); test("escapes channel title", async function (assert) { - this.channel.set("title", "
evil
"); + this.channel.title = "
evil
"; await render(hbs``); @@ -26,7 +24,7 @@ module("Discourse Chat | Component | chat-channel-card", function (hooks) { }); test("escapes channel description", async function (assert) { - this.channel.set("description", "
evil
"); + this.channel.description = "
evil
"; await render(hbs``); @@ -34,14 +32,14 @@ module("Discourse Chat | Component | chat-channel-card", function (hooks) { }); test("Closed channel", async function (assert) { - this.channel.set("status", "closed"); + this.channel.status = "closed"; await render(hbs``); assert.true(exists(".chat-channel-card.-closed")); }); test("Archived channel", async function (assert) { - this.channel.set("status", "archived"); + this.channel.status = "archived"; await render(hbs``); assert.true(exists(".chat-channel-card.-archived")); @@ -59,7 +57,7 @@ module("Discourse Chat | Component | chat-channel-card", function (hooks) { }); test("Joined channel", async function (assert) { - this.channel.currentUserMembership.set("following", true); + this.channel.currentUserMembership.following = true; await render(hbs``); assert.strictEqual( @@ -77,7 +75,7 @@ module("Discourse Chat | Component | chat-channel-card", function (hooks) { }); test("Memberships count", async function (assert) { - this.channel.set("membershipsCount", 4); + this.channel.membershipsCount = 4; await render(hbs``); assert.strictEqual( @@ -87,7 +85,7 @@ module("Discourse Chat | Component | chat-channel-card", function (hooks) { }); test("No description", async function (assert) { - this.channel.set("description", null); + this.channel.description = null; await render(hbs``); assert.false(exists(".chat-channel-card__description")); @@ -118,7 +116,7 @@ module("Discourse Chat | Component | chat-channel-card", function (hooks) { }); test("Read restricted chatable", async function (assert) { - this.channel.set("chatable.read_restricted", true); + this.channel.chatable.read_restricted = true; await render(hbs``); assert.true(exists(".d-icon-lock")); diff --git a/plugins/chat/test/javascripts/components/chat-channel-leave-btn-test.js b/plugins/chat/test/javascripts/components/chat-channel-leave-btn-test.js index d75f533bd5e..672f480333d 100644 --- a/plugins/chat/test/javascripts/components/chat-channel-leave-btn-test.js +++ b/plugins/chat/test/javascripts/components/chat-channel-leave-btn-test.js @@ -5,20 +5,15 @@ import hbs from "htmlbars-inline-precompile"; import pretender from "discourse/tests/helpers/create-pretender"; import I18n from "I18n"; import { module, test } from "qunit"; +import fabricators from "../helpers/fabricators"; module("Discourse Chat | Component | chat-channel-leave-btn", function (hooks) { setupRenderingTest(hooks); test("accepts an optional onLeaveChannel callback", async function (assert) { - this.set("foo", 1); - this.set("onLeaveChannel", () => this.set("foo", 2)); - this.set("channel", { - id: 1, - chatable_type: "DirectMessage", - chatable: { - users: [{ id: 1 }], - }, - }); + this.foo = 1; + this.onLeaveChannel = () => (this.foo = 2); + this.channel = fabricators.directMessageChatChannel({ users: [{ id: 1 }] }); await render( hbs`` @@ -34,7 +29,7 @@ module("Discourse Chat | Component | chat-channel-leave-btn", function (hooks) { }); test("has a specific title for direct message channel", async function (assert) { - this.set("channel", { chatable_type: "DirectMessage" }); + this.channel = fabricators.directMessageChatChannel(); await render(hbs``); @@ -43,7 +38,7 @@ module("Discourse Chat | Component | chat-channel-leave-btn", function (hooks) { }); test("has a specific title for message channel", async function (assert) { - this.set("channel", { chatable_type: "Topic" }); + this.channel = fabricators.chatChannel(); await render(hbs``); @@ -53,7 +48,7 @@ module("Discourse Chat | Component | chat-channel-leave-btn", function (hooks) { test("is not visible on mobile", async function (assert) { this.site.mobileView = true; - this.set("channel", { chatable_type: "Topic" }); + this.channel = fabricators.chatChannel(); await render(hbs``); diff --git a/plugins/chat/test/javascripts/components/chat-channel-metadata-test.js b/plugins/chat/test/javascripts/components/chat-channel-metadata-test.js index db01ba779e9..4ed5253b727 100644 --- a/plugins/chat/test/javascripts/components/chat-channel-metadata-test.js +++ b/plugins/chat/test/javascripts/components/chat-channel-metadata-test.js @@ -29,7 +29,7 @@ module("Discourse Chat | Component | chat-channel-metadata", function (hooks) { test("unreadIndicator", async function (assert) { this.channel = fabricators.directMessageChatChannel(); - this.channel.currentUserMembership.unread_count = 1; + this.channel.currentUserMembership.unreadCount = 1; this.unreadIndicator = true; await render( diff --git a/plugins/chat/test/javascripts/components/chat-channel-preview-card-test.js b/plugins/chat/test/javascripts/components/chat-channel-preview-card-test.js index ee8356527f2..99ae91090ef 100644 --- a/plugins/chat/test/javascripts/components/chat-channel-preview-card-test.js +++ b/plugins/chat/test/javascripts/components/chat-channel-preview-card-test.js @@ -15,10 +15,9 @@ module( "channel", fabricators.chatChannel({ chatable_type: "Category" }) ); - this.channel.setProperties({ - description: "Important stuff is announced here.", - title: "announcements", - }); + + this.channel.description = "Important stuff is announced here."; + this.channel.title = "announcements"; this.currentUser.set("has_chat_enabled", true); this.siteSettings.chat_enabled = true; }); @@ -49,7 +48,7 @@ module( }); test("no channel description", async function (assert) { - this.channel.set("description", null); + this.channel.description = null; await render(hbs``); @@ -83,7 +82,7 @@ module( }); test("closed channel", async function (assert) { - this.channel.set("status", "closed"); + this.channel.status = "closed"; await render(hbs``); assert.false( diff --git a/plugins/chat/test/javascripts/components/chat-channel-row-test.js b/plugins/chat/test/javascripts/components/chat-channel-row-test.js index 624d574da95..e4e0891971a 100644 --- a/plugins/chat/test/javascripts/components/chat-channel-row-test.js +++ b/plugins/chat/test/javascripts/components/chat-channel-row-test.js @@ -131,7 +131,7 @@ module("Discourse Chat | Component | chat-channel-row", function (hooks) { assert.dom(".chat-channel-row").doesNotHaveClass("has-unread"); - this.categoryChatChannel.currentUserMembership.unread_count = 1; + this.categoryChatChannel.currentUserMembership.unreadCount = 1; await render(hbs``); diff --git a/plugins/chat/test/javascripts/components/chat-channel-title-test.js b/plugins/chat/test/javascripts/components/chat-channel-title-test.js index c43838b2709..7523815867c 100644 --- a/plugins/chat/test/javascripts/components/chat-channel-title-test.js +++ b/plugins/chat/test/javascripts/components/chat-channel-title-test.js @@ -10,12 +10,9 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) { setupRenderingTest(hooks); test("category channel", async function (assert) { - this.set( - "channel", - fabricators.chatChannel({ - chatable_type: CHATABLE_TYPES.categoryChannel, - }) - ); + this.channel = fabricators.chatChannel({ + chatable_type: CHATABLE_TYPES.categoryChannel, + }); await render(hbs``); @@ -30,13 +27,10 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) { }); test("category channel - escapes title", async function (assert) { - this.set( - "channel", - fabricators.chatChannel({ - chatable_type: CHATABLE_TYPES.categoryChannel, - title: "
evil
", - }) - ); + this.channel = fabricators.chatChannel({ + chatable_type: CHATABLE_TYPES.categoryChannel, + title: "
evil
", + }); await render(hbs``); @@ -44,13 +38,10 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) { }); test("category channel - read restricted", async function (assert) { - this.set( - "channel", - fabricators.chatChannel({ - chatable_type: CHATABLE_TYPES.categoryChannel, - chatable: { read_restricted: true }, - }) - ); + this.channel = fabricators.chatChannel({ + chatable_type: CHATABLE_TYPES.categoryChannel, + chatable: { read_restricted: true }, + }); await render(hbs``); @@ -58,13 +49,10 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) { }); test("category channel - not read restricted", async function (assert) { - this.set( - "channel", - fabricators.chatChannel({ - chatable_type: CHATABLE_TYPES.categoryChannel, - chatable: { read_restricted: false }, - }) - ); + this.channel = fabricators.chatChannel({ + chatable_type: CHATABLE_TYPES.categoryChannel, + chatable: { read_restricted: false }, + }); await render(hbs``); @@ -72,7 +60,7 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) { }); test("direct message channel - one user", async function (assert) { - this.set("channel", fabricators.directMessageChatChannel()); + this.channel = fabricators.directMessageChatChannel(); await render(hbs``); @@ -98,7 +86,7 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) { avatar_template: "/letter_avatar_proxy/v3/letter/t/31188e/{size}.png", }); - this.set("channel", channel); + this.channel = channel; await render(hbs``); diff --git a/plugins/chat/test/javascripts/components/chat-message-test.js b/plugins/chat/test/javascripts/components/chat-message-test.js index afb43b0a575..094e0d75538 100644 --- a/plugins/chat/test/javascripts/components/chat-message-test.js +++ b/plugins/chat/test/javascripts/components/chat-message-test.js @@ -11,8 +11,8 @@ module("Discourse Chat | Component | chat-message", function (hooks) { setupRenderingTest(hooks); function generateMessageProps(messageData = {}) { - const chatChannel = ChatChannel.create({ - chatable: { id: 1 }, + const channel = ChatChannel.create({ + chatable_id: 1, chatable_type: "Category", id: 9, title: "Site", @@ -21,15 +21,15 @@ module("Discourse Chat | Component | chat-message", function (hooks) { unread_count: 0, muted: false, }, - canDeleteSelf: true, - canDeleteOthers: true, - canFlag: true, - userSilenced: false, - canModerate: true, + can_delete_self: true, + can_delete_others: true, + can_flag: true, + user_silenced: false, + can_moderate: true, }); return { message: ChatMessage.create( - chatChannel, + channel, Object.assign( { id: 178, @@ -44,7 +44,7 @@ module("Discourse Chat | Component | chat-message", function (hooks) { messageData ) ), - chatChannel, + channel, afterExpand: () => {}, onHoverMessage: () => {}, messageDidEnterViewport: () => {}, @@ -55,7 +55,7 @@ module("Discourse Chat | Component | chat-message", function (hooks) { const template = hbs` @@ -64,6 +64,7 @@ module("Discourse Chat | Component | chat-message", function (hooks) { test("Message with edits", async function (assert) { this.setProperties(generateMessageProps({ edited: true })); await render(template); + assert.true( exists(".chat-message-edited"), "has the correct edited css class" @@ -83,6 +84,7 @@ module("Discourse Chat | Component | chat-message", function (hooks) { test("Hidden message", async function (assert) { this.setProperties(generateMessageProps({ hidden: true })); await render(template); + assert.true( exists(".chat-message-hidden .chat-message-expand"), "has the correct hidden css class and expand button within" diff --git a/plugins/chat/test/javascripts/components/chat-replying-indicator-test.js b/plugins/chat/test/javascripts/components/chat-replying-indicator-test.js index 3ee425029bd..a0bb90994b4 100644 --- a/plugins/chat/test/javascripts/components/chat-replying-indicator-test.js +++ b/plugins/chat/test/javascripts/components/chat-replying-indicator-test.js @@ -2,9 +2,9 @@ import { setupRenderingTest } from "discourse/tests/helpers/component-test"; import { exists, query } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import fabricators from "../helpers/fabricators"; -import MockPresenceChannel from "../helpers/mock-presence-channel"; import { module, test } from "qunit"; -import { render } from "@ember/test-helpers"; +import { render, settled } from "@ember/test-helpers"; +import { joinChannel } from "discourse/tests/helpers/presence-pretender"; module( "Discourse Chat | Component | chat-replying-indicator", @@ -12,155 +12,148 @@ module( setupRenderingTest(hooks); test("not displayed when no one is replying", async function (assert) { - this.set("chatChannel", fabricators.chatChannel()); - this.set( - "presenceChannel", - MockPresenceChannel.create({ - name: `/chat-reply/${this.chatChannel.id}`, - }) - ); + this.channel = fabricators.chatChannel(); - await render( - hbs`` - ); + await render(hbs``); assert.false(exists(".chat-replying-indicator__text")); }); test("displays indicator when user is replying", async function (assert) { - this.set("chatChannel", fabricators.chatChannel()); - this.set( - "presenceChannel", - MockPresenceChannel.create({ - name: `/chat-reply/${this.chatChannel.id}`, - }) - ); + this.channel = fabricators.chatChannel(); - await render( - hbs`` - ); + await render(hbs``); - const sam = { id: 1, username: "sam" }; - this.set("presenceChannel.users", [sam]); + await joinChannel("/chat-reply/1", { + id: 1, + avatar_template: "/images/avatar.png", + username: "sam", + }); assert.strictEqual( query(".chat-replying-indicator__text").innerText, - `${sam.username} is typing` + `sam is typing` ); }); test("displays indicator when 2 or 3 users are replying", async function (assert) { - this.set("chatChannel", fabricators.chatChannel()); - this.set( - "presenceChannel", - MockPresenceChannel.create({ - name: `/chat-reply/${this.chatChannel.id}`, - }) - ); + this.channel = fabricators.chatChannel(); - await render( - hbs`` - ); + await render(hbs``); - const sam = { id: 1, username: "sam" }; - const mark = { id: 2, username: "mark" }; - this.set("presenceChannel.users", [sam, mark]); + await joinChannel("/chat-reply/1", { + id: 1, + avatar_template: "/images/avatar.png", + username: "sam", + }); + + await joinChannel("/chat-reply/1", { + id: 2, + avatar_template: "/images/avatar.png", + username: "mark", + }); assert.strictEqual( query(".chat-replying-indicator__text").innerText, - `${sam.username} and ${mark.username} are typing` + `sam and mark are typing` ); }); test("displays indicator when 3 users are replying", async function (assert) { - this.set("chatChannel", fabricators.chatChannel()); - this.set( - "presenceChannel", - MockPresenceChannel.create({ - name: `/chat-reply/${this.chatChannel.id}`, - }) - ); + this.channel = fabricators.chatChannel(); - await render( - hbs`` - ); + await render(hbs``); - const sam = { id: 1, username: "sam" }; - const mark = { id: 2, username: "mark" }; - const joffrey = { id: 3, username: "joffrey" }; - this.set("presenceChannel.users", [sam, mark, joffrey]); + await joinChannel("/chat-reply/1", { + id: 1, + avatar_template: "/images/avatar.png", + username: "sam", + }); + + await joinChannel("/chat-reply/1", { + id: 2, + avatar_template: "/images/avatar.png", + username: "mark", + }); + + await joinChannel("/chat-reply/1", { + id: 3, + avatar_template: "/images/avatar.png", + username: "joffrey", + }); assert.strictEqual( query(".chat-replying-indicator__text").innerText, - `${sam.username}, ${mark.username} and ${joffrey.username} are typing` + `sam, mark and joffrey are typing` ); }); test("displays indicator when more than 3 users are replying", async function (assert) { - this.set("chatChannel", fabricators.chatChannel()); - this.set( - "presenceChannel", - MockPresenceChannel.create({ - name: `/chat-reply/${this.chatChannel.id}`, - }) - ); + this.channel = fabricators.chatChannel(); - await render( - hbs`` - ); + await render(hbs``); - const sam = { id: 1, username: "sam" }; - const mark = { id: 2, username: "mark" }; - const joffrey = { id: 3, username: "joffrey" }; - const taylor = { id: 4, username: "taylor" }; - this.set("presenceChannel.users", [sam, mark, joffrey, taylor]); + await joinChannel("/chat-reply/1", { + id: 1, + avatar_template: "/images/avatar.png", + username: "sam", + }); + + await joinChannel("/chat-reply/1", { + id: 2, + avatar_template: "/images/avatar.png", + username: "mark", + }); + + await joinChannel("/chat-reply/1", { + id: 3, + avatar_template: "/images/avatar.png", + username: "joffrey", + }); + + await joinChannel("/chat-reply/1", { + id: 4, + avatar_template: "/images/avatar.png", + username: "taylor", + }); assert.strictEqual( query(".chat-replying-indicator__text").innerText, - `${sam.username}, ${mark.username} and 2 others are typing` + `sam, mark and 2 others are typing` ); }); test("filters current user from list of repliers", async function (assert) { - this.set("chatChannel", fabricators.chatChannel()); - this.set( - "presenceChannel", - MockPresenceChannel.create({ - name: `/chat-reply/${this.chatChannel.id}`, - }) - ); + this.channel = fabricators.chatChannel(); - await render( - hbs`` - ); + await render(hbs``); - const sam = { id: 1, username: "sam" }; - this.set("presenceChannel.users", [sam, this.currentUser]); + await joinChannel("/chat-reply/1", { + id: 1, + avatar_template: "/images/avatar.png", + username: "sam", + }); + + await joinChannel("/chat-reply/1", this.currentUser); assert.strictEqual( query(".chat-replying-indicator__text").innerText, - `${sam.username} is typing` + `sam is typing` ); }); test("resets presence when channel is draft", async function (assert) { - this.set("chatChannel", fabricators.chatChannel()); - this.set( - "presenceChannel", - MockPresenceChannel.create({ - name: `/chat-reply/${this.chatChannel.id}`, - subscribed: true, - }) - ); + this.channel = fabricators.chatChannel(); - await render( - hbs`` - ); + await render(hbs``); - assert.true(this.presenceChannel.subscribed); + assert.dom(".chat-replying-indicator.is-subscribed").exists(); - this.set("chatChannel", fabricators.chatChannel({ isDraft: true })); - assert.false(this.presenceChannel.subscribed); + this.channel.isDraft = true; + + await settled(); + + assert.dom(".chat-replying-indicator.is-subscribed").doesNotExist(); }); } ); diff --git a/plugins/chat/test/javascripts/components/chat-retention-reminder-text-test.js b/plugins/chat/test/javascripts/components/chat-retention-reminder-text-test.js index f4ea8cf864b..a5d8468d99c 100644 --- a/plugins/chat/test/javascripts/components/chat-retention-reminder-text-test.js +++ b/plugins/chat/test/javascripts/components/chat-retention-reminder-text-test.js @@ -1,9 +1,9 @@ -import ChatChannel from "discourse/plugins/chat/discourse/models/chat-channel"; import { setupRenderingTest } from "discourse/tests/helpers/component-test"; import hbs from "htmlbars-inline-precompile"; import I18n from "I18n"; import { module, test } from "qunit"; import { render } from "@ember/test-helpers"; +import fabricators from "../helpers/fabricators"; module( "Discourse Chat | Component | chat-retention-reminder-text", @@ -11,7 +11,7 @@ module( setupRenderingTest(hooks); test("when setting is set on 0", async function (assert) { - this.channel = ChatChannel.create({ chatable_type: "Category" }); + this.channel = fabricators.chatChannel(); this.siteSettings.chat_channel_retention_days = 0; await render( @@ -25,7 +25,7 @@ module( test("when channel is a public channel", async function (assert) { const count = 10; - this.channel = ChatChannel.create({ chatable_type: "Category" }); + this.channel = fabricators.chatChannel(); this.siteSettings.chat_channel_retention_days = count; await render( @@ -39,9 +39,7 @@ module( test("when channel is a DM channel", async function (assert) { const count = 10; - this.channel = ChatChannel.create({ - chatable_type: "DirectMessage", - }); + this.channel = fabricators.directMessageChatChannel(); this.siteSettings.chat_dm_retention_days = count; await render( diff --git a/plugins/chat/test/javascripts/components/direct-message-creator-test.js b/plugins/chat/test/javascripts/components/direct-message-creator-test.js index 822003f7c9b..050df9ebdd7 100644 --- a/plugins/chat/test/javascripts/components/direct-message-creator-test.js +++ b/plugins/chat/test/javascripts/components/direct-message-creator-test.js @@ -2,7 +2,7 @@ import { setupRenderingTest } from "discourse/tests/helpers/component-test"; import { click, fillIn, render } from "@ember/test-helpers"; import hbs from "htmlbars-inline-precompile"; import { exists, query } from "discourse/tests/helpers/qunit-helpers"; -import { createDirectMessageChannelDraft } from "discourse/plugins/chat/discourse/models/chat-channel"; +import ChatChannel from "discourse/plugins/chat/discourse/models/chat-channel"; import { Promise } from "rsvp"; import fabricators from "../helpers/fabricators"; import { module, test } from "qunit"; @@ -25,7 +25,7 @@ module("Discourse Chat | Component | direct-message-creator", function (hooks) { test("search", async function (assert) { this.set("chat", mockChat(this)); - this.set("channel", createDirectMessageChannelDraft()); + this.set("channel", ChatChannel.createDirectMessageChannelDraft()); await render( hbs`` @@ -37,7 +37,7 @@ module("Discourse Chat | Component | direct-message-creator", function (hooks) { test("select/deselect", async function (assert) { this.set("chat", mockChat(this)); - this.set("channel", createDirectMessageChannelDraft()); + this.set("channel", ChatChannel.createDirectMessageChannelDraft()); await render( hbs`` @@ -54,7 +54,7 @@ module("Discourse Chat | Component | direct-message-creator", function (hooks) { test("no search results", async function (assert) { this.set("chat", mockChat(this, { users: [] })); - this.set("channel", createDirectMessageChannelDraft()); + this.set("channel", ChatChannel.createDirectMessageChannelDraft()); await render( hbs`` @@ -66,7 +66,7 @@ module("Discourse Chat | Component | direct-message-creator", function (hooks) { test("loads user on first load", async function (assert) { this.set("chat", mockChat(this)); - this.set("channel", createDirectMessageChannelDraft()); + this.set("channel", ChatChannel.createDirectMessageChannelDraft()); await render( hbs`` @@ -78,7 +78,7 @@ module("Discourse Chat | Component | direct-message-creator", function (hooks) { test("do not load more users after selection", async function (assert) { this.set("chat", mockChat(this)); - this.set("channel", createDirectMessageChannelDraft()); + this.set("channel", ChatChannel.createDirectMessageChannelDraft()); await render( hbs`` @@ -90,7 +90,7 @@ module("Discourse Chat | Component | direct-message-creator", function (hooks) { test("apply is-focused to filter-area on focus input", async function (assert) { this.set("chat", mockChat(this)); - this.set("channel", createDirectMessageChannelDraft()); + this.set("channel", ChatChannel.createDirectMessageChannelDraft()); await render( hbs`` @@ -105,7 +105,7 @@ module("Discourse Chat | Component | direct-message-creator", function (hooks) { test("state is reset on channel change", async function (assert) { this.set("chat", mockChat(this)); - this.set("channel", createDirectMessageChannelDraft()); + this.set("channel", ChatChannel.createDirectMessageChannelDraft()); await render( hbs`` @@ -115,7 +115,7 @@ module("Discourse Chat | Component | direct-message-creator", function (hooks) { assert.strictEqual(query(".filter-usernames").value, "hawk"); this.set("channel", fabricators.chatChannel()); - this.set("channel", createDirectMessageChannelDraft()); + this.set("channel", ChatChannel.createDirectMessageChannelDraft()); assert.strictEqual(query(".filter-usernames").value, ""); assert.true(exists(".filter-area.is-focused")); @@ -129,7 +129,7 @@ module("Discourse Chat | Component | direct-message-creator", function (hooks) { }; const chat = mockChat(this, { users: [userWithStatus] }); this.set("chat", chat); - this.set("channel", createDirectMessageChannelDraft()); + this.set("channel", ChatChannel.createDirectMessageChannelDraft()); await render( hbs`` diff --git a/plugins/chat/test/javascripts/helpers/chat-pretenders.js b/plugins/chat/test/javascripts/helpers/chat-pretenders.js index a72c917f7d4..8045130e842 100644 --- a/plugins/chat/test/javascripts/helpers/chat-pretenders.js +++ b/plugins/chat/test/javascripts/helpers/chat-pretenders.js @@ -138,7 +138,7 @@ export function directMessageChannelPretender( opts = { unread_count: 0, muted: false } ) { let copy = cloneJSON(directMessageChannels[0]); - copy.chat_channel.currentUserMembership.unread_count = opts.unread_count; + copy.chat_channel.currentUserMembership.unreadCount = opts.unread_count; copy.chat_channel.currentUserMembership.muted = opts.muted; server.get("/chat/chat_channels/75.json", () => helper.response(copy)); } @@ -150,13 +150,13 @@ export function chatChannelPretender(server, helper, changes = []) { let found; found = copy.public_channels.find((c) => c.id === change.id); if (found) { - found.currentUserMembership.unread_count = change.unread_count; + found.currentUserMembership.unreadCount = change.unread_count; found.currentUserMembership.muted = change.muted; } if (!found) { found = copy.direct_message_channels.find((c) => c.id === change.id); if (found) { - found.currentUserMembership.unread_count = change.unread_count; + found.currentUserMembership.unreadCount = change.unread_count; found.currentUserMembership.muted = change.muted; } } diff --git a/plugins/chat/test/javascripts/helpers/mock-presence-channel.js b/plugins/chat/test/javascripts/helpers/mock-presence-channel.js deleted file mode 100644 index 320529dfbde..00000000000 --- a/plugins/chat/test/javascripts/helpers/mock-presence-channel.js +++ /dev/null @@ -1,15 +0,0 @@ -import EmberObject from "@ember/object"; - -export default class MockPresenceChannel extends EmberObject { - users = []; - name = null; - subscribed = false; - - async unsubscribe() { - this.set("subscribed", false); - } - - async subscribe() { - this.set("subscribed", true); - } -} diff --git a/plugins/chat/test/javascripts/unit/services/chat-guardian-test.js b/plugins/chat/test/javascripts/unit/services/chat-guardian-test.js index cc9fb4f171a..05fd86d5041 100644 --- a/plugins/chat/test/javascripts/unit/services/chat-guardian-test.js +++ b/plugins/chat/test/javascripts/unit/services/chat-guardian-test.js @@ -83,12 +83,12 @@ acceptance("Discourse Chat | Unit | Service | chat-guardian", function (needs) { set(this.currentUser, "admin", true); set(this.currentUser, "moderator", true); - channel.set("status", "read_only"); + channel.status = "read_only"; assert.notOk(this.chatGuardian.canArchiveChannel(channel)); - channel.set("status", "open"); + channel.status = "open"; - channel.set("status", "archived"); + channel.status = "archived"; assert.notOk(this.chatGuardian.canArchiveChannel(channel)); - channel.set("status", "open"); + channel.status = "open"; }); });