Files
CT/src/Model/Global/connectionModel.ts
T

261 lines
7.3 KiB
TypeScript
Raw Normal View History

2024-07-19 17:56:25 +02:00
// this file is responsible for managing UDN connections.
2024-07-22 02:05:27 +02:00
import { ChatMessage, ChatMessageReference } from "../Chat/chatModel";
import { HandlerManager, stringify } from "../Utility/utility";
2024-07-25 16:44:08 +02:00
import StorageModel, { StorageModelSubPath, filePaths } from "./storageModel";
2024-07-19 17:56:25 +02:00
import UDNFrontend, { Message } from "udn-frontend";
export default class ConnectionModel {
udn: UDNFrontend;
storageModel: StorageModel;
2024-07-19 17:56:25 +02:00
// data
get isConnected(): boolean {
return this.udn.ws != undefined && this.udn.ws.readyState == 1;
}
get address(): string | undefined {
2024-07-19 17:56:25 +02:00
return this.udn.ws?.url;
}
connectionChangeHandlerManager: HandlerManager<void> = new HandlerManager();
messageHandlerManager: HandlerManager<Message> = new HandlerManager();
messageSentHandlerManager: HandlerManager<ChatMessage> = new HandlerManager();
2024-07-20 22:44:23 +02:00
2024-07-21 01:12:35 +02:00
channelsToSubscribe: Set<string> = new Set();
2024-07-22 02:23:21 +02:00
// handlers
2024-07-20 22:44:23 +02:00
handleMessage = (data: Message): void => {
this.messageHandlerManager.trigger(data);
2024-07-20 22:44:23 +02:00
};
2024-07-20 20:42:43 +02:00
2024-07-20 02:18:15 +02:00
handleConnectionChange = (): void => {
console.log("connection status:", this.isConnected, this.address);
this.connectionChangeHandlerManager.trigger();
2024-07-21 03:41:10 +02:00
if (this.isConnected == false) return;
2024-07-25 16:44:08 +02:00
if (this.address == undefined) return;
2024-07-21 01:12:35 +02:00
this.storeAddress(this.address);
this.sendSubscriptionRequest();
2024-07-20 22:44:23 +02:00
this.sendMessagesInOutbox();
};
2024-07-19 17:56:25 +02:00
2024-07-22 02:23:21 +02:00
// connection
connect = (address: string): void => {
this.udn.connect(address);
};
disconnect = (): void => {
this.udn.disconnect();
// do not reconnect
2024-07-22 03:01:04 +02:00
const reconnectAddressPath: string[] = StorageModel.getPath(
2024-07-25 16:44:08 +02:00
StorageModelSubPath.ConnectionModel,
2024-07-22 03:01:04 +02:00
filePaths.connectionModel.reconnectAddress
);
2024-07-22 02:23:21 +02:00
this.storageModel.remove(reconnectAddressPath);
};
2024-07-21 15:15:24 +02:00
// mailbox
2024-07-22 03:01:04 +02:00
getMailboxPath = (address: string): string[] => {
const mailboxDirPath = StorageModel.getPath(
2024-07-25 16:44:08 +02:00
StorageModelSubPath.ConnectionModel,
2024-07-22 03:01:04 +02:00
filePaths.connectionModel.mailboxes
);
const mailboxFilePath = [...mailboxDirPath, address];
return mailboxFilePath;
};
2024-07-21 15:15:24 +02:00
requestNewMailbox = (): void => {
2024-07-25 16:44:08 +02:00
console.log("requesting new mailbox");
2024-07-21 15:15:24 +02:00
this.udn.requestMailbox();
};
connectMailbox = (): void => {
if (this.address == undefined) return;
2024-07-22 03:01:04 +02:00
const mailboxId = this.storageModel.read(this.getMailboxPath(this.address));
2024-07-22 01:38:08 +02:00
console.log("connecting mailbox", mailboxId);
2024-07-21 15:15:24 +02:00
if (mailboxId == null) return this.requestNewMailbox();
this.udn.connectMailbox(mailboxId);
};
storeMailbox = (mailboxId: string): void => {
if (this.address == undefined) return;
2024-07-22 03:01:04 +02:00
this.storageModel.write(this.getMailboxPath(this.address), mailboxId);
2024-07-21 15:15:24 +02:00
};
2024-07-21 01:12:35 +02:00
// subscription
addChannel = (channel: string): void => {
this.channelsToSubscribe.add(channel);
this.sendSubscriptionRequest();
};
sendSubscriptionRequest = (): void => {
2024-07-21 03:41:10 +02:00
if (this.isConnected == false) return;
2024-07-21 01:12:35 +02:00
for (const channel of this.channelsToSubscribe) {
this.udn.subscribe(channel);
}
2024-07-21 15:15:24 +02:00
// update mailbox
this.connectMailbox();
2024-07-21 01:12:35 +02:00
};
2024-07-20 20:03:46 +02:00
// outbox
2024-07-22 03:01:04 +02:00
getOutboxPath = (): string[] => {
return StorageModel.getPath(
2024-07-25 16:44:08 +02:00
StorageModelSubPath.ConnectionModel,
2024-07-22 03:01:04 +02:00
filePaths.connectionModel.outbox
);
};
2024-07-20 20:03:46 +02:00
getOutboxMessags = (): ChatMessage[] => {
2024-07-22 03:01:04 +02:00
const outboxPath: string[] = this.getOutboxPath();
2024-07-20 20:03:46 +02:00
const messageIds: string[] = this.storageModel.list(outboxPath);
2024-07-22 01:38:08 +02:00
let chatMessages: ChatMessage[] = [];
2024-07-20 20:03:46 +02:00
for (const messageId of messageIds) {
2024-07-22 01:38:08 +02:00
const chatMessage: ChatMessage | null =
this.storageModel.readStringifiable(
[...outboxPath, messageId],
ChatMessageReference
);
if (chatMessage == null) continue;
chatMessages.push(chatMessage);
2024-07-20 20:03:46 +02:00
}
2024-07-22 01:38:08 +02:00
return chatMessages;
2024-07-20 20:03:46 +02:00
};
addToOutbox = (chatMessage: ChatMessage): void => {
2024-07-22 03:01:04 +02:00
const messagePath: string[] = [...this.getOutboxPath(), chatMessage.id];
2024-07-21 21:41:19 +02:00
this.storageModel.writeStringifiable(messagePath, chatMessage);
2024-07-20 20:03:46 +02:00
};
removeFromOutbox = (chatMessage: ChatMessage): void => {
2024-07-22 03:01:04 +02:00
const messagePath: string[] = [...this.getOutboxPath(), chatMessage.id];
2024-07-20 20:03:46 +02:00
this.storageModel.remove(messagePath);
};
sendMessagesInOutbox = (): void => {
const messages: ChatMessage[] = this.getOutboxMessags();
for (const message of messages) {
const isSent: boolean = this.tryToSendMessage(message);
2024-07-20 20:03:46 +02:00
if (isSent == false) return;
this.removeFromOutbox(message);
}
};
2024-07-19 17:56:25 +02:00
// messaging
2024-07-20 20:03:46 +02:00
sendMessageOrStore = (chatMessage: ChatMessage): void => {
const isSent = this.tryToSendMessage(chatMessage);
if (isSent == true) return;
this.addToOutbox(chatMessage);
};
tryToSendMessage = (chatMessage: ChatMessage): boolean => {
2024-07-19 20:50:42 +02:00
const stringifiedBody: string = stringify(chatMessage);
2024-07-27 18:03:12 +02:00
const isSent: boolean = this.sendPlainMessage(
chatMessage.channel,
stringifiedBody
);
if (isSent) this.messageSentHandlerManager.trigger(chatMessage);
return isSent;
};
2024-07-19 17:56:25 +02:00
2024-07-27 18:03:12 +02:00
sendPlainMessage = (channel: string, body: string): boolean => {
return this.udn.sendMessage(channel, body);
};
// storage
2024-07-22 03:01:04 +02:00
getPreviousAddressPath = (): string[] => {
return StorageModel.getPath(
2024-07-25 16:44:08 +02:00
StorageModelSubPath.ConnectionModel,
2024-07-22 03:01:04 +02:00
filePaths.connectionModel.previousAddresses
);
};
getAddressPath = (address: string): string[] => {
const dirPath = this.getPreviousAddressPath();
return [...dirPath, address];
};
2024-07-22 03:01:04 +02:00
getReconnectAddressPath = (): string[] => {
return StorageModel.getPath(
2024-07-25 16:44:08 +02:00
StorageModelSubPath.ConnectionModel,
2024-07-22 03:01:04 +02:00
filePaths.connectionModel.reconnectAddress
);
};
storeAddress = (address: string): void => {
2024-07-21 03:41:10 +02:00
// history
const addressPath = this.getAddressPath(address);
2024-07-21 21:41:19 +02:00
this.storageModel.write(addressPath, "");
2024-07-21 03:41:10 +02:00
// reconnect
2024-07-22 03:01:04 +02:00
const reconnectAddressPath: string[] = this.getReconnectAddressPath();
2024-07-21 21:41:19 +02:00
this.storageModel.write(reconnectAddressPath, address);
};
removeAddress = (address: string): void => {
const addressPath = this.getAddressPath(address);
this.storageModel.remove(addressPath);
};
2024-07-20 02:59:40 +02:00
get addresses(): string[] {
2024-07-22 03:01:04 +02:00
const dirPath = this.getPreviousAddressPath();
return this.storageModel.list(dirPath);
2024-07-20 20:03:46 +02:00
}
2024-07-25 16:44:08 +02:00
2024-07-22 02:23:21 +02:00
// init
2024-07-20 20:42:43 +02:00
constructor(storageModel: StorageModel) {
2024-07-19 18:17:00 +02:00
// create frontend
2024-07-19 17:56:25 +02:00
this.udn = new UDNFrontend();
2024-07-20 20:42:43 +02:00
this.storageModel = storageModel;
2024-07-19 18:17:00 +02:00
// setup handlers
this.udn.onmessage = (data: Message) => {
2024-07-20 20:42:43 +02:00
this.handleMessage(data);
2024-07-19 18:17:00 +02:00
};
this.udn.onconnect = () => {
this.handleConnectionChange();
2024-07-19 18:17:00 +02:00
};
this.udn.ondisconnect = () => {
this.handleConnectionChange();
2024-07-19 18:17:00 +02:00
};
2024-07-21 03:41:10 +02:00
2024-07-21 15:15:24 +02:00
this.udn.onmailboxcreate = (mailboxId: string) => {
console.log("created mailbox", mailboxId);
this.storeMailbox(mailboxId);
this.connectMailbox();
};
this.udn.onmailboxdelete = (mailboxId: string) => {
console.log(`mailbox ${mailboxId} deleted`);
this.requestNewMailbox();
};
this.udn.onmailboxconnect = (mailboxId: string) => {
console.log(`using mailbox ${mailboxId}`);
};
2024-07-21 03:41:10 +02:00
// reconnect
2024-07-22 03:02:33 +02:00
const reconnectAddressPath: string[] = this.getReconnectAddressPath();
2024-07-21 03:41:10 +02:00
const reconnectAddress: string | null =
2024-07-21 21:41:19 +02:00
storageModel.read(reconnectAddressPath);
2024-07-21 03:41:10 +02:00
if (reconnectAddress != null) {
this.connect(reconnectAddress);
}
2024-07-19 17:56:25 +02:00
}
2024-07-20 22:44:23 +02:00
}
2024-07-22 03:01:04 +02:00
// paths
export enum settingsModelStorageFiles {
username = "user-name",
firstDayOfWeek = "first-day-of-week",
}