discourse/plugins/chat/assets/javascripts/discourse/models/chat-channel.js
Joffrey JAFFEUX 09277bc543
FEATURE: my threads page (#24771)
This commit adds a new "My threads" link in sidebar and drawer. This link will open the "/chat/threads" page which contains all threads where the current user is a member. It's ordered by activity (unread and then last message created).

Moreover, the threads list of a channel page is now showing every threads of a channel, and not just the ones where you are a member.
2023-12-11 07:38:07 +01:00

275 lines
6.9 KiB
JavaScript

import { tracked } from "@glimmer/tracking";
import guid from "pretty-text/guid";
import { escapeExpression } from "discourse/lib/utilities";
import Category from "discourse/models/category";
import { getOwnerWithFallback } from "discourse-common/lib/get-owner";
import ChatMessagesManager from "discourse/plugins/chat/discourse/lib/chat-messages-manager";
import ChatThreadsManager from "discourse/plugins/chat/discourse/lib/chat-threads-manager";
import slugifyChannel from "discourse/plugins/chat/discourse/lib/slugify-channel";
import ChatChannelArchive from "discourse/plugins/chat/discourse/models/chat-channel-archive";
import ChatDirectMessage from "discourse/plugins/chat/discourse/models/chat-direct-message";
import ChatMessage from "discourse/plugins/chat/discourse/models/chat-message";
import ChatTrackingState from "discourse/plugins/chat/discourse/models/chat-tracking-state";
import UserChatChannelMembership from "discourse/plugins/chat/discourse/models/user-chat-channel-membership";
export const CHATABLE_TYPES = {
directMessageChannel: "DirectMessage",
categoryChannel: "Category",
};
export const CHANNEL_STATUSES = {
open: "open",
readOnly: "read_only",
closed: "closed",
archived: "archived",
};
export function channelStatusIcon(channelStatus) {
if (channelStatus === CHANNEL_STATUSES.open) {
return null;
}
switch (channelStatus) {
case CHANNEL_STATUSES.closed:
return "lock";
case CHANNEL_STATUSES.readOnly:
return "comment-slash";
case CHANNEL_STATUSES.archived:
return "archive";
}
}
const STAFF_READONLY_STATUSES = [
CHANNEL_STATUSES.readOnly,
CHANNEL_STATUSES.archived,
];
const READONLY_STATUSES = [
CHANNEL_STATUSES.closed,
CHANNEL_STATUSES.readOnly,
CHANNEL_STATUSES.archived,
];
export default class ChatChannel {
static create(args = {}) {
return new ChatChannel(args);
}
@tracked title;
@tracked slug;
@tracked description;
@tracked status;
@tracked activeThread = null;
@tracked meta;
@tracked chatableId;
@tracked chatableType;
@tracked chatableUrl;
@tracked autoJoinUsers = false;
@tracked allowChannelWideMentions = true;
@tracked membershipsCount = 0;
@tracked archive;
@tracked tracking;
@tracked threadingEnabled = false;
@tracked draft;
threadsManager = new ChatThreadsManager(getOwnerWithFallback(this));
messagesManager = new ChatMessagesManager(getOwnerWithFallback(this));
@tracked _currentUserMembership;
@tracked _lastMessage;
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.slug = args.slug;
this.title = args.title;
this.status = args.status;
this.description = args.description;
this.threadingEnabled = args.threading_enabled;
this.autoJoinUsers = args.auto_join_users;
this.allowChannelWideMentions = args.allow_channel_wide_mentions;
this.chatable = this.#initChatable(args.chatable || []);
this.currentUserMembership = args.current_user_membership;
if (args.archive_completed || args.archive_failed) {
this.archive = ChatChannelArchive.create(args);
}
this.tracking = new ChatTrackingState(getOwnerWithFallback(this));
this.lastMessage = args.last_message;
this.meta = args.meta;
}
get unreadThreadsCountSinceLastViewed() {
return Array.from(this.threadsManager.unreadThreadOverview.values()).filter(
(lastReplyCreatedAt) =>
lastReplyCreatedAt >= this.currentUserMembership.lastViewedAt
).length;
}
get unreadThreadsCount() {
return Array.from(this.threadsManager.unreadThreadOverview.values()).length;
}
updateLastViewedAt() {
this.currentUserMembership.lastViewedAt = new Date();
}
get canDeleteSelf() {
return this.meta.can_delete_self;
}
get canDeleteOthers() {
return this.meta.can_delete_others;
}
get canFlag() {
return this.meta.can_flag;
}
get userSilenced() {
return this.meta.user_silenced;
}
get canModerate() {
return this.meta.can_moderate;
}
get escapedTitle() {
return escapeExpression(this.title);
}
get escapedDescription() {
return escapeExpression(this.description);
}
get slugifiedTitle() {
return this.slug || slugifyChannel(this);
}
get routeModels() {
return [this.slugifiedTitle, this.id];
}
get isDirectMessageChannel() {
return this.chatableType === CHATABLE_TYPES.directMessageChannel;
}
get isCategoryChannel() {
return this.chatableType === CHATABLE_TYPES.categoryChannel;
}
get isOpen() {
return !this.status || this.status === CHANNEL_STATUSES.open;
}
get isReadOnly() {
return this.status === CHANNEL_STATUSES.readOnly;
}
get isClosed() {
return this.status === CHANNEL_STATUSES.closed;
}
get isArchived() {
return this.status === CHANNEL_STATUSES.archived;
}
get isJoinable() {
return this.isOpen && !this.isArchived;
}
get isFollowing() {
return this.currentUserMembership.following;
}
get canJoin() {
return this.meta.can_join_chat_channel;
}
async stageMessage(message) {
message.id = guid();
message.staged = true;
message.processed = false;
message.draft = false;
message.createdAt = new Date();
message.channel = this;
if (message.inReplyTo) {
if (!this.threadingEnabled) {
this.messagesManager.addMessages([message]);
}
} else {
this.messagesManager.addMessages([message]);
}
message.manager = this.messagesManager;
}
resetDraft(user) {
this.draft = ChatMessage.createDraftMessage(this, {
user,
});
}
canModifyMessages(user) {
if (user.staff) {
return !STAFF_READONLY_STATUSES.includes(this.status);
}
return !READONLY_STATUSES.includes(this.status);
}
get currentUserMembership() {
return this._currentUserMembership;
}
set currentUserMembership(membership) {
if (membership instanceof UserChatChannelMembership) {
this._currentUserMembership = membership;
} else {
this._currentUserMembership =
UserChatChannelMembership.create(membership);
}
}
get lastMessage() {
return this._lastMessage;
}
set lastMessage(message) {
if (!message) {
this._lastMessage = null;
return;
}
if (message instanceof ChatMessage) {
this._lastMessage = message;
} else {
this._lastMessage = ChatMessage.create(this, message);
}
}
#initChatable(chatable) {
if (
!chatable ||
chatable instanceof Category ||
chatable instanceof ChatDirectMessage
) {
return chatable;
} else {
if (this.isDirectMessageChannel) {
return ChatDirectMessage.create({
users: chatable?.users,
group: chatable?.group,
});
} else {
return Category.create(chatable);
}
}
}
}