add backend for message reactions
This commit is contained in:
Vendored
+117
-1
@@ -603,6 +603,10 @@
|
||||
info: (id) => [...filePaths.chat.chatBase(id), "info"],
|
||||
color: (id) => [...filePaths.chat.chatBase(id), "color"],
|
||||
messages: (id) => [...filePaths.chat.chatBase(id), "messages"],
|
||||
reactions: (id) => [
|
||||
...filePaths.chat.chatBase(id),
|
||||
"reactions"
|
||||
],
|
||||
lastUsedPage: (id) => [
|
||||
...filePaths.chat.chatBase(id),
|
||||
"last-used-page"
|
||||
@@ -1037,6 +1041,7 @@
|
||||
const didStore = this.storeFileContent(fileContent);
|
||||
if (didStore == false) return;
|
||||
this.boardsAndTasksModel.handleFileContent(fileContent);
|
||||
this.chatModel.handleReaction(fileContent);
|
||||
};
|
||||
// methods
|
||||
this.addFileContentAndSend = (fileContent) => {
|
||||
@@ -1203,6 +1208,7 @@
|
||||
// init
|
||||
constructor(storageModel2, connectionModel2, settingsModel2, chatListModel2, chatId) {
|
||||
this.chatMessageHandlerManager = new HandlerManager();
|
||||
this.reactionHandlerManager = new HandlerManager();
|
||||
// paths
|
||||
this.getBasePath = () => {
|
||||
return StorageModel.getPath(
|
||||
@@ -1231,6 +1237,15 @@
|
||||
this.getMessagePath = (id) => {
|
||||
return [...this.getMessageDirPath(), id];
|
||||
};
|
||||
this.getReactionDirPath = () => {
|
||||
return StorageModel.getPath(
|
||||
"chat" /* Chat */,
|
||||
filePaths.chat.reactions(this.id)
|
||||
);
|
||||
};
|
||||
this.getReactionPath = (id) => {
|
||||
return [...this.getReactionDirPath(), id];
|
||||
};
|
||||
// handlers
|
||||
this.handleMessage = (body) => {
|
||||
const chatMessage = parseValidObject(
|
||||
@@ -1242,6 +1257,10 @@
|
||||
this.addMessage(chatMessage);
|
||||
this.setReadStatus(true);
|
||||
};
|
||||
this.handleReaction = (reaction) => {
|
||||
if (!checkMatchesObjectStructure(reaction, ChatMessageReactionReference)) return;
|
||||
this.addReaction(reaction);
|
||||
};
|
||||
this.handleMessageSent = (chatMessage) => {
|
||||
chatMessage.status = "sent" /* Sent */;
|
||||
this.addMessage(chatMessage);
|
||||
@@ -1276,7 +1295,12 @@
|
||||
chatMessage.stringifiedFile
|
||||
);
|
||||
};
|
||||
this.sendMessage = async (body, fileContent) => {
|
||||
this.addReaction = async (reaction) => {
|
||||
const reactionPath = this.getReactionPath(reaction.fileId);
|
||||
this.storageModel.writeStringifiable(reactionPath, reaction);
|
||||
this.reactionHandlerManager.trigger(reaction);
|
||||
};
|
||||
this.getNameAndChannel = () => {
|
||||
const senderName = this.settingsModel.username;
|
||||
if (senderName == "") return false;
|
||||
const allChannels = [this.info.primaryChannel];
|
||||
@@ -1284,6 +1308,12 @@
|
||||
allChannels.push(secondaryChannel);
|
||||
}
|
||||
const combinedChannel = allChannels.join("/");
|
||||
return [senderName, combinedChannel];
|
||||
};
|
||||
this.sendMessage = async (body, fileContent) => {
|
||||
const nameAndChannel = this.getNameAndChannel();
|
||||
if (nameAndChannel == false) return;
|
||||
const [senderName, combinedChannel] = nameAndChannel;
|
||||
const chatMessage = await _ChatModel.createChatMessage(
|
||||
combinedChannel,
|
||||
senderName,
|
||||
@@ -1307,6 +1337,18 @@
|
||||
chatMessage.body = decryptedBody;
|
||||
chatMessage.stringifiedFile = decryptedFile;
|
||||
};
|
||||
this.sendReaction = async (messageId, content) => {
|
||||
const nameAndChannel = this.getNameAndChannel();
|
||||
if (nameAndChannel == false) return;
|
||||
const [senderName, combinedChannel] = nameAndChannel;
|
||||
const reaction = _ChatModel.createMessageReaction(
|
||||
messageId,
|
||||
senderName,
|
||||
content
|
||||
);
|
||||
this.sendMessage("", reaction);
|
||||
this.addReaction(reaction);
|
||||
};
|
||||
this.subscribe = () => {
|
||||
this.connectionModel.addChannel(this.info.primaryChannel);
|
||||
};
|
||||
@@ -1376,6 +1418,7 @@
|
||||
messagePath,
|
||||
ChatMessageReference
|
||||
);
|
||||
if (chatMessage == null) continue;
|
||||
chatMessages.push(chatMessage);
|
||||
}
|
||||
const sorted = chatMessages.sort(
|
||||
@@ -1383,6 +1426,23 @@
|
||||
);
|
||||
return sorted;
|
||||
}
|
||||
get reactions() {
|
||||
const reactionIds = this.storageModel.list(
|
||||
this.getReactionDirPath()
|
||||
);
|
||||
if (!Array.isArray(reactionIds)) return [];
|
||||
const reactions = [];
|
||||
for (const reactionId of reactionIds) {
|
||||
const reactionPath = this.getReactionPath(reactionId);
|
||||
const reaction = this.storageModel.readStringifiable(
|
||||
reactionPath,
|
||||
ChatMessageReactionReference
|
||||
);
|
||||
if (reaction == null) continue;
|
||||
reactions.push(reaction);
|
||||
}
|
||||
return reactions;
|
||||
}
|
||||
// utility
|
||||
static splitChannel(channelString) {
|
||||
return channelString.split("/");
|
||||
@@ -1427,6 +1487,18 @@
|
||||
return chatMessage;
|
||||
};
|
||||
}
|
||||
static {
|
||||
this.createMessageReaction = (messageId, sender, content) => {
|
||||
const fileContent = FileModel2.createFileContent(v4_default(), "reaction");
|
||||
const reaction = {
|
||||
...fileContent,
|
||||
messageId,
|
||||
sender,
|
||||
content
|
||||
};
|
||||
return reaction;
|
||||
};
|
||||
}
|
||||
};
|
||||
var ChatInfoReference = {
|
||||
dataVersion: DATA_VERSION,
|
||||
@@ -1445,6 +1517,16 @@
|
||||
status: "",
|
||||
stringifiedFile: ""
|
||||
};
|
||||
var ChatMessageReactionReference = {
|
||||
dataVersion: DATA_VERSION,
|
||||
fileId: "",
|
||||
fileContentId: "",
|
||||
creationDate: "",
|
||||
type: "reaction",
|
||||
messageId: "",
|
||||
sender: "",
|
||||
content: ""
|
||||
};
|
||||
|
||||
// src/Model/Chat/chatListModel.ts
|
||||
var ChatListModel = class {
|
||||
@@ -1923,6 +2005,11 @@
|
||||
this.status = new State(
|
||||
void 0
|
||||
);
|
||||
this.reactionsThumbsUp = new MapState();
|
||||
this.reactionsCheck = new MapState();
|
||||
this.reactionsAttention = new MapState();
|
||||
this.reactionsDoubleAttention = new MapState();
|
||||
this.reactionsQuestion = new MapState();
|
||||
// state
|
||||
this.isPresentingInfoModal = new State(false);
|
||||
// methods
|
||||
@@ -1942,6 +2029,21 @@
|
||||
this.hideInfoModal = () => {
|
||||
this.isPresentingInfoModal.value = false;
|
||||
};
|
||||
// reactions
|
||||
this.addReaction = (reaction) => {
|
||||
switch (reaction.content) {
|
||||
case "\u{1F44D}":
|
||||
return this.reactionsThumbsUp.set(reaction.fileId, reaction);
|
||||
case "\u2705":
|
||||
return this.reactionsCheck.set(reaction.fileId, reaction);
|
||||
case "\u2757\uFE0F":
|
||||
return this.reactionsAttention.set(reaction.fileId, reaction);
|
||||
case "\u203C\uFE0F":
|
||||
return this.reactionsDoubleAttention.set(reaction.fileId, reaction);
|
||||
case "\u2753":
|
||||
return this.reactionsQuestion.set(reaction.fileId, reaction);
|
||||
}
|
||||
};
|
||||
// load
|
||||
this.loadData = () => {
|
||||
this.channel = this.chatMessage.channel;
|
||||
@@ -1980,6 +2082,9 @@
|
||||
this.chatViewModel.chatModel.addMessage(chatMessage);
|
||||
messageViewModel.loadData();
|
||||
};
|
||||
this.sendReaction = (messageId, content) => {
|
||||
this.chatViewModel.chatModel.sendReaction(messageId, content);
|
||||
};
|
||||
// view
|
||||
this.showChatMessage = (chatMessage) => {
|
||||
const chatMessageViewModel = new ChatMessageViewModel(
|
||||
@@ -1999,12 +2104,20 @@
|
||||
);
|
||||
}
|
||||
};
|
||||
this.showReaction = (reaction) => {
|
||||
const messageViewModel = this.chatMessageViewModels.value.get(reaction.messageId);
|
||||
if (messageViewModel == void 0) return;
|
||||
messageViewModel.addReaction(reaction);
|
||||
};
|
||||
// load
|
||||
this.loadData = () => {
|
||||
this.chatMessageViewModels.clear();
|
||||
for (const chatMessage of this.chatViewModel.chatModel.messages) {
|
||||
this.showChatMessage(chatMessage);
|
||||
}
|
||||
for (const reaction of this.chatViewModel.chatModel.reactions) {
|
||||
this.showReaction(reaction);
|
||||
}
|
||||
};
|
||||
this.chatViewModel = chatViewModel;
|
||||
this.cannotSendMessage = createProxyState(
|
||||
@@ -3149,6 +3262,9 @@
|
||||
this.notificationViewModel.showNotification(chatMessage);
|
||||
}
|
||||
);
|
||||
chatModel.reactionHandlerManager.addHandler((reaction) => {
|
||||
this.messagePageViewModel.showReaction(reaction);
|
||||
});
|
||||
this.loadPageSelection();
|
||||
this.resetColor();
|
||||
this.loadInfo();
|
||||
|
||||
+124
-7
@@ -1,11 +1,16 @@
|
||||
// this file is responsible for managing chats.
|
||||
|
||||
import { DATA_VERSION, ValidObject } from "../Utility/typeSafety";
|
||||
import {
|
||||
checkMatchesObjectStructure,
|
||||
DATA_VERSION,
|
||||
ValidObject,
|
||||
} from "../Utility/typeSafety";
|
||||
import FileModel, { FileContent } from "../Files/fileModel";
|
||||
import {
|
||||
HandlerManager,
|
||||
createTimestamp,
|
||||
localeCompare,
|
||||
parse,
|
||||
parseValidObject,
|
||||
stringify,
|
||||
} from "../Utility/utility";
|
||||
@@ -36,6 +41,8 @@ export default class ChatModel {
|
||||
|
||||
chatMessageHandlerManager: HandlerManager<ChatMessage> =
|
||||
new HandlerManager();
|
||||
reactionHandlerManager: HandlerManager<ChatMessageReaction> =
|
||||
new HandlerManager();
|
||||
|
||||
get secondaryChannels(): string[] {
|
||||
return this.info.secondaryChannels.sort(localeCompare);
|
||||
@@ -74,6 +81,17 @@ export default class ChatModel {
|
||||
return [...this.getMessageDirPath(), id];
|
||||
};
|
||||
|
||||
getReactionDirPath = (): string[] => {
|
||||
return StorageModel.getPath(
|
||||
StorageModelSubPath.Chat,
|
||||
filePaths.chat.reactions(this.id),
|
||||
);
|
||||
};
|
||||
|
||||
getReactionPath = (id: string): string[] => {
|
||||
return [...this.getReactionDirPath(), id];
|
||||
};
|
||||
|
||||
// handlers
|
||||
handleMessage = (body: string): void => {
|
||||
const chatMessage: ChatMessage | null = parseValidObject(
|
||||
@@ -83,11 +101,19 @@ export default class ChatModel {
|
||||
if (chatMessage == null) return;
|
||||
|
||||
chatMessage.status = ChatMessageStatus.Received;
|
||||
this.addMessage(chatMessage);
|
||||
|
||||
this.addMessage(chatMessage);
|
||||
this.setReadStatus(true);
|
||||
};
|
||||
|
||||
handleReaction = (reaction: ChatMessageReaction | any): void => {
|
||||
if (
|
||||
!checkMatchesObjectStructure(reaction, ChatMessageReactionReference)
|
||||
)
|
||||
return;
|
||||
this.addReaction(reaction);
|
||||
};
|
||||
|
||||
handleMessageSent = (chatMessage: ChatMessage): void => {
|
||||
chatMessage.status = ChatMessageStatus.Sent;
|
||||
this.addMessage(chatMessage);
|
||||
@@ -132,10 +158,13 @@ export default class ChatModel {
|
||||
);
|
||||
};
|
||||
|
||||
sendMessage = async (
|
||||
body: string,
|
||||
fileContent?: FileContent<string>,
|
||||
): Promise<boolean> => {
|
||||
addReaction = async (reaction: ChatMessageReaction): Promise<void> => {
|
||||
const reactionPath: string[] = this.getReactionPath(reaction.fileId);
|
||||
this.storageModel.writeStringifiable(reactionPath, reaction);
|
||||
this.reactionHandlerManager.trigger(reaction);
|
||||
};
|
||||
|
||||
getNameAndChannel = (): [string, string] | false => {
|
||||
const senderName = this.settingsModel.username;
|
||||
if (senderName == "") return false;
|
||||
|
||||
@@ -146,6 +175,17 @@ export default class ChatModel {
|
||||
|
||||
const combinedChannel: string = allChannels.join("/");
|
||||
|
||||
return [senderName, combinedChannel];
|
||||
};
|
||||
|
||||
sendMessage = async (
|
||||
body: string,
|
||||
fileContent?: FileContent<string>,
|
||||
): Promise<boolean> => {
|
||||
const nameAndChannel = this.getNameAndChannel();
|
||||
if (nameAndChannel == false) return;
|
||||
const [senderName, combinedChannel] = nameAndChannel;
|
||||
|
||||
const chatMessage: ChatMessage = await ChatModel.createChatMessage(
|
||||
combinedChannel,
|
||||
senderName,
|
||||
@@ -172,6 +212,23 @@ export default class ChatModel {
|
||||
chatMessage.stringifiedFile = decryptedFile;
|
||||
};
|
||||
|
||||
sendReaction = async (
|
||||
messageId: string,
|
||||
content: ReactionSymbol,
|
||||
): Promise<void> => {
|
||||
const nameAndChannel = this.getNameAndChannel();
|
||||
if (nameAndChannel == false) return;
|
||||
const [senderName, combinedChannel] = nameAndChannel;
|
||||
|
||||
const reaction = ChatModel.createMessageReaction(
|
||||
messageId,
|
||||
senderName,
|
||||
content,
|
||||
);
|
||||
this.sendMessage("", reaction);
|
||||
this.addReaction(reaction);
|
||||
};
|
||||
|
||||
subscribe = (): void => {
|
||||
this.connectionModel.addChannel(this.info.primaryChannel);
|
||||
};
|
||||
@@ -231,11 +288,12 @@ export default class ChatModel {
|
||||
const chatMessages: ChatMessage[] = [];
|
||||
for (const messageId of messageIds) {
|
||||
const messagePath: string[] = this.getMessagePath(messageId);
|
||||
const chatMessage: ChatMessage | any =
|
||||
const chatMessage: ChatMessage | null =
|
||||
this.storageModel.readStringifiable(
|
||||
messagePath,
|
||||
ChatMessageReference,
|
||||
);
|
||||
if (chatMessage == null) continue;
|
||||
chatMessages.push(chatMessage);
|
||||
}
|
||||
|
||||
@@ -245,6 +303,27 @@ export default class ChatModel {
|
||||
return sorted;
|
||||
}
|
||||
|
||||
get reactions(): ChatMessageReaction[] {
|
||||
const reactionIds: string[] = this.storageModel.list(
|
||||
this.getReactionDirPath(),
|
||||
);
|
||||
if (!Array.isArray(reactionIds)) return [];
|
||||
|
||||
const reactions: ChatMessageReaction[] = [];
|
||||
for (const reactionId of reactionIds) {
|
||||
const reactionPath: string[] = this.getReactionPath(reactionId);
|
||||
const reaction: ChatMessageReaction | null =
|
||||
this.storageModel.readStringifiable(
|
||||
reactionPath,
|
||||
ChatMessageReactionReference,
|
||||
);
|
||||
if (reaction == null) continue;
|
||||
reactions.push(reaction);
|
||||
}
|
||||
|
||||
return reactions;
|
||||
}
|
||||
|
||||
// init
|
||||
constructor(
|
||||
storageModel: StorageModel,
|
||||
@@ -324,9 +403,27 @@ export default class ChatModel {
|
||||
|
||||
return chatMessage;
|
||||
};
|
||||
|
||||
static createMessageReaction = (
|
||||
messageId: string,
|
||||
sender: string,
|
||||
content: ReactionSymbol,
|
||||
): ChatMessageReaction => {
|
||||
const fileContent = FileModel.createFileContent(v4(), "reaction");
|
||||
const reaction: ChatMessageReaction = {
|
||||
...fileContent,
|
||||
|
||||
messageId,
|
||||
sender,
|
||||
content,
|
||||
};
|
||||
return reaction;
|
||||
};
|
||||
}
|
||||
|
||||
// types
|
||||
export type ReactionSymbol = "👍" | "✅" | "❗️" | "‼️" | "❓";
|
||||
|
||||
export interface ChatInfo extends ValidObject {
|
||||
primaryChannel: string;
|
||||
secondaryChannels: string[];
|
||||
@@ -355,6 +452,13 @@ export interface ChatMessage extends ValidObject {
|
||||
stringifiedFile: string;
|
||||
}
|
||||
|
||||
export interface ChatMessageReaction
|
||||
extends ValidObject, FileContent<"reaction"> {
|
||||
messageId: string;
|
||||
sender: string;
|
||||
content: ReactionSymbol | string;
|
||||
}
|
||||
|
||||
// references
|
||||
export const ChatInfoReference: ChatInfo = {
|
||||
dataVersion: DATA_VERSION,
|
||||
@@ -380,3 +484,16 @@ export const ChatMessageReference: ChatMessage = {
|
||||
|
||||
stringifiedFile: "",
|
||||
};
|
||||
|
||||
export const ChatMessageReactionReference: ChatMessageReaction = {
|
||||
dataVersion: DATA_VERSION,
|
||||
|
||||
fileId: "",
|
||||
fileContentId: "",
|
||||
creationDate: "",
|
||||
type: "reaction",
|
||||
|
||||
messageId: "",
|
||||
sender: "",
|
||||
content: "",
|
||||
};
|
||||
|
||||
@@ -65,6 +65,7 @@ export default class FileModel {
|
||||
if (didStore == false) return;
|
||||
|
||||
this.boardsAndTasksModel.handleFileContent(fileContent);
|
||||
this.chatModel.handleReaction(fileContent);
|
||||
};
|
||||
|
||||
// methods
|
||||
|
||||
@@ -247,6 +247,10 @@ export const filePaths = {
|
||||
info: (id: string) => [...filePaths.chat.chatBase(id), "info"],
|
||||
color: (id: string) => [...filePaths.chat.chatBase(id), "color"],
|
||||
messages: (id: string) => [...filePaths.chat.chatBase(id), "messages"],
|
||||
reactions: (id: string) => [
|
||||
...filePaths.chat.chatBase(id),
|
||||
"reactions",
|
||||
],
|
||||
lastUsedPage: (id: string) => [
|
||||
...filePaths.chat.chatBase(id),
|
||||
"last-used-page",
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import { ChatMessage, ChatMessageStatus } from "../../Model/Chat/chatModel";
|
||||
import {
|
||||
ChatMessage,
|
||||
ChatMessageReaction,
|
||||
ChatMessageReactionReference,
|
||||
ChatMessageStatus,
|
||||
ReactionSymbol,
|
||||
} from "../../Model/Chat/chatModel";
|
||||
|
||||
import CoreViewModel from "../Global/coreViewModel";
|
||||
import MessagePageViewModel from "../Pages/messagePageViewModel";
|
||||
@@ -19,6 +25,12 @@ export default class ChatMessageViewModel {
|
||||
);
|
||||
sentByUser: boolean;
|
||||
|
||||
reactionsThumbsUp = new React.MapState<ChatMessageReaction>();
|
||||
reactionsCheck = new React.MapState<ChatMessageReaction>();
|
||||
reactionsAttention = new React.MapState<ChatMessageReaction>();
|
||||
reactionsDoubleAttention = new React.MapState<ChatMessageReaction>();
|
||||
reactionsQuestion = new React.MapState<ChatMessageReaction>();
|
||||
|
||||
// state
|
||||
isPresentingInfoModal: React.State<boolean> = new React.State(false);
|
||||
|
||||
@@ -42,6 +54,25 @@ export default class ChatMessageViewModel {
|
||||
this.isPresentingInfoModal.value = false;
|
||||
};
|
||||
|
||||
// reactions
|
||||
addReaction = (reaction: ChatMessageReaction): void => {
|
||||
switch (reaction.content) {
|
||||
case "👍":
|
||||
return this.reactionsThumbsUp.set(reaction.fileId, reaction);
|
||||
case "✅":
|
||||
return this.reactionsCheck.set(reaction.fileId, reaction);
|
||||
case "❗️":
|
||||
return this.reactionsAttention.set(reaction.fileId, reaction);
|
||||
case "‼️":
|
||||
return this.reactionsDoubleAttention.set(
|
||||
reaction.fileId,
|
||||
reaction,
|
||||
);
|
||||
case "❓":
|
||||
return this.reactionsQuestion.set(reaction.fileId, reaction);
|
||||
}
|
||||
};
|
||||
|
||||
// load
|
||||
loadData = (): void => {
|
||||
this.channel = this.chatMessage.channel;
|
||||
|
||||
@@ -3,7 +3,10 @@ import * as React from "bloatless-react";
|
||||
import CalendarPageViewModel, {
|
||||
CALENDAR_EVENT_BOARD_ID,
|
||||
} from "../Pages/calendarPageViewModel";
|
||||
import ChatModel, { ChatMessage } from "../../Model/Chat/chatModel";
|
||||
import ChatModel, {
|
||||
ChatMessage,
|
||||
ChatMessageReaction,
|
||||
} from "../../Model/Chat/chatModel";
|
||||
import StorageModel, {
|
||||
StorageModelSubPath,
|
||||
filePaths,
|
||||
@@ -176,6 +179,11 @@ export default class ChatViewModel {
|
||||
this.notificationViewModel.showNotification(chatMessage);
|
||||
},
|
||||
);
|
||||
chatModel.reactionHandlerManager.addHandler(
|
||||
(reaction: ChatMessageReaction) => {
|
||||
this.messagePageViewModel.showReaction(reaction);
|
||||
},
|
||||
);
|
||||
|
||||
// load
|
||||
this.loadPageSelection();
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import { ChatMessage } from "../../Model/Chat/chatModel";
|
||||
import {
|
||||
ChatMessage,
|
||||
ChatMessageReaction,
|
||||
ReactionSymbol,
|
||||
} from "../../Model/Chat/chatModel";
|
||||
import ChatMessageViewModel from "../Chat/chatMessageViewModel";
|
||||
import ChatViewModel from "../Chat/chatViewModel";
|
||||
import CoreViewModel from "../Global/coreViewModel";
|
||||
@@ -37,6 +41,10 @@ export default class MessagePageViewModel {
|
||||
messageViewModel.loadData();
|
||||
};
|
||||
|
||||
sendReaction = (messageId: string, content: ReactionSymbol): void => {
|
||||
this.chatViewModel.chatModel.sendReaction(messageId, content);
|
||||
};
|
||||
|
||||
// view
|
||||
showChatMessage = (chatMessage: ChatMessage): void => {
|
||||
const chatMessageViewModel = new ChatMessageViewModel(
|
||||
@@ -60,12 +68,22 @@ export default class MessagePageViewModel {
|
||||
}
|
||||
};
|
||||
|
||||
showReaction = (reaction: ChatMessageReaction): void => {
|
||||
const messageViewModel: ChatMessageViewModel | undefined =
|
||||
this.chatMessageViewModels.value.get(reaction.messageId);
|
||||
if (messageViewModel == undefined) return;
|
||||
messageViewModel.addReaction(reaction);
|
||||
};
|
||||
|
||||
// load
|
||||
loadData = (): void => {
|
||||
this.chatMessageViewModels.clear();
|
||||
for (const chatMessage of this.chatViewModel.chatModel.messages) {
|
||||
this.showChatMessage(chatMessage);
|
||||
}
|
||||
for (const reaction of this.chatViewModel.chatModel.reactions) {
|
||||
this.showReaction(reaction);
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
|
||||
Reference in New Issue
Block a user