2026-04-18 11:55:01 +00:00
|
|
|
import MessagePageViewModel from "../Pages/messagePageViewModel";
|
|
|
|
|
import CoreViewModel from "../Global/coreViewModel";
|
2026-09-23 00:09:09 +02:00
|
|
|
import * as React from "../../react";
|
2026-04-06 20:47:49 +00:00
|
|
|
import {
|
|
|
|
|
ChatMessage,
|
|
|
|
|
ChatMessageReaction,
|
2026-04-08 14:02:12 +00:00
|
|
|
ChatMessageStatuses,
|
2026-04-07 18:39:55 +00:00
|
|
|
ReactionSymbols,
|
2026-04-06 20:47:49 +00:00
|
|
|
} from "../../Model/Chat/chatModel";
|
2024-07-21 01:12:35 +02:00
|
|
|
|
|
|
|
|
export default class ChatMessageViewModel {
|
2026-04-01 08:29:39 +00:00
|
|
|
// data
|
|
|
|
|
chatMessage: ChatMessage;
|
2026-09-09 00:04:27 +02:00
|
|
|
channel: string = "";
|
|
|
|
|
sender: string = "";
|
|
|
|
|
dateSent: string = "";
|
2026-04-01 08:29:39 +00:00
|
|
|
body: React.State<string> = new React.State("");
|
2026-04-14 13:15:38 +00:00
|
|
|
inlineReply: ChatMessageViewModel | undefined = undefined;
|
2026-09-23 14:44:34 +02:00
|
|
|
replies: React.MapState<ChatMessageViewModel> = new React.MapState();
|
|
|
|
|
replyCount: React.State<number> = React.createProxyState([this.replies], ()=>this.replies.value.size);
|
2026-04-08 14:02:12 +00:00
|
|
|
status: React.State<ChatMessageStatuses | any> = new React.State<any>(
|
2026-04-01 08:29:39 +00:00
|
|
|
undefined,
|
|
|
|
|
);
|
|
|
|
|
sentByUser: boolean;
|
2024-07-26 03:14:55 +02:00
|
|
|
|
2026-04-11 21:01:23 +00:00
|
|
|
isHidden = new React.State<boolean>(false);
|
|
|
|
|
|
2026-04-11 17:47:24 +00:00
|
|
|
allReactions = new React.MapState<ChatMessageReaction>();
|
2026-04-11 19:26:13 +00:00
|
|
|
userReaction = new React.State<ReactionSymbols | string | undefined>(
|
|
|
|
|
undefined,
|
|
|
|
|
);
|
2026-04-11 17:47:24 +00:00
|
|
|
reactionsThumbsUp = React.MapState<ChatMessageReaction>;
|
|
|
|
|
reactionsCheck = React.MapState<ChatMessageReaction>;
|
|
|
|
|
reactionsStop = React.MapState<ChatMessageReaction>;
|
|
|
|
|
reactionsAttention = React.MapState<ChatMessageReaction>;
|
|
|
|
|
reactionsDoubleAttention = React.MapState<ChatMessageReaction>;
|
|
|
|
|
reactionsQuestion = React.MapState<ChatMessageReaction>;
|
2026-04-06 20:47:49 +00:00
|
|
|
|
2026-04-11 17:47:24 +00:00
|
|
|
generateReactionCountProxyState = (
|
|
|
|
|
content: ReactionSymbols,
|
|
|
|
|
): React.State<number> => {
|
|
|
|
|
return React.createProxyState(
|
|
|
|
|
[this.allReactions],
|
|
|
|
|
() =>
|
|
|
|
|
[...this.allReactions.value.values()].filter(
|
|
|
|
|
(x) => x.content == content,
|
|
|
|
|
).length,
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
reactionsThumbsUpCount = this.generateReactionCountProxyState(
|
|
|
|
|
ReactionSymbols.ThumbsUp,
|
2026-04-07 18:39:55 +00:00
|
|
|
);
|
2026-04-11 17:47:24 +00:00
|
|
|
reactionsCheckCount = this.generateReactionCountProxyState(
|
|
|
|
|
ReactionSymbols.Check,
|
2026-04-07 18:39:55 +00:00
|
|
|
);
|
2026-04-11 17:47:24 +00:00
|
|
|
reactionsStopCount = this.generateReactionCountProxyState(
|
|
|
|
|
ReactionSymbols.Stop,
|
2026-04-08 11:24:33 +00:00
|
|
|
);
|
2026-04-11 17:47:24 +00:00
|
|
|
reactionsAttentionCount = this.generateReactionCountProxyState(
|
|
|
|
|
ReactionSymbols.Attention,
|
2026-04-07 18:39:55 +00:00
|
|
|
);
|
2026-04-11 17:47:24 +00:00
|
|
|
reactionsDoubleAttentionCount = this.generateReactionCountProxyState(
|
|
|
|
|
ReactionSymbols.DoubleAttention,
|
2026-04-07 18:39:55 +00:00
|
|
|
);
|
2026-04-11 17:47:24 +00:00
|
|
|
reactionsQuestionCount = this.generateReactionCountProxyState(
|
|
|
|
|
ReactionSymbols.Question,
|
2026-04-07 18:39:55 +00:00
|
|
|
);
|
|
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
// state
|
|
|
|
|
isPresentingInfoModal: React.State<boolean> = new React.State(false);
|
2024-07-21 01:12:35 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
// methods
|
|
|
|
|
copyMessage = (): void => {
|
|
|
|
|
navigator.clipboard.writeText(this.body.value);
|
|
|
|
|
};
|
|
|
|
|
resendMessage = (): void => {
|
|
|
|
|
this.messagePageViewModel.sendMessageFromBody(this.body.value);
|
|
|
|
|
};
|
|
|
|
|
decryptMessage = (): void => {
|
|
|
|
|
this.messagePageViewModel.decryptMessage(this);
|
|
|
|
|
};
|
2024-07-21 13:13:41 +02:00
|
|
|
|
2026-04-14 13:15:38 +00:00
|
|
|
reply = (): void => {
|
2026-04-15 12:47:10 +00:00
|
|
|
this.messagePageViewModel.setReply(this);
|
2026-04-14 13:15:38 +00:00
|
|
|
this.hideInfoModal();
|
|
|
|
|
};
|
|
|
|
|
cancelReply = (): void => {
|
|
|
|
|
if (this.messagePageViewModel.replyingMessage.value != this) return;
|
2026-04-15 12:47:10 +00:00
|
|
|
this.messagePageViewModel.setReply(undefined);
|
2026-04-14 13:15:38 +00:00
|
|
|
};
|
|
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
// view
|
|
|
|
|
showInfoModal = (): void => {
|
|
|
|
|
this.isPresentingInfoModal.value = true;
|
|
|
|
|
};
|
2024-07-23 13:09:46 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
hideInfoModal = (): void => {
|
|
|
|
|
this.isPresentingInfoModal.value = false;
|
|
|
|
|
};
|
2024-07-23 13:09:46 +02:00
|
|
|
|
2026-04-06 20:47:49 +00:00
|
|
|
// reactions
|
2026-04-07 18:48:01 +00:00
|
|
|
handleReaction = (reaction: ChatMessageReaction): void => {
|
2026-04-11 17:47:24 +00:00
|
|
|
if (reaction.isDeleting) {
|
|
|
|
|
this.allReactions.remove(reaction.sender);
|
|
|
|
|
} else {
|
|
|
|
|
this.allReactions.set(reaction.sender, reaction);
|
2026-04-07 18:48:01 +00:00
|
|
|
}
|
|
|
|
|
|
2026-04-11 19:26:13 +00:00
|
|
|
if (reaction.sender != this.coreViewModel.settingsModel.username)
|
|
|
|
|
return;
|
|
|
|
|
this.userReaction.value = reaction.isDeleting
|
|
|
|
|
? undefined
|
|
|
|
|
: reaction.content;
|
2026-04-06 20:47:49 +00:00
|
|
|
};
|
|
|
|
|
|
2026-04-07 18:48:01 +00:00
|
|
|
sendReaction = (content: ReactionSymbols, isDeleting: boolean): void => {
|
2026-04-08 20:31:25 +00:00
|
|
|
this.messagePageViewModel.sendReaction(
|
|
|
|
|
this.chatMessage.id,
|
|
|
|
|
content,
|
|
|
|
|
isDeleting,
|
|
|
|
|
);
|
2026-04-07 18:39:55 +00:00
|
|
|
};
|
|
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
// load
|
|
|
|
|
loadData = (): void => {
|
|
|
|
|
this.channel = this.chatMessage.channel;
|
|
|
|
|
this.sender = this.chatMessage.sender;
|
|
|
|
|
this.dateSent = new Date(this.chatMessage.dateSent).toLocaleString();
|
|
|
|
|
this.body.value = this.chatMessage.body;
|
|
|
|
|
this.status.value = this.chatMessage.status;
|
2026-04-14 13:15:38 +00:00
|
|
|
|
|
|
|
|
if (this.chatMessage.inlineReplyId) {
|
2026-04-15 12:47:10 +00:00
|
|
|
this.inlineReply =
|
|
|
|
|
this.messagePageViewModel.chatMessageViewModels.value.get(
|
|
|
|
|
this.chatMessage.inlineReplyId,
|
|
|
|
|
);
|
2026-09-23 14:44:34 +02:00
|
|
|
this.inlineReply.replies.set(this.chatMessage.id, this);
|
2026-04-14 13:15:38 +00:00
|
|
|
}
|
2026-04-01 08:29:39 +00:00
|
|
|
};
|
2024-07-21 13:13:41 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
// init
|
|
|
|
|
constructor(
|
2026-04-13 10:58:21 +00:00
|
|
|
public readonly coreViewModel: CoreViewModel,
|
|
|
|
|
public readonly messagePageViewModel: MessagePageViewModel,
|
2026-04-01 08:29:39 +00:00
|
|
|
chatMessage: ChatMessage,
|
|
|
|
|
sentByUser: boolean,
|
|
|
|
|
) {
|
|
|
|
|
this.chatMessage = chatMessage;
|
|
|
|
|
this.sentByUser = sentByUser;
|
|
|
|
|
this.loadData();
|
2026-04-11 21:01:23 +00:00
|
|
|
|
2026-09-23 14:44:34 +02:00
|
|
|
let hideForReactions: boolean = false;
|
|
|
|
|
let hideForReplyView: boolean = false;
|
|
|
|
|
|
|
|
|
|
const updateHiding = () => {
|
|
|
|
|
this.isHidden.value = hideForReactions || hideForReplyView;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-11 21:01:23 +00:00
|
|
|
this.messagePageViewModel.reactionFilter.subscribe((content) => {
|
|
|
|
|
if (content == undefined) {
|
2026-09-23 14:44:34 +02:00
|
|
|
hideForReactions = false;
|
2026-04-11 21:01:23 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-13 11:23:17 +00:00
|
|
|
let count: number = 0;
|
2026-04-11 21:01:23 +00:00
|
|
|
switch (content) {
|
|
|
|
|
case ReactionSymbols.ThumbsUp: {
|
|
|
|
|
count = this.reactionsThumbsUpCount.value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ReactionSymbols.Check: {
|
|
|
|
|
count = this.reactionsCheckCount.value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ReactionSymbols.Stop: {
|
|
|
|
|
count = this.reactionsStopCount.value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ReactionSymbols.Attention: {
|
|
|
|
|
count = this.reactionsAttentionCount.value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ReactionSymbols.DoubleAttention: {
|
|
|
|
|
count = this.reactionsDoubleAttentionCount.value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ReactionSymbols.Question: {
|
|
|
|
|
count = this.reactionsQuestionCount.value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-23 14:44:34 +02:00
|
|
|
hideForReactions = count == 0;
|
|
|
|
|
updateHiding();
|
2026-04-12 11:58:45 +00:00
|
|
|
});
|
2026-09-23 14:44:34 +02:00
|
|
|
|
|
|
|
|
this.messagePageViewModel.replyViewSelectedMessage.subscribe(selectedMessage => {
|
|
|
|
|
if (selectedMessage == undefined) hideForReplyView = false;
|
|
|
|
|
else if (selectedMessage == this) hideForReplyView = false;
|
|
|
|
|
else if (selectedMessage == this.inlineReply) hideForReplyView = false;
|
|
|
|
|
else hideForReplyView = true;
|
|
|
|
|
updateHiding();
|
|
|
|
|
})
|
2026-04-01 08:29:39 +00:00
|
|
|
}
|
2024-07-21 01:12:35 +02:00
|
|
|
}
|