It was quite an oddball because its a global subscription created on each channel. channels manager now allows us to elegantly solve this case.
310 lines
8.6 KiB
JavaScript
310 lines
8.6 KiB
JavaScript
import Service, { inject as service } from "@ember/service";
|
|
import { bind } from "discourse-common/utils/decorators";
|
|
import { CHANNEL_STATUSES } from "discourse/plugins/chat/discourse/models/chat-channel";
|
|
|
|
export default class ChatSubscriptionsManager extends Service {
|
|
@service store;
|
|
@service chatChannelsManager;
|
|
@service currentUser;
|
|
@service appEvents;
|
|
|
|
_channelSubscriptions = new Set();
|
|
|
|
startChannelSubscription(channel) {
|
|
if (
|
|
channel.currentUserMembership.muted ||
|
|
this._channelSubscriptions.has(channel.id)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
this._channelSubscriptions.add(channel.id);
|
|
|
|
if (!channel.isDirectMessageChannel) {
|
|
this._startChannelMentionsSubscription(channel);
|
|
}
|
|
|
|
this._startChannelNewMessagesSubscription(channel);
|
|
}
|
|
|
|
stopChannelSubscription(channel) {
|
|
this.messageBus.unsubscribe(
|
|
`/chat/${channel.id}/new-messages`,
|
|
this._onNewMessages
|
|
);
|
|
if (!channel.isDirectMessageChannel) {
|
|
this.messageBus.unsubscribe(
|
|
`/chat/${channel.id}/new-mentions`,
|
|
this._onNewMentions
|
|
);
|
|
}
|
|
|
|
this._channelSubscriptions.delete(channel.id);
|
|
}
|
|
|
|
startChannelsSubscriptions(messageBusIds) {
|
|
this._startNewChannelSubscription(messageBusIds.new_channel);
|
|
this._startChannelArchiveStatusSubscription(messageBusIds.archive_status);
|
|
this._startUserTrackingStateSubscription(messageBusIds.user_tracking_state);
|
|
this._startChannelsEditsSubscription(messageBusIds.channel_edits);
|
|
this._startChannelsStatusChangesSubscription(messageBusIds.channel_status);
|
|
this._startChannelsMetadataChangesSubscription(
|
|
messageBusIds.channel_metadata
|
|
);
|
|
}
|
|
|
|
stopChannelsSubscriptions() {
|
|
this._stopNewChannelSubscription();
|
|
this._stopChannelArchiveStatusSubscription();
|
|
this._stopUserTrackingStateSubscription();
|
|
this._stopChannelsEditsSubscription();
|
|
this._stopChannelsStatusChangesSubscription();
|
|
this._stopChannelsMetadataChangesSubscription();
|
|
|
|
(this.chatChannelsManager.channels || []).forEach((channel) => {
|
|
this.stopChannelSubscription(channel);
|
|
});
|
|
}
|
|
|
|
_startChannelArchiveStatusSubscription(lastId) {
|
|
if (this.currentUser.admin) {
|
|
this.messageBus.subscribe(
|
|
"/chat/channel-archive-status",
|
|
this._onChannelArchiveStatusUpdate,
|
|
lastId
|
|
);
|
|
}
|
|
}
|
|
|
|
_stopChannelArchiveStatusSubscription() {
|
|
if (this.currentUser.admin) {
|
|
this.messageBus.unsubscribe(
|
|
"/chat/channel-archive-status",
|
|
this._onChannelArchiveStatusUpdate
|
|
);
|
|
}
|
|
}
|
|
|
|
_startChannelMentionsSubscription(channel) {
|
|
this.messageBus.subscribe(
|
|
`/chat/${channel.id}/new-mentions`,
|
|
this._onNewMentions,
|
|
channel.meta.message_bus_last_ids.new_mentions
|
|
);
|
|
}
|
|
|
|
@bind
|
|
_onChannelArchiveStatusUpdate(busData) {
|
|
// we don't want to fetch a channel we don't have locally because archive status changed
|
|
this.chatChannelsManager
|
|
.find(busData.chat_channel_id, { fetchIfNotFound: false })
|
|
.then((channel) => {
|
|
if (!channel) {
|
|
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,
|
|
});
|
|
});
|
|
}
|
|
|
|
@bind
|
|
_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;
|
|
}
|
|
});
|
|
}
|
|
|
|
_startChannelNewMessagesSubscription(channel) {
|
|
this.messageBus.subscribe(
|
|
`/chat/${channel.id}/new-messages`,
|
|
this._onNewMessages,
|
|
channel.meta.message_bus_last_ids.new_messages
|
|
);
|
|
}
|
|
|
|
@bind
|
|
_onNewMessages(busData) {
|
|
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;
|
|
} 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;
|
|
} else {
|
|
// Message from other user. Increment trackings state
|
|
if (
|
|
busData.message_id >
|
|
(channel.currentUserMembership.last_read_message_id || 0)
|
|
) {
|
|
channel.currentUserMembership.unread_count =
|
|
channel.currentUserMembership.unread_count + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
channel.set("last_message_sent_at", new Date());
|
|
});
|
|
}
|
|
|
|
_startUserTrackingStateSubscription(lastId) {
|
|
if (!this.currentUser) {
|
|
return;
|
|
}
|
|
|
|
this.messageBus.subscribe(
|
|
`/chat/user-tracking-state/${this.currentUser.id}`,
|
|
this._onUserTrackingStateUpdate,
|
|
lastId
|
|
);
|
|
}
|
|
|
|
_stopUserTrackingStateSubscription() {
|
|
if (!this.currentUser) {
|
|
return;
|
|
}
|
|
|
|
this.messageBus.unsubscribe(
|
|
`/chat/user-tracking-state/${this.currentUser.id}`,
|
|
this._onUserTrackingStateUpdate
|
|
);
|
|
}
|
|
|
|
@bind
|
|
_onUserTrackingStateUpdate(busData) {
|
|
this.chatChannelsManager.find(busData.chat_channel_id).then((channel) => {
|
|
if (
|
|
channel?.currentUserMembership?.last_read_message_id <=
|
|
busData.chat_message_id
|
|
) {
|
|
channel.currentUserMembership.last_read_message_id =
|
|
busData.chat_message_id;
|
|
channel.currentUserMembership.unread_count = 0;
|
|
channel.currentUserMembership.unread_mentions = 0;
|
|
}
|
|
});
|
|
}
|
|
|
|
_startNewChannelSubscription(lastId) {
|
|
this.messageBus.subscribe(
|
|
"/chat/new-channel",
|
|
this._onNewChannelSubscription,
|
|
lastId
|
|
);
|
|
}
|
|
|
|
_stopNewChannelSubscription() {
|
|
this.messageBus.unsubscribe(
|
|
"/chat/new-channel",
|
|
this._onNewChannelSubscription
|
|
);
|
|
}
|
|
|
|
@bind
|
|
_onNewChannelSubscription(data) {
|
|
this.chatChannelsManager.find(data.channel.id).then((channel) => {
|
|
// we need to refrehs here to have correct last message ids
|
|
channel.meta = data.channel.meta;
|
|
|
|
if (
|
|
channel.isDirectMessageChannel &&
|
|
!channel.currentUserMembership.following
|
|
) {
|
|
channel.currentUserMembership.unread_count = 1;
|
|
}
|
|
|
|
this.chatChannelsManager.follow(channel);
|
|
});
|
|
}
|
|
|
|
_startChannelsMetadataChangesSubscription(lastId) {
|
|
this.messageBus.subscribe(
|
|
"/chat/channel-metadata",
|
|
this._onChannelMetadata,
|
|
lastId
|
|
);
|
|
}
|
|
|
|
_startChannelsEditsSubscription(lastId) {
|
|
this.messageBus.subscribe(
|
|
"/chat/channel-edits",
|
|
this._onChannelEdits,
|
|
lastId
|
|
);
|
|
}
|
|
|
|
_startChannelsStatusChangesSubscription(lastId) {
|
|
this.messageBus.subscribe(
|
|
"/chat/channel-status",
|
|
this._onChannelStatus,
|
|
lastId
|
|
);
|
|
}
|
|
|
|
_stopChannelsStatusChangesSubscription() {
|
|
this.messageBus.unsubscribe("/chat/channel-status", this._onChannelStatus);
|
|
}
|
|
|
|
_stopChannelsEditsSubscription() {
|
|
this.messageBus.unsubscribe("/chat/channel-edits", this._onChannelEdits);
|
|
}
|
|
|
|
_stopChannelsMetadataChangesSubscription() {
|
|
this.messageBus.unsubscribe(
|
|
"/chat/channel-metadata",
|
|
this._onChannelMetadata
|
|
);
|
|
}
|
|
|
|
@bind
|
|
_onChannelMetadata(busData) {
|
|
this.chatChannelsManager.find(busData.chat_channel_id).then((channel) => {
|
|
if (channel) {
|
|
channel.setProperties({
|
|
memberships_count: busData.memberships_count,
|
|
});
|
|
this.appEvents.trigger("chat:refresh-channel-members");
|
|
}
|
|
});
|
|
}
|
|
|
|
@bind
|
|
_onChannelEdits(busData) {
|
|
this.chatChannelsManager.find(busData.chat_channel_id).then((channel) => {
|
|
if (channel) {
|
|
channel.setProperties({
|
|
title: busData.name,
|
|
description: busData.description,
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
@bind
|
|
_onChannelStatus(busData) {
|
|
this.chatChannelsManager.find(busData.chat_channel_id).then((channel) => {
|
|
channel.set("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;
|
|
}
|
|
});
|
|
}
|
|
}
|