204 lines
5.3 KiB
JavaScript
204 lines
5.3 KiB
JavaScript
import User from "discourse/models/user";
|
|
import { cached, tracked } from "@glimmer/tracking";
|
|
import { TrackedArray, TrackedObject } from "@ember-compat/tracked-built-ins";
|
|
import ChatMessageReaction from "discourse/plugins/chat/discourse/models/chat-message-reaction";
|
|
import Bookmark from "discourse/models/bookmark";
|
|
import I18n from "I18n";
|
|
import guid from "pretty-text/guid";
|
|
|
|
export default class ChatMessage {
|
|
static cookFunction = null;
|
|
|
|
static create(channel, args = {}) {
|
|
return new ChatMessage(channel, args);
|
|
}
|
|
|
|
static createStagedMessage(channel, args = {}) {
|
|
args.id = guid();
|
|
args.staged = true;
|
|
return new ChatMessage(channel, args);
|
|
}
|
|
|
|
@tracked id;
|
|
@tracked error;
|
|
@tracked selected;
|
|
@tracked channel;
|
|
@tracked staged = false;
|
|
@tracked channelId;
|
|
@tracked createdAt;
|
|
@tracked deletedAt;
|
|
@tracked uploads;
|
|
@tracked excerpt;
|
|
@tracked message;
|
|
@tracked threadId;
|
|
@tracked reactions;
|
|
@tracked reviewableId;
|
|
@tracked user;
|
|
@tracked cooked;
|
|
@tracked inReplyTo;
|
|
@tracked expanded;
|
|
@tracked bookmark;
|
|
@tracked userFlagStatus;
|
|
@tracked hidden;
|
|
@tracked version = 0;
|
|
@tracked edited;
|
|
@tracked chatWebhookEvent = new TrackedObject();
|
|
@tracked mentionWarning;
|
|
@tracked availableFlags;
|
|
@tracked newest = false;
|
|
@tracked highlighted = false;
|
|
@tracked firstOfResults = false;
|
|
|
|
constructor(channel, args = {}) {
|
|
this.channel = channel;
|
|
this.id = args.id;
|
|
this.newest = args.newest;
|
|
this.firstOfResults = args.firstOfResults;
|
|
this.staged = args.staged;
|
|
this.edited = args.edited;
|
|
this.availableFlags = args.available_flags;
|
|
this.hidden = args.hidden;
|
|
this.threadId = args.thread_id;
|
|
this.channelId = args.chat_channel_id;
|
|
this.chatWebhookEvent = args.chat_webhook_event;
|
|
this.createdAt = args.created_at;
|
|
this.deletedAt = args.deleted_at;
|
|
this.excerpt = args.excerpt;
|
|
this.reviewableId = args.reviewable_id;
|
|
this.userFlagStatus = args.user_flag_status;
|
|
this.inReplyTo = args.in_reply_to
|
|
? ChatMessage.create(channel, args.in_reply_to)
|
|
: null;
|
|
this.message = args.message;
|
|
this.cooked = args.cooked || ChatMessage.cookFunction(this.message);
|
|
this.reactions = this.#initChatMessageReactionModel(
|
|
args.id,
|
|
args.reactions
|
|
);
|
|
this.uploads = new TrackedArray(args.uploads || []);
|
|
this.user = this.#initUserModel(args.user);
|
|
this.bookmark = args.bookmark ? Bookmark.create(args.bookmark) : null;
|
|
}
|
|
|
|
get read() {
|
|
return this.channel.currentUserMembership?.last_read_message_id >= this.id;
|
|
}
|
|
|
|
get firstMessageOfTheDayAt() {
|
|
if (!this.previousMessage) {
|
|
return this.#calendarDate(this.createdAt);
|
|
}
|
|
|
|
if (
|
|
!this.#areDatesOnSameDay(
|
|
new Date(this.previousMessage.createdAt),
|
|
new Date(this.createdAt)
|
|
)
|
|
) {
|
|
return this.#calendarDate(this.createdAt);
|
|
}
|
|
}
|
|
|
|
#calendarDate(date) {
|
|
return moment(date).calendar(moment(), {
|
|
sameDay: `[${I18n.t("chat.chat_message_separator.today")}]`,
|
|
lastDay: `[${I18n.t("chat.chat_message_separator.yesterday")}]`,
|
|
lastWeek: "LL",
|
|
sameElse: "LL",
|
|
});
|
|
}
|
|
|
|
@cached
|
|
get index() {
|
|
return this.channel.messages.indexOf(this);
|
|
}
|
|
|
|
@cached
|
|
get previousMessage() {
|
|
return this.channel?.messages?.objectAt?.(this.index - 1);
|
|
}
|
|
|
|
@cached
|
|
get nextMessage() {
|
|
return this.channel?.messages?.objectAt?.(this.index + 1);
|
|
}
|
|
|
|
incrementVersion() {
|
|
this.version++;
|
|
}
|
|
|
|
react(emoji, action, actor, currentUserId) {
|
|
const selfReaction = actor.id === currentUserId;
|
|
const existingReaction = this.reactions.find(
|
|
(reaction) => reaction.emoji === emoji
|
|
);
|
|
|
|
if (existingReaction) {
|
|
if (action === "add") {
|
|
if (selfReaction && existingReaction.reacted) {
|
|
return;
|
|
}
|
|
|
|
// we might receive a message bus event while loading a channel who would
|
|
// already have the reaction added to the message
|
|
if (existingReaction.users.find((user) => user.id === actor.id)) {
|
|
return;
|
|
}
|
|
|
|
existingReaction.count = existingReaction.count + 1;
|
|
if (selfReaction) {
|
|
existingReaction.reacted = true;
|
|
}
|
|
existingReaction.users.pushObject(actor);
|
|
} else {
|
|
existingReaction.count = existingReaction.count - 1;
|
|
|
|
if (selfReaction) {
|
|
existingReaction.reacted = false;
|
|
}
|
|
|
|
if (existingReaction.count === 0) {
|
|
this.reactions.removeObject(existingReaction);
|
|
} else {
|
|
existingReaction.users.removeObject(
|
|
existingReaction.users.find((user) => user.id === actor.id)
|
|
);
|
|
}
|
|
}
|
|
} else {
|
|
if (action === "add") {
|
|
this.reactions.pushObject(
|
|
ChatMessageReaction.create({
|
|
count: 1,
|
|
emoji,
|
|
reacted: selfReaction,
|
|
users: [actor],
|
|
})
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
#initChatMessageReactionModel(messageId, reactions = []) {
|
|
return reactions.map((reaction) =>
|
|
ChatMessageReaction.create(Object.assign({ messageId }, reaction))
|
|
);
|
|
}
|
|
|
|
#initUserModel(user) {
|
|
if (!user || user instanceof User) {
|
|
return user;
|
|
}
|
|
|
|
return User.create(user);
|
|
}
|
|
|
|
#areDatesOnSameDay(a, b) {
|
|
return (
|
|
a.getFullYear() === b.getFullYear() &&
|
|
a.getMonth() === b.getMonth() &&
|
|
a.getDate() === b.getDate()
|
|
);
|
|
}
|
|
}
|