cleanup, add handleStringifiedFile and addFile

This commit is contained in:
marlon-erler
2024-07-21 22:42:32 +02:00
parent da757d10d1
commit 5443d045db
4 changed files with 145 additions and 57 deletions
+68 -28
View File
@@ -276,6 +276,12 @@
return element; return element;
} }
// src/Model/Utility/typeSafety.ts
var DATA_VERSION = "v2";
function checkIsValidObject(object) {
return object.dataVersion == DATA_VERSION;
}
// src/Model/Utility/utility.ts // src/Model/Utility/utility.ts
function createTimestamp() { function createTimestamp() {
return (/* @__PURE__ */ new Date()).toISOString(); return (/* @__PURE__ */ new Date()).toISOString();
@@ -284,18 +290,21 @@
return JSON.stringify(data, null, 4); return JSON.stringify(data, null, 4);
} }
function parse(string) { function parse(string) {
return JSON.parse(string); try {
return JSON.parse(string);
} catch {
return {};
}
}
function parseValidObject(string) {
const parsed = parse(string);
if (checkIsValidObject(parsed) == false) return null;
return parsed;
} }
function localeCompare(a, b) { function localeCompare(a, b) {
return a.localeCompare(b); return a.localeCompare(b);
} }
// src/Model/Utility/typeSafety.ts
var DATA_VERSION = "v2";
function checkIsValidObject(object) {
return object.dataVersion == DATA_VERSION;
}
// src/Model/storageModel.ts // src/Model/storageModel.ts
var PATH_COMPONENT_SEPARATOR = "\\"; var PATH_COMPONENT_SEPARATOR = "\\";
var StorageModel = class _StorageModel { var StorageModel = class _StorageModel {
@@ -425,6 +434,24 @@
chatMessages: (id) => [DATA_VERSION, "chat", id, "messages"] chatMessages: (id) => [DATA_VERSION, "chat", id, "messages"]
}; };
// src/Model/fileModel.ts
var FileModel = class {
chatModel;
// handler
handleStringifiedFile = (stringifiedFile) => {
const file = parseValidObject(stringifiedFile);
if (file == null) return;
};
// methods
addFile = (file) => {
this.chatModel.sendMessage("", file);
};
// init
constructor(chatModel) {
this.chatModel = chatModel;
}
};
// src/Model/Utility/crypto.ts // src/Model/Utility/crypto.ts
var IV_SIZE = 12; var IV_SIZE = 12;
var ENCRYPTION_ALG = "AES-GCM"; var ENCRYPTION_ALG = "AES-GCM";
@@ -516,6 +543,7 @@
storageModel; storageModel;
settingsModel; settingsModel;
chatListModel; chatListModel;
fileModel;
// data // data
id; id;
info; info;
@@ -569,9 +597,12 @@
}; };
addMessage = async (chatMessage) => { addMessage = async (chatMessage) => {
await this.decryptMessage(chatMessage); await this.decryptMessage(chatMessage);
const messagePath = this.getMessagePath(chatMessage.id); if (chatMessage.body != "") {
this.storageModel.writeStringifiable(messagePath, chatMessage); const messagePath = this.getMessagePath(chatMessage.id);
this.chatMessageHandler(chatMessage); this.storageModel.writeStringifiable(messagePath, chatMessage);
this.chatMessageHandler(chatMessage);
}
this.fileModel.handleStringifiedFile(chatMessage.stringifiedFile);
}; };
// delete // delete
delete = () => { delete = () => {
@@ -613,7 +644,7 @@
return sorted; return sorted;
} }
// messaging // messaging
sendMessage = async (body) => { sendMessage = async (body, file) => {
const senderName = this.settingsModel.username; const senderName = this.settingsModel.username;
if (senderName == "") return false; if (senderName == "") return false;
const allChannels = [this.info.primaryChannel]; const allChannels = [this.info.primaryChannel];
@@ -621,20 +652,19 @@
allChannels.push(secondaryChannel); allChannels.push(secondaryChannel);
} }
const combinedChannel = allChannels.join("/"); const combinedChannel = allChannels.join("/");
if (this.info.encryptionKey != "") { const chatMessage = await _ChatModel.createChatMessage(
body = await encryptString(body, this.info.encryptionKey);
}
const chatMessage = _ChatModel.createChatMessage(
combinedChannel, combinedChannel,
senderName, senderName,
body this.info.encryptionKey,
body,
file
); );
this.addMessage(chatMessage); this.addMessage(chatMessage);
this.connectionModel.sendMessageOrStore(chatMessage); this.connectionModel.sendMessageOrStore(chatMessage);
return true; return true;
}; };
handleMessage = (body) => { handleMessage = (body) => {
const chatMessage = _ChatModel.parseMessage(body); const chatMessage = parseValidObject(body);
if (chatMessage == null) return; if (chatMessage == null) return;
chatMessage.status = "received" /* Received */; chatMessage.status = "received" /* Received */;
this.addMessage(chatMessage); this.addMessage(chatMessage);
@@ -648,7 +678,12 @@
chatMessage.body, chatMessage.body,
this.info.encryptionKey this.info.encryptionKey
); );
const decryptedFile = await decryptString(
chatMessage.stringifiedFile ?? "",
this.info.encryptionKey
);
chatMessage.body = decryptedBody; chatMessage.body = decryptedBody;
chatMessage.stringifiedFile = decryptedFile;
}; };
setMessageHandler = (handler) => { setMessageHandler = (handler) => {
this.chatMessageHandler = handler; this.chatMessageHandler = handler;
@@ -667,6 +702,7 @@
this.loadColor(); this.loadColor();
this.subscribe(); this.subscribe();
connectionModel2.setMessageSentHandler(this.handleMessageSent); connectionModel2.setMessageSentHandler(this.handleMessageSent);
this.fileModel = new FileModel(this);
} }
// utility // utility
static generateChatInfo = (primaryChannel) => { static generateChatInfo = (primaryChannel) => {
@@ -677,25 +713,29 @@
hasUnreadMessages: false hasUnreadMessages: false
}; };
}; };
static createChatMessage = (channel, sender, body) => { static createChatMessage = async (channel, sender, encryptionKey, body, file) => {
return { const chatMessage = {
dataVersion: "v2", dataVersion: "v2",
id: v4_default(), id: v4_default(),
channel, channel,
sender, sender,
body, body,
dateSent: createTimestamp(), dateSent: createTimestamp(),
status: "outbox" /* Outbox */ status: "outbox" /* Outbox */,
stringifiedFile: ""
}; };
}; if (file != void 0) {
static parseMessage = (string) => { const stringifiedFile = stringify(file);
try { chatMessage.stringifiedFile = stringifiedFile;
const parsed = parse(string);
if (checkIsValidObject(parsed) == false) return null;
return parsed;
} catch {
return null;
} }
if (encryptionKey != "") {
chatMessage.body = await encryptString(chatMessage.body, encryptionKey);
chatMessage.stringifiedFile = await encryptString(
chatMessage.stringifiedFile,
encryptionKey
);
}
return chatMessage;
}; };
}; };
+13 -1
View File
@@ -1,3 +1,5 @@
import { checkIsValidObject } from "./typeSafety";
// date // date
export function createTimestamp(): string { export function createTimestamp(): string {
return new Date().toISOString(); return new Date().toISOString();
@@ -9,7 +11,17 @@ export function stringify(data: any): string {
} }
export function parse(string: string): any { export function parse(string: string): any {
return JSON.parse(string); try {
return JSON.parse(string);
} catch {
return {};
}
}
export function parseValidObject<T>(string: string): T|null {
const parsed: any = parse(string);
if (checkIsValidObject(parsed) == false) return null;
return parsed;
} }
// sort // sort
+49 -26
View File
@@ -1,13 +1,18 @@
// this file is responsible for managing chats. // this file is responsible for managing chats.
import FileModel, { File } from "./fileModel";
import StorageModel, { storageKeys } from "./storageModel"; import StorageModel, { storageKeys } from "./storageModel";
import { createTimestamp, parse } from "./Utility/utility"; import {
createTimestamp,
parse,
parseValidObject,
stringify,
} from "./Utility/utility";
import { decryptString, encryptString } from "./Utility/crypto"; import { decryptString, encryptString } from "./Utility/crypto";
import ChatListModel from "./chatListModel"; import ChatListModel from "./chatListModel";
import { Color } from "../ViewModel/colors"; import { Color } from "../ViewModel/colors";
import ConnectionModel from "./connectionModel"; import ConnectionModel from "./connectionModel";
import FileModel from "./fileModel";
import SettingsModel from "./settingsModel"; import SettingsModel from "./settingsModel";
import { checkIsValidObject } from "./Utility/typeSafety"; import { checkIsValidObject } from "./Utility/typeSafety";
import { v4 } from "uuid"; import { v4 } from "uuid";
@@ -85,9 +90,16 @@ export default class ChatModel {
addMessage = async (chatMessage: ChatMessage): Promise<void> => { addMessage = async (chatMessage: ChatMessage): Promise<void> => {
await this.decryptMessage(chatMessage); await this.decryptMessage(chatMessage);
const messagePath: string[] = this.getMessagePath(chatMessage.id);
this.storageModel.writeStringifiable(messagePath, chatMessage); // message
this.chatMessageHandler(chatMessage); if (chatMessage.body != "") {
const messagePath: string[] = this.getMessagePath(chatMessage.id);
this.storageModel.writeStringifiable(messagePath, chatMessage);
this.chatMessageHandler(chatMessage);
}
// file
this.fileModel.handleStringifiedFile(chatMessage.stringifiedFile);
}; };
// delete // delete
@@ -140,7 +152,7 @@ export default class ChatModel {
} }
// messaging // messaging
sendMessage = async (body: string): Promise<boolean> => { sendMessage = async (body: string, file?: File): Promise<boolean> => {
const senderName = this.settingsModel.username; const senderName = this.settingsModel.username;
if (senderName == "") return false; if (senderName == "") return false;
@@ -150,14 +162,13 @@ export default class ChatModel {
} }
const combinedChannel: string = allChannels.join("/"); const combinedChannel: string = allChannels.join("/");
if (this.info.encryptionKey != "") {
body = await encryptString(body, this.info.encryptionKey);
}
const chatMessage: ChatMessage = ChatModel.createChatMessage( const chatMessage: ChatMessage = await ChatModel.createChatMessage(
combinedChannel, combinedChannel,
senderName, senderName,
body this.info.encryptionKey,
body,
file
); );
this.addMessage(chatMessage); this.addMessage(chatMessage);
@@ -166,7 +177,7 @@ export default class ChatModel {
}; };
handleMessage = (body: string): void => { handleMessage = (body: string): void => {
const chatMessage: ChatMessage | null = ChatModel.parseMessage(body); const chatMessage: ChatMessage | null = parseValidObject<ChatMessage>(body);
if (chatMessage == null) return; if (chatMessage == null) return;
chatMessage.status = ChatMessageStatus.Received; chatMessage.status = ChatMessageStatus.Received;
@@ -183,7 +194,12 @@ export default class ChatModel {
chatMessage.body, chatMessage.body,
this.info.encryptionKey this.info.encryptionKey
); );
const decryptedFile: string = await decryptString(
chatMessage.stringifiedFile ?? "",
this.info.encryptionKey
);
chatMessage.body = decryptedBody; chatMessage.body = decryptedBody;
chatMessage.stringifiedFile = decryptedFile;
}; };
setMessageHandler = (handler: (chatMessage: ChatMessage) => void): void => { setMessageHandler = (handler: (chatMessage: ChatMessage) => void): void => {
@@ -227,12 +243,14 @@ export default class ChatModel {
}; };
}; };
static createChatMessage = ( static createChatMessage = async (
channel: string, channel: string,
sender: string, sender: string,
body: string encryptionKey: string,
): ChatMessage => { body: string,
return { file?: File
): Promise<ChatMessage> => {
const chatMessage: ChatMessage = {
dataVersion: "v2", dataVersion: "v2",
id: v4(), id: v4(),
@@ -243,17 +261,22 @@ export default class ChatModel {
dateSent: createTimestamp(), dateSent: createTimestamp(),
status: ChatMessageStatus.Outbox, status: ChatMessageStatus.Outbox,
stringifiedFile: "",
}; };
}; if (file != undefined) {
const stringifiedFile = stringify(file);
static parseMessage = (string: string): ChatMessage | null => { chatMessage.stringifiedFile = stringifiedFile;
try {
const parsed: any = parse(string);
if (checkIsValidObject(parsed) == false) return null;
return parsed;
} catch {
return null;
} }
if (encryptionKey != "") {
chatMessage.body = await encryptString(chatMessage.body, encryptionKey);
chatMessage.stringifiedFile = await encryptString(
chatMessage.stringifiedFile,
encryptionKey
);
}
return chatMessage;
}; };
} }
@@ -284,5 +307,5 @@ export interface ChatMessage {
status?: ChatMessageStatus; status?: ChatMessageStatus;
stringifiedFile?: string; stringifiedFile: string;
} }
+14 -1
View File
@@ -1,10 +1,23 @@
// this file is responsible for managing files within chats. // this file is responsible for managing files within chats.
import ChatModel from "./chatModel"; import ChatModel, { ChatMessage } from "./chatModel";
import { parseValidObject } from "./Utility/utility";
export default class FileModel { export default class FileModel {
chatModel: ChatModel; chatModel: ChatModel;
// handler
handleStringifiedFile = (stringifiedFile: string): void => {
const file: File | null = parseValidObject<File>(stringifiedFile);
if (file == null) return;
};
// methods
addFile = (file: File): void => {
this.chatModel.sendMessage("", file);
};
// init // init
constructor(chatModel: ChatModel) { constructor(chatModel: ChatModel) {
this.chatModel = chatModel; this.chatModel = chatModel;