remodel storage location map

This commit is contained in:
marlon-erler
2024-07-22 03:01:04 +02:00
parent 839e6e6b2a
commit c21d665776
8 changed files with 452 additions and 272 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
import StorageModel, { storageKeys } from "../Global/storageModel";
import StorageModel, { filePaths } from "../Global/storageModel";
import ChatModel from "./chatModel";
import ConnectionModel from "../Global/connectionModel";
@@ -78,7 +78,7 @@ export default class ChatListModel {
// load
loadChats = (): void => {
const chatDir = storageKeys.chats;
const chatDir = StorageModel.getPath("chat", filePaths.chat.base);
const chatIds = this.storageModel.list(chatDir);
for (const chatId of chatIds) {
const chatModel = new ChatModel(
+74 -68
View File
@@ -2,7 +2,7 @@
import { DATA_VERSION, ValidObject } from "../Utility/typeSafety";
import FileModel, { File } from "../Files/fileModel";
import StorageModel, { storageKeys } from "../Global/storageModel";
import StorageModel, { filePaths } from "../Global/storageModel";
import {
createTimestamp,
parseValidObject,
@@ -32,20 +32,24 @@ export default class ChatModel {
chatMessageHandler: (chatMessage: ChatMessage) => void = () => {};
// paths
get infoPath(): string[] {
return storageKeys.chatInfo(this.id);
}
getBasePath = (): string[] => {
return StorageModel.getPath("chat", filePaths.chat.chatBase(this.id));
};
get colorPath(): string[] {
return storageKeys.chatColor(this.id);
}
getInfoPath = (): string[] => {
return StorageModel.getPath("chat", filePaths.chat.info(this.id));
};
get messageDirPath(): string[] {
return storageKeys.chatMessages(this.id);
}
getColorPath = (): string[] => {
return StorageModel.getPath("chat", filePaths.chat.color(this.id));
};
getMessageDirPath = (): string[] => {
return StorageModel.getPath("chat", filePaths.chat.messages(this.id));
};
getMessagePath = (id: string): string[] => {
return [...this.messageDirPath, id];
return [...this.getMessageDirPath(), id];
};
// sorting
@@ -78,75 +82,75 @@ export default class ChatModel {
this.storeColor();
};
// messaging
sendMessage = async (body: string, file?: File): Promise<boolean> => {
const senderName = this.settingsModel.username;
if (senderName == "") return false;
// messaging
sendMessage = async (body: string, file?: File): Promise<boolean> => {
const senderName = this.settingsModel.username;
if (senderName == "") return false;
const allChannels = [this.info.primaryChannel];
for (const secondaryChannel of this.info.secondaryChannels) {
allChannels.push(secondaryChannel);
}
const allChannels = [this.info.primaryChannel];
for (const secondaryChannel of this.info.secondaryChannels) {
allChannels.push(secondaryChannel);
}
const combinedChannel: string = allChannels.join("/");
const combinedChannel: string = allChannels.join("/");
const chatMessage: ChatMessage = await ChatModel.createChatMessage(
combinedChannel,
senderName,
this.info.encryptionKey,
body,
file
);
const chatMessage: ChatMessage = await ChatModel.createChatMessage(
combinedChannel,
senderName,
this.info.encryptionKey,
body,
file
);
this.addMessage(chatMessage);
this.connectionModel.sendMessageOrStore(chatMessage);
return true;
};
this.addMessage(chatMessage);
this.connectionModel.sendMessageOrStore(chatMessage);
return true;
};
handleMessage = (body: string): void => {
const chatMessage: ChatMessage | null = parseValidObject(
body,
ChatMessageReference
);
if (chatMessage == null) return;
handleMessage = (body: string): void => {
const chatMessage: ChatMessage | null = parseValidObject(
body,
ChatMessageReference
);
if (chatMessage == null) return;
chatMessage.status = ChatMessageStatus.Received;
this.addMessage(chatMessage);
};
chatMessage.status = ChatMessageStatus.Received;
this.addMessage(chatMessage);
};
handleMessageSent = (chatMessage: ChatMessage): void => {
chatMessage.status = ChatMessageStatus.Sent;
this.addMessage(chatMessage);
};
handleMessageSent = (chatMessage: ChatMessage): void => {
chatMessage.status = ChatMessageStatus.Sent;
this.addMessage(chatMessage);
};
decryptMessage = async (chatMessage: ChatMessage): Promise<void> => {
const decryptedBody: string = await decryptString(
chatMessage.body,
this.info.encryptionKey
);
const decryptedFile: string = await decryptString(
chatMessage.stringifiedFile ?? "",
this.info.encryptionKey
);
chatMessage.body = decryptedBody;
chatMessage.stringifiedFile = decryptedFile;
};
decryptMessage = async (chatMessage: ChatMessage): Promise<void> => {
const decryptedBody: string = await decryptString(
chatMessage.body,
this.info.encryptionKey
);
const decryptedFile: string = await decryptString(
chatMessage.stringifiedFile ?? "",
this.info.encryptionKey
);
chatMessage.body = decryptedBody;
chatMessage.stringifiedFile = decryptedFile;
};
setMessageHandler = (handler: (chatMessage: ChatMessage) => void): void => {
this.chatMessageHandler = handler;
};
setMessageHandler = (handler: (chatMessage: ChatMessage) => void): void => {
this.chatMessageHandler = handler;
};
subscribe = (): void => {
this.connectionModel.addChannel(this.info.primaryChannel);
};
subscribe = (): void => {
this.connectionModel.addChannel(this.info.primaryChannel);
};
// storage
storeInfo = (): void => {
this.storageModel.writeStringifiable(this.infoPath, this.info);
this.storageModel.writeStringifiable(this.getInfoPath(), this.info);
};
storeColor = (): void => {
this.storageModel.write(this.colorPath, this.color);
this.storageModel.write(this.getColorPath(), this.color);
};
addMessage = async (chatMessage: ChatMessage): Promise<void> => {
@@ -168,14 +172,14 @@ subscribe = (): void => {
this.chatListModel.untrackChat(this);
// delete
const dirPath: string[] = [...storageKeys.chats, this.id];
const dirPath: string[] = this.getBasePath();
this.storageModel.removeRecursively(dirPath);
};
// load
loadInfo = (): void => {
const info: ChatInfo | null = this.storageModel.readStringifiable(
this.infoPath,
this.getInfoPath(),
ChatInfoReference
);
if (info != null) {
@@ -186,7 +190,7 @@ subscribe = (): void => {
};
loadColor = (): void => {
const path: string[] = this.colorPath;
const path: string[] = this.getColorPath();
const color: string | null = this.storageModel.read(path);
if (!color) {
this.color = Color.Standard;
@@ -196,7 +200,9 @@ subscribe = (): void => {
};
get messages(): ChatMessage[] {
const messageIds: string[] = this.storageModel.list(this.messageDirPath);
const messageIds: string[] = this.storageModel.list(
this.getMessageDirPath()
);
if (!Array.isArray(messageIds)) return [];
const chatMessages: ChatMessage[] = [];
+23 -18
View File
@@ -1,7 +1,7 @@
// this file is responsible for managing files within chats.
import { DATA_VERSION, ValidObject } from "../Utility/typeSafety";
import StorageModel, { storageKeys } from "../Global/storageModel";
import StorageModel, { filePaths } from "../Global/storageModel";
import { parseValidObject, stringify } from "../Utility/utility";
import ChatModel from "../Chat/chatModel";
@@ -14,6 +14,23 @@ export default class FileModel {
taskModel: TaskModel;
// paths
getBasePath = (): string[] => {
return StorageModel.getPath(
"chat",
filePaths.chat.files(this.chatModel.id)
);
};
getFilePath = (fileId: string): string[] => {
return [...this.getBasePath(), fileId];
};
getFileContentPath = (file: File, fileContentName: string): string[] => {
const filePath: string[] = this.getFilePath(file.id);
return [...filePath, fileContentName];
};
// handler
handleStringifiedFile = (stringifiedFile: string): void => {
const file: File | null = parseValidObject(stringifiedFile, FileReference);
@@ -36,7 +53,7 @@ export default class FileModel {
storeFileContent = (file: File, fileContent: FileContent): void => {
const fileContentName: string = FileModel.getFileContentName(fileContent);
const fileContentPath: string[] = FileModel.getFileContentPath(
const fileContentPath: string[] = this.getFileContentPath(
file,
fileContentName
);
@@ -51,16 +68,16 @@ export default class FileModel {
};
listFileIds = (): string[] => {
return this.storageModel.list(storageKeys.chatFiles);
return this.storageModel.list(this.getBasePath());
};
listFileContents = (file: File): string[] => {
const filePath: string[] = FileModel.getFilePath(file.id);
const filePath: string[] = this.getFilePath(file.id);
return this.storageModel.list(filePath);
};
getFile = (fileId: string): File | null => {
const filePath = FileModel.getFilePath(fileId);
const filePath = this.getFilePath(fileId);
const fileOrNull: File | null = this.storageModel.readStringifiable(
filePath,
FileReference
@@ -76,7 +93,7 @@ export default class FileModel {
file: File,
fileContentName: string
): FileContent | null => {
const filePath = FileModel.getFileContentPath(file, fileContentName);
const filePath = this.getFileContentPath(file, fileContentName);
const fileContentOrNull: FileContent | null =
this.storageModel.readStringifiable(filePath, FileContentReference);
return fileContentOrNull;
@@ -91,22 +108,10 @@ export default class FileModel {
}
// utility
static getFilePath = (fileId: string): string[] => {
return [...storageKeys.chatFiles, fileId];
};
static getFileContentName = (fileContent: FileContent): string => {
return fileContent.creationDate + fileContent.id;
};
static getFileContentPath = (
file: File,
fileContentName: string
): string[] => {
const filePath: string[] = FileModel.getFilePath(file.id);
return [...filePath, fileContentName];
};
static createFile = (): File => {
return {
dataVersion: DATA_VERSION,
+52 -14
View File
@@ -1,7 +1,7 @@
// this file is responsible for managing UDN connections.
import { ChatMessage, ChatMessageReference } from "../Chat/chatModel";
import StorageModel, { storageKeys } from "./storageModel";
import StorageModel, { filePaths } from "./storageModel";
import UDNFrontend, { Message } from "udn-frontend";
import { stringify } from "../Utility/utility";
@@ -52,11 +52,23 @@ export default class ConnectionModel {
this.udn.disconnect();
// do not reconnect
const reconnectAddressPath: string[] = storageKeys.reconnectAddress;
const reconnectAddressPath: string[] = StorageModel.getPath(
"connectionModel",
filePaths.connectionModel.reconnectAddress
);
this.storageModel.remove(reconnectAddressPath);
};
// mailbox
getMailboxPath = (address: string): string[] => {
const mailboxDirPath = StorageModel.getPath(
"connectionModel",
filePaths.connectionModel.mailboxes
);
const mailboxFilePath = [...mailboxDirPath, address];
return mailboxFilePath;
};
requestNewMailbox = (): void => {
console.trace("requesting mailbox");
this.udn.requestMailbox();
@@ -64,8 +76,8 @@ export default class ConnectionModel {
connectMailbox = (): void => {
if (this.address == undefined) return;
const path = [...storageKeys.mailboxes, this.address];
const mailboxId = this.storageModel.read(path);
const mailboxId = this.storageModel.read(this.getMailboxPath(this.address));
console.log("connecting mailbox", mailboxId);
if (mailboxId == null) return this.requestNewMailbox();
@@ -74,8 +86,7 @@ export default class ConnectionModel {
storeMailbox = (mailboxId: string): void => {
if (this.address == undefined) return;
const path = [...storageKeys.mailboxes, this.address];
this.storageModel.write(path, mailboxId);
this.storageModel.write(this.getMailboxPath(this.address), mailboxId);
};
// subscription
@@ -95,8 +106,15 @@ export default class ConnectionModel {
};
// outbox
getOutboxPath = (): string[] => {
return StorageModel.getPath(
"connectionModel",
filePaths.connectionModel.outbox
);
};
getOutboxMessags = (): ChatMessage[] => {
const outboxPath: string[] = storageKeys.outbox;
const outboxPath: string[] = this.getOutboxPath();
const messageIds: string[] = this.storageModel.list(outboxPath);
let chatMessages: ChatMessage[] = [];
@@ -115,12 +133,12 @@ export default class ConnectionModel {
};
addToOutbox = (chatMessage: ChatMessage): void => {
const messagePath: string[] = [...storageKeys.outbox, chatMessage.id];
const messagePath: string[] = [...this.getOutboxPath(), chatMessage.id];
this.storageModel.writeStringifiable(messagePath, chatMessage);
};
removeFromOutbox = (chatMessage: ChatMessage): void => {
const messagePath: string[] = [...storageKeys.outbox, chatMessage.id];
const messagePath: string[] = [...this.getOutboxPath(), chatMessage.id];
this.storageModel.remove(messagePath);
};
@@ -154,18 +172,32 @@ export default class ConnectionModel {
};
// storage
private getAddressPath = (address: string): string[] => {
const dirPath = storageKeys.previousAddresses;
getPreviousAddressPath = (): string[] => {
return StorageModel.getPath(
"connectionModel",
filePaths.connectionModel.previousAddresses
);
};
getAddressPath = (address: string): string[] => {
const dirPath = this.getPreviousAddressPath();
return [...dirPath, address];
};
getReconnectAddressPath = (): string[] => {
return StorageModel.getPath(
"connectionModel",
filePaths.connectionModel.reconnectAddress
);
};
storeAddress = (address: string): void => {
// history
const addressPath = this.getAddressPath(address);
this.storageModel.write(addressPath, "");
// reconnect
const reconnectAddressPath: string[] = storageKeys.reconnectAddress;
const reconnectAddressPath: string[] = this.getReconnectAddressPath();
this.storageModel.write(reconnectAddressPath, address);
};
@@ -175,7 +207,7 @@ export default class ConnectionModel {
};
get addresses(): string[] {
const dirPath = storageKeys.previousAddresses;
const dirPath = this.getPreviousAddressPath();
return this.storageModel.list(dirPath);
}
@@ -225,7 +257,7 @@ export default class ConnectionModel {
};
// reconnect
const reconnectAddressPath: string[] = storageKeys.reconnectAddress;
const reconnectAddressPath: string[] = this.getPreviousAddressPath();
const reconnectAddress: string | null =
storageModel.read(reconnectAddressPath);
if (reconnectAddress != null) {
@@ -233,3 +265,9 @@ export default class ConnectionModel {
}
}
}
// paths
export enum settingsModelStorageFiles {
username = "user-name",
firstDayOfWeek = "first-day-of-week",
}
+18 -6
View File
@@ -1,6 +1,6 @@
// this file is responsible for all settings.
import StorageModel, { storageKeys } from "./storageModel";
import StorageModel, { filePaths } from "./storageModel";
export default class SettingsModel {
storageModel: StorageModel;
@@ -9,28 +9,40 @@ export default class SettingsModel {
username: string;
firstDayOfWeek: string;
// set
// storage
setName(newValue: string): void {
this.username = newValue;
const path = storageKeys.username;
const path = StorageModel.getPath(
"settingsModel",
filePaths.settingsModel.username
);
this.storageModel.write(path, newValue);
}
setFirstDayOfWeek(newValue: string): void {
this.firstDayOfWeek = newValue;
const path = storageKeys.firstDayOfWeek;
const path = StorageModel.getPath(
"settingsModel",
filePaths.settingsModel.firstDayOfWeek
);
this.storageModel.write(path, newValue);
}
// load
loadUsernam(): void {
const path = storageKeys.username;
const path = StorageModel.getPath(
"settingsModel",
filePaths.settingsModel.username
);
const content = this.storageModel.read(path);
this.username = content ?? "";
}
loadFirstDayofWeek(): void {
const path = storageKeys.firstDayOfWeek;
const path = StorageModel.getPath(
"settingsModel",
filePaths.settingsModel.firstDayOfWeek
);
const content = this.storageModel.read(path);
this.firstDayOfWeek = content ?? "0";
}
+48 -31
View File
@@ -90,12 +90,7 @@ export default class StorageModel {
return object;
};
// init
constructor() {
this.initializeTree();
}
// utility
// tree
initializeTree = (): void => {
console.log("initializing tree");
@@ -121,6 +116,12 @@ export default class StorageModel {
return stringify(this.storageEntryTree);
};
// init
constructor() {
this.initializeTree();
}
// utility
static getFileName = (pathComponents: string[]): string => {
return pathComponents[pathComponents.length - 1] || "\\";
};
@@ -146,36 +147,52 @@ export default class StorageModel {
}
return StorageModel.pathComponentsToString(...allComponents);
};
static getPath(
locationName: keyof typeof storageLocations,
filePath: string[]
): string[] {
return [DATA_VERSION, storageLocations[locationName], ...filePath];
}
}
// types
export type StorageEntry = { [key: string]: StorageEntry };
// keys
export const storageKeys = {
// connection
socketAddress: [DATA_VERSION, "connection", "socket-address"],
reconnectAddress: [DATA_VERSION, "connection", "reconnect-address"],
outbox: [DATA_VERSION, "connection", "outbox"],
mailboxes: [DATA_VERSION, "connection", "mailboxes"],
// locations
const storageLocations = {
connectionModel: "connection",
// settings
username: [DATA_VERSION, "settings", "user-name"],
firstDayOfWeek: [DATA_VERSION, "settings", "first-day-of-week"],
chat: "chat",
// history
previousAddresses: [DATA_VERSION, "history", "previous-addresses"],
// chat
chats: [DATA_VERSION, "chat"],
chatInfo: (id: string) => [DATA_VERSION, "chat", id, "info"],
chatLastUsedPage: (id: string) => [
DATA_VERSION,
"chat",
id,
"last-used-page",
],
chatColor: (id: string) => [DATA_VERSION, "chat", id, "color"],
chatMessages: (id: string) => [DATA_VERSION, "chat", id, "messages"],
chatFiles: [DATA_VERSION, "chat", "files"],
settingsModel: "settings",
};
export const filePaths = {
connectionModel: {
socketAddress: ["socket-address"],
reconnectAddress: ["reconnect-address"],
outbox: ["outbox"],
mailboxes: ["mailboxes"],
previousAddresses: ["previous-addresses"],
},
chat: {
base: [],
chatBase: (id: string) => [id],
info: (id: string) => [...filePaths.chat.chatBase(id), "info"],
color: (id: string) => [...filePaths.chat.chatBase(id), "color"],
messages: (id: string) => [...filePaths.chat.chatBase(id), "messages"],
files: (id: string) => [...filePaths.chat.chatBase(id), "files"],
lastUsedPage: (id: string) => [
...filePaths.chat.chatBase(id),
"last-used-page",
],
},
settingsModel: {
username: ["user-name"],
firstDayOfWeek: ["first-day-of-week"],
},
};
+7 -4
View File
@@ -1,7 +1,7 @@
import * as React from "bloatless-react";
import ChatModel, { ChatMessage } from "../Model/Chat/chatModel";
import StorageModel, { storageKeys } from "../Model/Global/storageModel";
import StorageModel, { filePaths } from "../Model/Global/storageModel";
import ChatListViewModel from "./chatListViewModel";
import ChatMessageViewModel from "./chatMessageViewModel";
@@ -134,7 +134,7 @@ export default class ChatViewModel {
// messaging
sendMessage = (): void => {
if (this.cannotSendMessage.value == true) return;
this.sendMessageFromBody(this.composingMessage.value);
this.composingMessage.value = "";
};
@@ -154,7 +154,10 @@ export default class ChatViewModel {
// load
loadPageSelection = (): void => {
const path: string[] = storageKeys.chatLastUsedPage(this.chatModel.id);
const path: string[] = StorageModel.getPath(
"chat",
filePaths.chat.lastUsedPage(this.chatModel.id)
);
const lastUsedPage: string | null = this.storageModel.read(path);
if (lastUsedPage != null) {
this.selectedPage.value = lastUsedPage as any;
@@ -178,7 +181,7 @@ export default class ChatViewModel {
for (const chatMessage of this.chatModel.messages) {
this.addChatMessage(chatMessage);
}
}
};
// init
constructor(