add basic thread view

This commit is contained in:
marlon-erler
2024-07-21 01:12:35 +02:00
parent 611b876509
commit c97b38dcd6
13 changed files with 359 additions and 87 deletions
+26 -2
View File
@@ -2,6 +2,7 @@ import StorageModel, { storageKeys } from "./storageModel";
import { ChatModel } from "./chatModel";
import ConnectionModel from "./connectionModel";
import { Message } from "udn-frontend";
import SettingsModel from "./settingsModel";
import { localeCompare } from "./Utility/utility";
import { v4 } from "uuid";
@@ -15,6 +16,23 @@ export default class ChatListModel {
chatModels = new Set<ChatModel>();
sortedPrimaryChannels: string[] = [];
// handlers
messageHandler = (data: Message): void => {
for (const chatModel of this.chatModels) {
const channel: string | undefined = data.messageChannel;
const body: string | undefined = data.messageBody;
if (channel == undefined) return;
if (body == undefined) return;
const allChannels = channel.split("/");
for (const channel of allChannels) {
if (channel != chatModel.info.primaryChannel) continue;
chatModel.handleMessage(channel, body);
break;
}
}
};
// store & add
addChatModel = (chatModel: ChatModel) => {
this.chatModels.add(chatModel);
@@ -57,7 +75,7 @@ export default class ChatListModel {
getIndexOfPrimaryChannel(primaryChannel: string): number {
return this.sortedPrimaryChannels.indexOf(primaryChannel);
}
// restore
loadChats = (): void => {
const chatDir = storageKeys.chats;
@@ -75,10 +93,16 @@ export default class ChatListModel {
};
// init
constructor(storageModel: StorageModel, settingsModel: SettingsModel, connectionModel: ConnectionModel) {
constructor(
storageModel: StorageModel,
settingsModel: SettingsModel,
connectionModel: ConnectionModel
) {
this.storageModel = storageModel;
this.settingsModel = settingsModel;
this.connectionModel = connectionModel;
this.loadChats();
connectionModel.setMessageHandler(this.messageHandler);
}
}
+24
View File
@@ -0,0 +1,24 @@
// this file is responsible for managing individual chat messages.
import * as React from "bloatless-react";
import { ChatMessage, ChatModel } from "./chatModel";
export default class ChatMessageViewModel {
chatModel: ChatModel;
// data
channel: string;
sender: string;
dateSent: string;
body: React.State<string> = new React.State("");
constructor(chatModel: ChatModel, chatMessage: ChatMessage) {
this.chatModel = chatModel;
this.channel = chatMessage.channel;
this.sender = chatMessage.sender;
this.dateSent = new Date(chatMessage.dateSent).toLocaleString();
this.body.value = chatMessage.body;
}
}
+38 -8
View File
@@ -1,6 +1,7 @@
// this file is responsible for managing chats and chat messages. objects are delegated to objectModel.ts.
// this file is responsible for managing chats. objects are delegated to objectModel.ts.
import StorageModel, { storageKeys } from "./storageModel";
import { createTimestamp, parse } from "./Utility/utility";
import ChatListModel from "./chatListModel";
import { Color } from "../ViewModel/colors";
@@ -8,7 +9,6 @@ import ConnectionModel from "./connectionModel";
import { Message } from "udn-frontend";
import SettingsModel from "./settingsModel";
import { checkIsValidObject } from "./Utility/typeSafety";
import { createTimestamp } from "./Utility/utility";
import { v4 } from "uuid";
export class ChatModel {
@@ -22,6 +22,8 @@ export class ChatModel {
info: ChatInfo;
color: Color;
chatMessageHandler: (chatMessage: ChatMessage) => void = () => {};
// sorting
get index(): number {
return this.chatListModel.getIndexOfPrimaryChannel(
@@ -59,6 +61,7 @@ export class ChatModel {
this.info.primaryChannel = primaryChannel;
this.storeInfo();
this.chatListModel.updateIndices();
this.subscribe();
};
setSecondaryChannels = (secondaryChannels: string[]): void => {
@@ -85,14 +88,15 @@ export class ChatModel {
this.storageModel.store(this.colorPath, this.color);
};
addMessage = (message: ChatMessage): void => {
const messagePath: string[] = this.getMessagePath(message.id);
this.storageModel.storeStringifiable(messagePath, message);
addMessage = (chatMessage: ChatMessage): void => {
const messagePath: string[] = this.getMessagePath(chatMessage.id);
this.storageModel.storeStringifiable(messagePath, chatMessage);
this.chatMessageHandler(chatMessage);
};
addObject = (object: ChatObject): void => {
const objectPath: string[] = this.getObjectPath(object.id);
this.storageModel.storeStringifiable(objectPath, object);
addObject = (chatObject: ChatObject): void => {
const objectPath: string[] = this.getObjectPath(chatObject.id);
this.storageModel.storeStringifiable(objectPath, chatObject);
};
// delete
@@ -179,6 +183,21 @@ export class ChatModel {
return true;
};
handleMessage = (channel: string, body: string): void => {
const chatMessage: ChatMessage | null = ChatModel.parseMessage(body);
if (chatMessage == null) return;
this.addMessage(chatMessage);
};
setMessageHandler = (handler: (chatMessage: ChatMessage) => void): void => {
this.chatMessageHandler = handler;
};
subscribe = (): void => {
this.connectionModel.addChannel(this.info.primaryChannel);
};
// init
constructor(
storageModel: StorageModel,
@@ -195,6 +214,7 @@ export class ChatModel {
this.restoreInfo();
this.restoreColor();
this.subscribe();
}
// utility
@@ -223,6 +243,16 @@ export class ChatModel {
dateSent: createTimestamp(),
};
};
static parseMessage = (string: string): ChatMessage | null => {
try {
const parsed: any = parse(string);
if (checkIsValidObject(parsed) == false) return null;
return parsed;
} catch {
return null;
}
};
}
// types
+17 -5
View File
@@ -23,6 +23,8 @@ export default class ConnectionModel {
connectionChangeHandler: () => void = () => {};
messageHandler: (data: Message) => void = () => {};
channelsToSubscribe: Set<string> = new Set();
// connection
connect = (address: string): void => {
this.udn.connect(address);
@@ -39,16 +41,26 @@ export default class ConnectionModel {
handleConnectionChange = (): void => {
console.log("connection status:", this.isConnected, this.address);
this.connectionChangeHandler();
if (this.isConnected == false) return;
if (!this.address) return;
if (this.address) {
this.storeAddress(this.address);
}
this.storeAddress(this.address);
this.sendSubscriptionRequest();
this.sendMessagesInOutbox();
};
// subscription
addChannel = (channel: string): void => {
this.channelsToSubscribe.add(channel);
this.sendSubscriptionRequest();
};
sendSubscriptionRequest = (): void => {
for (const channel of this.channelsToSubscribe) {
this.udn.subscribe(channel);
}
};
// outbox
getOutboxMessags = (): ChatMessage[] => {
const outboxPath: string[] = storageKeys.outbox;
+1 -1
View File
@@ -1 +1 @@
// this file is responsible for managing message objects.
// this file is responsible for managing message objects.c