diff --git a/dist/index.js b/dist/index.js index d2a019dd..6a1960f1 100644 --- a/dist/index.js +++ b/dist/index.js @@ -514,7 +514,7 @@ } }; - // src/ViewModel/colors.ts + // src/colors.ts var Color = /* @__PURE__ */ ((Color2) => { Color2["Standard"] = "standard"; Color2["Coral"] = "coral"; @@ -897,6 +897,9 @@ color; chatMessageHandler = () => { }; + get secondaryChannels() { + return this.info.secondaryChannels.sort(localeCompare); + } // paths getBasePath = () => { return StorageModel.getPath("chat", filePaths.chat.chatBase(this.id)); @@ -1195,9 +1198,9 @@ } }; - // src/ViewModel/chatMessageViewModel.ts + // src/ViewModel/Chat/chatMessageViewModel.ts var ChatMessageViewModel = class { - chatViewModel; + messagePageViewModel; // data chatMessage; channel; @@ -1211,10 +1214,10 @@ navigator.clipboard.writeText(this.body.value); }; resendMessage = () => { - this.chatViewModel.sendMessageFromBody(this.body.value); + this.messagePageViewModel.sendMessageFromBody(this.body.value); }; decryptMessage = () => { - this.chatViewModel.decryptMessage(this); + this.messagePageViewModel.decryptMessage(this); }; // load loadData = () => { @@ -1225,22 +1228,75 @@ this.status.value = this.chatMessage.status; }; // init - constructor(chatViewModel, chatMessage, sentByUser) { - this.chatViewModel = chatViewModel; + constructor(messagePageViewModel, chatMessage, sentByUser) { + this.messagePageViewModel = messagePageViewModel; this.chatMessage = chatMessage; this.sentByUser = sentByUser; this.loadData(); } }; - // src/ViewModel/chatViewModel.ts - var ChatViewModel = class { - chatModel; - storageModel; - settingsViewModel; - chatListViewModel; + // src/ViewModel/Pages/messagePageViewModel.ts + var MessagePageViewModel = class { + chatViewModel; + // state + chatMessageViewModels = new MapState(); + composingMessage = new State(""); + // guards + cannotSendMessage; + // methods + addChatMessage = (chatMessage) => { + const chatMessageModel = new ChatMessageViewModel( + this, + chatMessage, + chatMessage.sender == this.chatViewModel.settingsViewModel.username.value + ); + const existingChatMessageViewModel = this.chatMessageViewModels.value.get(chatMessage.id); + if (existingChatMessageViewModel != void 0) { + existingChatMessageViewModel.body.value = chatMessage.body; + existingChatMessageViewModel.status.value = chatMessage.status; + } else { + this.chatMessageViewModels.set(chatMessage.id, chatMessageModel); + } + }; + // messaging + sendMessage = () => { + if (this.cannotSendMessage.value == true) return; + this.sendMessageFromBody(this.composingMessage.value); + this.composingMessage.value = ""; + }; + sendMessageFromBody = (body) => { + this.chatViewModel.chatModel.sendMessage(body); + }; + decryptMessage = async (messageViewModel) => { + const chatMessage = messageViewModel.chatMessage; + await this.chatViewModel.chatModel.decryptMessage(chatMessage); + this.chatViewModel.chatModel.addMessage(chatMessage); + messageViewModel.loadData(); + }; + // load + loadData = () => { + this.cannotSendMessage = createProxyState( + [this.chatViewModel.settingsViewModel.username, this.composingMessage], + () => this.chatViewModel.settingsViewModel.username.value == "" || this.composingMessage.value == "" + ); + }; + loadMessages = () => { + for (const chatMessage of this.chatViewModel.chatModel.messages) { + this.addChatMessage(chatMessage); + } + }; + // init + constructor(chatViewModel) { + this.chatViewModel = chatViewModel; + this.loadData(); + } + }; + + // src/ViewModel/Pages/settingsPageViewModel.ts + var SettingsPageViewModel = class { + chatViewModel; // state - index = new State(0); primaryChannel = new State(""); primaryChannelInput = new State(""); secondaryChannels = new ListState(); @@ -1252,11 +1308,6 @@ () => this.shouldShowEncryptionKey.value == true ? "text" : "password" ); color = new State("standard" /* Standard */); - selectedPage = new State( - "messages" /* Messages */ - ); - chatMessageViewModels = new MapState(); - composingMessage = new State(""); // guards cannotSetPrimaryChannel = createProxyState( [this.primaryChannel, this.primaryChannelInput], @@ -1267,39 +1318,13 @@ () => this.newSecondaryChannelInput.value == "" ); cannotSetEncryptionKey; - cannotSendMessage; - // sorting - updateIndex = () => { - this.index.value = this.chatModel.index; - }; - // view - open = () => { - this.chatListViewModel.openChat(this); - this.loadMessages(); - }; - close = () => { - this.chatListViewModel.closeChat(); - }; - // add - addChatMessage = (chatMessage) => { - const chatMessageModel = new ChatMessageViewModel( - this, - chatMessage, - chatMessage.sender == this.settingsViewModel.username.value - ); - const existingChatMessageViewModel = this.chatMessageViewModels.value.get(chatMessage.id); - if (existingChatMessageViewModel != void 0) { - existingChatMessageViewModel.body.value = chatMessage.body; - existingChatMessageViewModel.status.value = chatMessage.status; - } else { - this.chatMessageViewModels.set(chatMessage.id, chatMessageModel); - } - }; - // settings + // methods setPrimaryChannel = () => { - this.chatModel.setPrimaryChannel(this.primaryChannelInput.value); - this.primaryChannel.value = this.chatModel.info.primaryChannel; - this.chatListViewModel.updateIndices(); + this.chatViewModel.chatModel.setPrimaryChannel( + this.primaryChannelInput.value + ); + this.primaryChannel.value = this.chatViewModel.chatModel.info.primaryChannel; + this.chatViewModel.chatListViewModel.updateIndices(); }; addSecondaryChannel = () => { this.secondaryChannels.add(this.newSecondaryChannelInput.value); @@ -1312,37 +1337,99 @@ this.storeSecondaryChannels(); }; storeSecondaryChannels = () => { - this.chatModel.setSecondaryChannels([ + this.chatViewModel.chatModel.setSecondaryChannels([ ...this.secondaryChannels.value.values() ]); }; setEncryptionKey = () => { - this.chatModel.setEncryptionKey(this.encryptionKeyInput.value); + this.chatViewModel.chatModel.setEncryptionKey( + this.encryptionKeyInput.value + ); this.encryptionKeyInput.callSubscriptions(); }; setColor = (newColor) => { this.color.value = newColor; - this.chatModel.setColor(newColor); + this.chatViewModel.chatModel.setColor(newColor); }; remove = () => { - this.close(); - this.chatModel.delete(); - this.chatListViewModel.loadChats(); + this.chatViewModel.close(); + this.chatViewModel.chatModel.delete(); + this.chatViewModel.chatListViewModel.loadChats(); }; - // messaging - sendMessage = () => { - if (this.cannotSendMessage.value == true) return; - this.sendMessageFromBody(this.composingMessage.value); - this.composingMessage.value = ""; + // load + loadViewRelevantData = () => { + this.primaryChannel.value = this.chatViewModel.chatModel.info.primaryChannel; + this.color.value = this.chatViewModel.chatModel.color; + this.cannotSetEncryptionKey = createProxyState( + [this.encryptionKeyInput], + () => this.encryptionKeyInput.value == this.chatViewModel.chatModel.info.encryptionKey + ); }; - sendMessageFromBody = (body) => { - this.chatModel.sendMessage(body); + loadData = () => { + this.primaryChannelInput.value = this.chatViewModel.chatModel.info.primaryChannel; + this.loadSecondaryChannels(); + this.encryptionKeyInput.value = this.chatViewModel.chatModel.info.encryptionKey; }; - decryptMessage = async (messageViewModel) => { - const chatMessage = messageViewModel.chatMessage; - await this.chatModel.decryptMessage(chatMessage); - this.chatModel.addMessage(chatMessage); - messageViewModel.loadData(); + loadSecondaryChannels = () => { + this.secondaryChannels.clear(); + for (const secondaryChannel of this.chatViewModel.chatModel.secondaryChannels) { + this.secondaryChannels.add(secondaryChannel); + } + }; + // init + constructor(chatViewModel) { + this.chatViewModel = chatViewModel; + this.loadViewRelevantData(); + } + }; + + // src/ViewModel/Pages/taskPageViewModel.ts + var TaskPageViewModel = class { + taskModel; + // state + newBoardNameInput = new State(""); + boards = new ListState(); + // guards + cannotCreateBoard = createProxyState( + [this.newBoardNameInput], + () => this.newBoardNameInput.value == "" + ); + // methods + createBoard = () => { + if (this.cannotCreateBoard.value == true) return; + this.taskModel.createBoard(this.newBoardNameInput.value); + this.newBoardNameInput.value = ""; + }; + // init + constructor(taskModel, storageModel2) { + this.taskModel = taskModel; + } + }; + + // src/ViewModel/Chat/chatViewModel.ts + var ChatViewModel = class { + chatModel; + storageModel; + settingsViewModel; + chatListViewModel; + taskPageViewModel; + messagePageViewModel; + settingsPageViewModel; + // state + index = new State(0); + selectedPage = new State( + "messages" /* Messages */ + ); + // sorting + updateIndex = () => { + this.index.value = this.chatModel.index; + }; + // view + open = () => { + this.chatListViewModel.openChat(this); + }; + close = () => { + this.chatListViewModel.closeChat(); }; // load loadPageSelection = () => { @@ -1358,47 +1445,27 @@ this.storageModel.write(path, newPage); }); }; - loadSecondaryChannels = () => { - this.secondaryChannels.clear(); - for (const secondaryChannel of this.chatModel.info.secondaryChannels.sort( - localeCompare - )) { - this.secondaryChannels.add(secondaryChannel); - } - }; - loadMessages = () => { - for (const chatMessage of this.chatModel.messages) { - this.addChatMessage(chatMessage); - } - }; // init constructor(chatModel, storageModel2, settingsViewModel2, chatListViewModel2) { this.chatModel = chatModel; this.storageModel = storageModel2; this.settingsViewModel = settingsViewModel2; this.chatListViewModel = chatListViewModel2; - chatModel.setMessageHandler((chatMessage) => { - this.addChatMessage(chatMessage); - }); - this.primaryChannel.value = chatModel.info.primaryChannel; - this.primaryChannelInput.value = chatModel.info.primaryChannel; - this.encryptionKeyInput.value = chatModel.info.encryptionKey; - this.cannotSetEncryptionKey = createProxyState( - [this.encryptionKeyInput], - () => this.encryptionKeyInput.value == this.chatModel.info.encryptionKey + this.taskPageViewModel = new TaskPageViewModel( + this.chatModel.fileModel.taskModel, + this.storageModel ); - this.color.value = chatModel.color; - this.loadSecondaryChannels(); + this.messagePageViewModel = new MessagePageViewModel(this); + this.settingsPageViewModel = new SettingsPageViewModel(this); + chatModel.setMessageHandler((chatMessage) => { + this.messagePageViewModel.addChatMessage(chatMessage); + }); this.loadPageSelection(); this.updateIndex(); - this.cannotSendMessage = createProxyState( - [this.settingsViewModel.username, this.composingMessage], - () => this.settingsViewModel.username.value == "" || this.composingMessage.value == "" - ); } }; - // src/ViewModel/chatListViewModel.ts + // src/ViewModel/Chat/chatListViewModel.ts var ChatListViewModel = class { chatListModel; storageModel; @@ -1565,6 +1632,7 @@ deleteChatButton: "Delete entire chat" }, message: { + messagesHeadline: "Messages", composerInputPlaceholder: "Type a message...", sendMessageButtonAudioLabel: "send message", showMessageInfoButtonAudioLabel: "show message info", @@ -1661,13 +1729,14 @@ }; // src/View/ChatPages/messagePage.tsx - function MessagePage(chatViewModel) { + function MessagePage(messagePageViewModel) { + messagePageViewModel.loadMessages(); const messageContainer = /* @__PURE__ */ createElement( "div", { id: "message-container", "children:append": [ - chatViewModel.chatMessageViewModels, + messagePageViewModel.chatMessageViewModels, ChatMessageViewModelToView ] } @@ -1680,13 +1749,15 @@ if (scrollFromBottom > 400) return; scrollDown(); } - chatViewModel.chatMessageViewModels.subscribeSilent(scrollDownIfApplicable); + messagePageViewModel.chatMessageViewModels.subscribeSilent( + scrollDownIfApplicable + ); setTimeout(() => scrollDown(), 100); - return /* @__PURE__ */ createElement("div", { id: "message-page" }, /* @__PURE__ */ createElement("div", { class: "pane" }, /* @__PURE__ */ createElement("div", { class: "toolbar" }, /* @__PURE__ */ createElement("span", { "subscribe:innerText": chatViewModel.primaryChannel })), /* @__PURE__ */ createElement("div", { class: "content" }, messageContainer, /* @__PURE__ */ createElement("div", { id: "composer" }, /* @__PURE__ */ createElement("div", { class: "content-width-constraint" }, /* @__PURE__ */ createElement("div", { class: "input-width-constraint" }, /* @__PURE__ */ createElement( + return /* @__PURE__ */ createElement("div", { id: "message-page" }, /* @__PURE__ */ createElement("div", { class: "pane" }, /* @__PURE__ */ createElement("div", { class: "toolbar" }, /* @__PURE__ */ createElement("span", null, translations.chatPage.message.messagesHeadline)), /* @__PURE__ */ createElement("div", { class: "content" }, messageContainer, /* @__PURE__ */ createElement("div", { id: "composer" }, /* @__PURE__ */ createElement("div", { class: "content-width-constraint" }, /* @__PURE__ */ createElement("div", { class: "input-width-constraint" }, /* @__PURE__ */ createElement( "input", { - "bind:value": chatViewModel.composingMessage, - "on:enter": chatViewModel.sendMessage, + "bind:value": messagePageViewModel.composingMessage, + "on:enter": messagePageViewModel.sendMessage, placeholder: translations.chatPage.message.composerInputPlaceholder } ), /* @__PURE__ */ createElement( @@ -1694,8 +1765,8 @@ { class: "primary", "aria-label": translations.chatPage.message.sendMessageButtonAudioLabel, - "on:click": chatViewModel.sendMessage, - "toggle:disabled": chatViewModel.cannotSendMessage + "on:click": messagePageViewModel.sendMessage, + "toggle:disabled": messagePageViewModel.cannotSendMessage }, /* @__PURE__ */ createElement("span", { class: "icon" }, "send") ))))))); @@ -1749,25 +1820,26 @@ } // src/View/ChatPages/settingsPage.tsx - function SettingsPage(chatViewModel) { + function SettingsPage(settingsPageViewModel) { + settingsPageViewModel.loadData(); const secondaryChannelConverter = (secondaryChannel) => { return DeletableListItem(secondaryChannel, /* @__PURE__ */ createElement("span", null), () => { - chatViewModel.removeSecondaryChannel(secondaryChannel); + settingsPageViewModel.removeSecondaryChannel(secondaryChannel); }); }; return /* @__PURE__ */ createElement("div", { id: "settings-page" }, /* @__PURE__ */ createElement("div", { class: "pane" }, /* @__PURE__ */ createElement("div", { class: "toolbar" }, /* @__PURE__ */ createElement("span", null, translations.chatPage.settings.settingsHeadline)), /* @__PURE__ */ createElement("div", { class: "content" }, /* @__PURE__ */ createElement("label", { class: "tile flex-no" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "forum"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translations.chatPage.settings.primaryChannelLabel), /* @__PURE__ */ createElement( "input", { - "bind:value": chatViewModel.primaryChannelInput, - "on:enter": chatViewModel.setPrimaryChannel + "bind:value": settingsPageViewModel.primaryChannelInput, + "on:enter": settingsPageViewModel.setPrimaryChannel } ))), /* @__PURE__ */ createElement("div", { class: "flex-row justify-end width-input" }, /* @__PURE__ */ createElement( "button", { class: "width-50", "aria-label": translations.chatPage.settings.setPrimaryChannelButtonAudioLabel, - "on:click": chatViewModel.setPrimaryChannel, - "toggle:disabled": chatViewModel.cannotSetPrimaryChannel + "on:click": settingsPageViewModel.setPrimaryChannel, + "toggle:disabled": settingsPageViewModel.cannotSetPrimaryChannel }, translations.general.setButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "check") @@ -1776,16 +1848,16 @@ { "aria-label": translations.chatPage.settings.newSecondaryChannelAudioLabel, placeholder: translations.chatPage.settings.newSecondaryChannelPlaceholder, - "bind:value": chatViewModel.newSecondaryChannelInput, - "on:enter": chatViewModel.addSecondaryChannel + "bind:value": settingsPageViewModel.newSecondaryChannelInput, + "on:enter": settingsPageViewModel.addSecondaryChannel } ), /* @__PURE__ */ createElement( "button", { class: "primary", "aria-label": translations.chatPage.settings.addSecondaryChannelButtonAudioLabel, - "on:click": chatViewModel.addSecondaryChannel, - "toggle:disabled": chatViewModel.cannotAddSecondaryChannel + "on:click": settingsPageViewModel.addSecondaryChannel, + "toggle:disabled": settingsPageViewModel.cannotAddSecondaryChannel }, /* @__PURE__ */ createElement("span", { class: "icon" }, "add") )), /* @__PURE__ */ createElement( @@ -1793,24 +1865,24 @@ { class: "flex-column gap width-input", "children:append": [ - chatViewModel.secondaryChannels, + settingsPageViewModel.secondaryChannels, secondaryChannelConverter ] } ), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("label", { class: "tile flex-no" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "key"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translations.chatPage.settings.encryptionKeyLabel), /* @__PURE__ */ createElement( "input", { - "bind:value": chatViewModel.encryptionKeyInput, - "on:enter": chatViewModel.setEncryptionKey, - "set:type": chatViewModel.encryptionKeyInputType + "bind:value": settingsPageViewModel.encryptionKeyInput, + "on:enter": settingsPageViewModel.setEncryptionKey, + "set:type": settingsPageViewModel.encryptionKeyInputType } ))), /* @__PURE__ */ createElement("div", { class: "flex-row justify-end width-input" }, /* @__PURE__ */ createElement( "button", { class: "width-50", "aria-label": translations.chatPage.settings.setEncryptionKeyButtonAudioLabel, - "on:click": chatViewModel.setEncryptionKey, - "toggle:disabled": chatViewModel.cannotSetEncryptionKey + "on:click": settingsPageViewModel.setEncryptionKey, + "toggle:disabled": settingsPageViewModel.cannotSetEncryptionKey }, translations.general.setButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "check") @@ -1818,15 +1890,15 @@ "input", { type: "checkbox", - "bind:checked": chatViewModel.shouldShowEncryptionKey + "bind:checked": settingsPageViewModel.shouldShowEncryptionKey } ), translations.chatPage.settings.showEncryptionKey), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-row gap width-input" }, ...Object.values(Color).map((color) => { const isSelected = createProxyState( - [chatViewModel.color], - () => chatViewModel.color.value == color + [settingsPageViewModel.color], + () => settingsPageViewModel.color.value == color ); function setColor() { - chatViewModel.setColor(color); + settingsPageViewModel.setColor(color); } return /* @__PURE__ */ createElement( "button", @@ -1841,25 +1913,29 @@ })), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "width-input" }, DangerousActionButton( translations.chatPage.settings.deleteChatButton, "chat_error", - chatViewModel.remove + settingsPageViewModel.remove ))))); } // src/View/ChatPages/taskPage.tsx - function TaskPage(chatViewModel) { + function TaskPage(taskPageViewModel) { return /* @__PURE__ */ createElement("div", { id: "task-page" }, /* @__PURE__ */ createElement("div", { class: "pane side" }, /* @__PURE__ */ createElement("div", { class: "content" }, /* @__PURE__ */ createElement("div", { class: "flex-row width-input" }, /* @__PURE__ */ createElement( "input", { + "bind:value": taskPageViewModel.newBoardNameInput, + "on:enter": taskPageViewModel.createBoard, placeholder: translations.chatPage.task.newBoardNamePlaceholder } ), /* @__PURE__ */ createElement( "button", { class: "primary", - "aria-label": translations.chatPage.task.createBoardButtonAudioLabel + "aria-label": translations.chatPage.task.createBoardButtonAudioLabel, + "on:click": taskPageViewModel.createBoard, + "toggle:disabled": taskPageViewModel.cannotCreateBoard }, /* @__PURE__ */ createElement("span", { class: "icon" }, "add") - )), /* @__PURE__ */ createElement("div", { class: "flex-row gap" }))), /* @__PURE__ */ createElement("div", { class: "pane" }, /* @__PURE__ */ createElement("div", { class: "toolbar" }, /* @__PURE__ */ createElement("span", { "subscribe:innerText": chatViewModel.primaryChannel })), /* @__PURE__ */ createElement("div", { class: "content" }))); + )), /* @__PURE__ */ createElement("div", { class: "flex-row gap" }))), /* @__PURE__ */ createElement("div", { class: "pane" }, /* @__PURE__ */ createElement("div", { class: "toolbar" }), /* @__PURE__ */ createElement("div", { class: "content" }))); } // src/View/chatPage.tsx @@ -1867,19 +1943,24 @@ const mainContent = new State(/* @__PURE__ */ createElement("div", null)); chatViewModel.selectedPage.subscribe((selectedPage) => { switch (selectedPage) { - case "settings" /* Settings */: - return mainContent.value = SettingsPage(chatViewModel); - case "tasks" /* Tasks */: - return mainContent.value = TaskPage(chatViewModel); - default: - return mainContent.value = MessagePage(chatViewModel); + case "settings" /* Settings */: { + mainContent.value = SettingsPage(chatViewModel.settingsPageViewModel); + break; + } + case "tasks" /* Tasks */: { + mainContent.value = TaskPage(chatViewModel.taskPageViewModel); + break; + } + default: { + mainContent.value = MessagePage(chatViewModel.messagePageViewModel); + } } }); return /* @__PURE__ */ createElement( "article", { id: "chat-page", - "set:color": chatViewModel.color, + "set:color": chatViewModel.settingsPageViewModel.color, class: "subtle-background" }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("div", { id: "ribbon" }, /* @__PURE__ */ createElement( @@ -2300,7 +2381,7 @@ } }; - // src/ViewModel/connectionViewModel.ts + // src/ViewModel/Global/connectionViewModel.ts var ConnectionViewModel = class { connectionModel; // state @@ -2374,13 +2455,27 @@ // src/View/Components/chatEntry.tsx function ChatEntry(chatViewModel) { - const view = /* @__PURE__ */ createElement("button", { "set:color": chatViewModel.color, class: "chat-entry tile", "on:click": chatViewModel.open }, /* @__PURE__ */ createElement( - "span", + const view = /* @__PURE__ */ createElement( + "button", { - class: "shadow", - "subscribe:innerText": chatViewModel.primaryChannel - } - ), /* @__PURE__ */ createElement("h2", { "subscribe:innerText": chatViewModel.primaryChannel })); + "set:color": chatViewModel.settingsPageViewModel.color, + class: "chat-entry tile", + "on:click": chatViewModel.open + }, + /* @__PURE__ */ createElement( + "span", + { + class: "shadow", + "subscribe:innerText": chatViewModel.settingsPageViewModel.primaryChannel + } + ), + /* @__PURE__ */ createElement( + "h2", + { + "subscribe:innerText": chatViewModel.settingsPageViewModel.primaryChannel + } + ) + ); chatViewModel.index.subscribe((newIndex) => { view.style.order = newIndex; }); @@ -2542,7 +2637,7 @@ } }; - // src/ViewModel/settingsViewModel.ts + // src/ViewModel/Global/settingsViewModel.ts var SettingsViewModel = class { settingsModel; // state @@ -2665,7 +2760,7 @@ return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": storageViewModel2.isShowingStorageModal }, /* @__PURE__ */ createElement("div", { style: "max-width: 64rem" }, /* @__PURE__ */ createElement("main", { class: "padding-0" }, FileBrowser(storageViewModel2)), /* @__PURE__ */ createElement("button", { "on:click": storageViewModel2.hideStorageModal }, translations.general.closeButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "close")))); } - // src/ViewModel/storageViewModel.ts + // src/ViewModel/Global/storageViewModel.ts var StorageViewModel = class { storageModel; // state diff --git a/src/Model/Chat/chatModel.ts b/src/Model/Chat/chatModel.ts index e31126c0..117a96c9 100644 --- a/src/Model/Chat/chatModel.ts +++ b/src/Model/Chat/chatModel.ts @@ -5,6 +5,7 @@ import FileModel, { FileContent } from "../Files/fileModel"; import StorageModel, { filePaths } from "../Global/storageModel"; import { createTimestamp, + localeCompare, parseValidObject, stringify, } from "../Utility/utility"; @@ -31,6 +32,10 @@ export default class ChatModel { chatMessageHandler: (chatMessage: ChatMessage) => void = () => {}; + get secondaryChannels(): string[] { + return this.info.secondaryChannels.sort(localeCompare); + } + // paths getBasePath = (): string[] => { return StorageModel.getPath("chat", filePaths.chat.chatBase(this.id)); diff --git a/src/View/ChatPages/messagePage.tsx b/src/View/ChatPages/messagePage.tsx index 0e991bc9..a1af6601 100644 --- a/src/View/ChatPages/messagePage.tsx +++ b/src/View/ChatPages/messagePage.tsx @@ -3,15 +3,17 @@ import "./messagePage.css"; import * as React from "bloatless-react"; import { ChatMessageViewModelToView } from "../Components/chatMessage"; -import ChatViewModel from "../../ViewModel/Chat/chatViewModel"; +import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel"; import { translations } from "../translations"; -export function MessagePage(chatViewModel: ChatViewModel) { +export function MessagePage(messagePageViewModel: MessagePageViewModel) { + messagePageViewModel.loadMessages(); + const messageContainer = (
@@ -28,14 +30,16 @@ export function MessagePage(chatViewModel: ChatViewModel) { scrollDown(); } - chatViewModel.chatMessageViewModels.subscribeSilent(scrollDownIfApplicable); + messagePageViewModel.chatMessageViewModels.subscribeSilent( + scrollDownIfApplicable + ); setTimeout(() => scrollDown(), 100); return (
- + {translations.chatPage.message.messagesHeadline}
{messageContainer} @@ -43,8 +47,8 @@ export function MessagePage(chatViewModel: ChatViewModel) {
send diff --git a/src/View/ChatPages/settingsPage.tsx b/src/View/ChatPages/settingsPage.tsx index 333407e2..4decca27 100644 --- a/src/View/ChatPages/settingsPage.tsx +++ b/src/View/ChatPages/settingsPage.tsx @@ -1,17 +1,19 @@ import * as React from "bloatless-react"; -import ChatViewModel from "../../ViewModel/chatViewModel"; import { Color } from "../../colors"; import { DangerousActionButton } from "../Components/dangerousActionButton"; import { DeletableListItem } from "../Components/deletableListItem"; +import SettingsPageViewModel from "../../ViewModel/Pages/settingsPageViewModel"; import { translations } from "../translations"; -export function SettingsPage(chatViewModel: ChatViewModel) { +export function SettingsPage(settingsPageViewModel: SettingsPageViewModel) { + settingsPageViewModel.loadData(); + const secondaryChannelConverter: React.StateItemConverter = ( secondaryChannel: string ) => { return DeletableListItem(secondaryChannel, , () => { - chatViewModel.removeSecondaryChannel(secondaryChannel); + settingsPageViewModel.removeSecondaryChannel(secondaryChannel); }); }; @@ -27,8 +29,8 @@ export function SettingsPage(chatViewModel: ChatViewModel) {
{translations.chatPage.settings.primaryChannelLabel}
@@ -38,8 +40,8 @@ export function SettingsPage(chatViewModel: ChatViewModel) { aria-label={ translations.chatPage.settings.setPrimaryChannelButtonAudioLabel } - on:click={chatViewModel.setPrimaryChannel} - toggle:disabled={chatViewModel.cannotSetPrimaryChannel} + on:click={settingsPageViewModel.setPrimaryChannel} + toggle:disabled={settingsPageViewModel.cannotSetPrimaryChannel} > {translations.general.setButton} check @@ -56,8 +58,8 @@ export function SettingsPage(chatViewModel: ChatViewModel) { placeholder={ translations.chatPage.settings.newSecondaryChannelPlaceholder } - bind:value={chatViewModel.newSecondaryChannelInput} - on:enter={chatViewModel.addSecondaryChannel} + bind:value={settingsPageViewModel.newSecondaryChannelInput} + on:enter={settingsPageViewModel.addSecondaryChannel} > @@ -75,7 +77,7 @@ export function SettingsPage(chatViewModel: ChatViewModel) {
@@ -87,9 +89,9 @@ export function SettingsPage(chatViewModel: ChatViewModel) {
{translations.chatPage.settings.encryptionKeyLabel}
@@ -99,8 +101,8 @@ export function SettingsPage(chatViewModel: ChatViewModel) { aria-label={ translations.chatPage.settings.setEncryptionKeyButtonAudioLabel } - on:click={chatViewModel.setEncryptionKey} - toggle:disabled={chatViewModel.cannotSetEncryptionKey} + on:click={settingsPageViewModel.setEncryptionKey} + toggle:disabled={settingsPageViewModel.cannotSetEncryptionKey} > {translations.general.setButton} check @@ -110,7 +112,7 @@ export function SettingsPage(chatViewModel: ChatViewModel) { @@ -120,12 +122,12 @@ export function SettingsPage(chatViewModel: ChatViewModel) {
{...Object.values(Color).map((color) => { const isSelected = React.createProxyState( - [chatViewModel.color], - () => chatViewModel.color.value == color + [settingsPageViewModel.color], + () => settingsPageViewModel.color.value == color ); function setColor() { - chatViewModel.setColor(color); + settingsPageViewModel.setColor(color); } return ( @@ -146,7 +148,7 @@ export function SettingsPage(chatViewModel: ChatViewModel) { {DangerousActionButton( translations.chatPage.settings.deleteChatButton, "chat_error", - chatViewModel.remove + settingsPageViewModel.remove )}
diff --git a/src/View/ChatPages/taskPage.tsx b/src/View/ChatPages/taskPage.tsx index 6505db3d..35bab475 100644 --- a/src/View/ChatPages/taskPage.tsx +++ b/src/View/ChatPages/taskPage.tsx @@ -1,17 +1,17 @@ import * as React from "bloatless-react"; -import TaskViewModel from "../../ViewModel/Files/taskViewModel"; +import TaskPageViewModel from "../../ViewModel/Pages/taskPageViewModel"; import { translations } from "../translations"; -export function TaskPage(taskViewModel: TaskViewModel) { +export function TaskPage(taskPageViewModel: TaskPageViewModel) { return (
diff --git a/src/View/Components/chatEntry.tsx b/src/View/Components/chatEntry.tsx index fdb2b928..2858a79c 100644 --- a/src/View/Components/chatEntry.tsx +++ b/src/View/Components/chatEntry.tsx @@ -6,12 +6,18 @@ import ChatViewModel from "../../ViewModel/Chat/chatViewModel"; export function ChatEntry(chatViewModel: ChatViewModel) { const view = ( - ); diff --git a/src/View/Components/chatMessageInfoModal.tsx b/src/View/Components/chatMessageInfoModal.tsx index 0cce0ed7..80d547dd 100644 --- a/src/View/Components/chatMessageInfoModal.tsx +++ b/src/View/Components/chatMessageInfoModal.tsx @@ -1,6 +1,6 @@ import * as React from "bloatless-react"; -import ChatMessageViewModel from "../../Model/chatMessageViewModel"; +import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel"; import { translations } from "../translations"; export function ChatMessageInfoModal( diff --git a/src/View/Components/chatViewToggleButton.tsx b/src/View/Components/chatViewToggleButton.tsx index 964f8026..0fafa7ab 100644 --- a/src/View/Components/chatViewToggleButton.tsx +++ b/src/View/Components/chatViewToggleButton.tsx @@ -1,6 +1,6 @@ import * as React from "bloatless-react"; -import ChatViewModel, { ChatPageType } from "../../ViewModel/chatViewModel"; +import ChatViewModel, { ChatPageType } from "../../ViewModel/Chat/chatViewModel"; export function ChatViewToggleButton( label: string, diff --git a/src/View/chatPage.tsx b/src/View/chatPage.tsx index 65e4ea11..133f2437 100644 --- a/src/View/chatPage.tsx +++ b/src/View/chatPage.tsx @@ -15,19 +15,24 @@ export function ChatPage(chatViewModel: ChatViewModel) { chatViewModel.selectedPage.subscribe((selectedPage) => { switch (selectedPage) { - case ChatPageType.Settings: - return (mainContent.value = SettingsPage(chatViewModel)); - case ChatPageType.Tasks: - return (mainContent.value = TaskPage(chatViewModel)); - default: - return (mainContent.value = MessagePage(chatViewModel)); + case ChatPageType.Settings: { + mainContent.value = SettingsPage(chatViewModel.settingsPageViewModel); + break; + } + case ChatPageType.Tasks: { + mainContent.value = TaskPage(chatViewModel.taskPageViewModel); + break; + } + default: { + mainContent.value = MessagePage(chatViewModel.messagePageViewModel); + } } }); return (
diff --git a/src/View/chatPageWrapper.tsx b/src/View/chatPageWrapper.tsx index 46c6a715..ac732b07 100644 --- a/src/View/chatPageWrapper.tsx +++ b/src/View/chatPageWrapper.tsx @@ -2,7 +2,7 @@ import "./chatPage.css"; import * as React from "bloatless-react"; -import ChatListViewModel from "../ViewModel/chatListViewModel"; +import ChatListViewModel from "../ViewModel/Chat/chatListViewModel"; import { ChatPage } from "./chatPage"; export function ChatPageWrapper(chatListViewModel: ChatListViewModel) { diff --git a/src/View/homePage.tsx b/src/View/homePage.tsx index 83e8f726..2e15505f 100644 --- a/src/View/homePage.tsx +++ b/src/View/homePage.tsx @@ -4,7 +4,7 @@ import * as React from "bloatless-react"; import { Option, StringToOption } from "./Components/option"; -import ChatListViewModel from "../ViewModel/chatListViewModel"; +import ChatListViewModel from "../ViewModel/Chat/chatListViewModel"; import { ChatViewModelToChatEntry } from "./Components/chatEntry"; import ConnectionViewModel from "../ViewModel/Global/connectionViewModel"; import SettingsViewModel from "../ViewModel/Global/settingsViewModel"; diff --git a/src/View/translations.ts b/src/View/translations.ts index 15f7e0c0..f4fc2b2e 100644 --- a/src/View/translations.ts +++ b/src/View/translations.ts @@ -104,6 +104,8 @@ const englishTranslations = { }, message: { + messagesHeadline: "Messages", + composerInputPlaceholder: "Type a message...", sendMessageButtonAudioLabel: "send message", diff --git a/src/ViewModel/Chat/chatMessageViewModel.ts b/src/ViewModel/Chat/chatMessageViewModel.ts index e5ed9940..b11bd67d 100644 --- a/src/ViewModel/Chat/chatMessageViewModel.ts +++ b/src/ViewModel/Chat/chatMessageViewModel.ts @@ -5,9 +5,10 @@ import * as React from "bloatless-react"; import { ChatMessage, ChatMessageStatus } from "../../Model/Chat/chatModel"; import ChatViewModel from "./chatViewModel"; +import MessagePageViewModel from "../Pages/messagePageViewModel"; export default class ChatMessageViewModel { - chatViewModel: ChatViewModel; + messagePageViewModel: MessagePageViewModel; // data chatMessage: ChatMessage; @@ -25,10 +26,10 @@ export default class ChatMessageViewModel { navigator.clipboard.writeText(this.body.value); }; resendMessage = (): void => { - this.chatViewModel.sendMessageFromBody(this.body.value); + this.messagePageViewModel.sendMessageFromBody(this.body.value); }; decryptMessage = (): void => { - this.chatViewModel.decryptMessage(this); + this.messagePageViewModel.decryptMessage(this); }; // load @@ -42,11 +43,11 @@ export default class ChatMessageViewModel { // init constructor( - chatViewModel: ChatViewModel, + messagePageViewModel: MessagePageViewModel, chatMessage: ChatMessage, sentByUser: boolean ) { - this.chatViewModel = chatViewModel; + this.messagePageViewModel = messagePageViewModel; this.chatMessage = chatMessage; this.sentByUser = sentByUser; diff --git a/src/ViewModel/Chat/chatViewModel.ts b/src/ViewModel/Chat/chatViewModel.ts index 9c653d4e..53c5e9fe 100644 --- a/src/ViewModel/Chat/chatViewModel.ts +++ b/src/ViewModel/Chat/chatViewModel.ts @@ -4,10 +4,10 @@ import ChatModel, { ChatMessage } from "../../Model/Chat/chatModel"; import StorageModel, { filePaths } from "../../Model/Global/storageModel"; import ChatListViewModel from "./chatListViewModel"; -import ChatMessageViewModel from "./chatMessageViewModel"; -import { Color } from "../../colors"; +import MessagePageViewModel from "../Pages/messagePageViewModel"; +import SettingsPageViewModel from "../Pages/settingsPageViewModel"; import SettingsViewModel from "../Global/settingsViewModel"; -import { localeCompare } from "../../Model/Utility/utility"; +import TaskPageViewModel from "../Pages/taskPageViewModel"; export default class ChatViewModel { chatModel: ChatModel; @@ -15,46 +15,17 @@ export default class ChatViewModel { settingsViewModel: SettingsViewModel; chatListViewModel: ChatListViewModel; + taskPageViewModel: TaskPageViewModel; + messagePageViewModel: MessagePageViewModel; + settingsPageViewModel: SettingsPageViewModel; + // state index: React.State = new React.State(0); - primaryChannel: React.State = new React.State(""); - primaryChannelInput: React.State = new React.State(""); - - secondaryChannels: React.ListState = new React.ListState(); - newSecondaryChannelInput: React.State = new React.State(""); - - encryptionKeyInput: React.State = new React.State(""); - shouldShowEncryptionKey: React.State = new React.State(false); - encryptionKeyInputType: React.State<"text" | "password"> = - React.createProxyState([this.shouldShowEncryptionKey], () => - this.shouldShowEncryptionKey.value == true ? "text" : "password" - ); - - color: React.State = new React.State(Color.Standard); - selectedPage: React.State = new React.State( ChatPageType.Messages ); - chatMessageViewModels: React.MapState = - new React.MapState(); - composingMessage: React.State = new React.State(""); - - // guards - cannotSetPrimaryChannel: React.State = React.createProxyState( - [this.primaryChannel, this.primaryChannelInput], - () => - this.primaryChannelInput.value == "" || - this.primaryChannelInput.value == this.primaryChannel.value - ); - cannotAddSecondaryChannel: React.State = React.createProxyState( - [this.newSecondaryChannelInput], - () => this.newSecondaryChannelInput.value == "" - ); - cannotSetEncryptionKey: React.State; - cannotSendMessage: React.State; - // sorting updateIndex = (): void => { this.index.value = this.chatModel.index; @@ -63,95 +34,12 @@ export default class ChatViewModel { // view open = (): void => { this.chatListViewModel.openChat(this); - this.loadMessages(); }; close = (): void => { this.chatListViewModel.closeChat(); }; - // add - addChatMessage = (chatMessage: ChatMessage): void => { - const chatMessageModel = new ChatMessageViewModel( - this, - chatMessage, - chatMessage.sender == this.settingsViewModel.username.value - ); - - const existingChatMessageViewModel: ChatMessageViewModel | undefined = - this.chatMessageViewModels.value.get(chatMessage.id); - if (existingChatMessageViewModel != undefined) { - existingChatMessageViewModel.body.value = chatMessage.body; - existingChatMessageViewModel.status.value = chatMessage.status; - } else { - this.chatMessageViewModels.set(chatMessage.id, chatMessageModel); - } - }; - - // settings - setPrimaryChannel = (): void => { - this.chatModel.setPrimaryChannel(this.primaryChannelInput.value); - this.primaryChannel.value = this.chatModel.info.primaryChannel; - this.chatListViewModel.updateIndices(); - }; - - addSecondaryChannel = (): void => { - this.secondaryChannels.add(this.newSecondaryChannelInput.value); - this.newSecondaryChannelInput.value = ""; - this.storeSecondaryChannels(); - this.loadSecondaryChannels(); - }; - - removeSecondaryChannel = (secondaryChannel: string): void => { - this.secondaryChannels.remove(secondaryChannel); - this.storeSecondaryChannels(); - }; - - storeSecondaryChannels = (): void => { - this.chatModel.setSecondaryChannels([ - ...this.secondaryChannels.value.values(), - ]); - }; - - setEncryptionKey = (): void => { - this.chatModel.setEncryptionKey(this.encryptionKeyInput.value); - - // disable button - this.encryptionKeyInput.callSubscriptions(); - }; - - setColor = (newColor: Color): void => { - this.color.value = newColor; - this.chatModel.setColor(newColor); - }; - - remove = (): void => { - this.close(); - this.chatModel.delete(); - this.chatListViewModel.loadChats(); - }; - - // messaging - sendMessage = (): void => { - if (this.cannotSendMessage.value == true) return; - - this.sendMessageFromBody(this.composingMessage.value); - this.composingMessage.value = ""; - }; - - sendMessageFromBody = (body: string): void => { - this.chatModel.sendMessage(body); - }; - - decryptMessage = async ( - messageViewModel: ChatMessageViewModel - ): Promise => { - const chatMessage: ChatMessage = messageViewModel.chatMessage; - await this.chatModel.decryptMessage(chatMessage); - this.chatModel.addMessage(chatMessage); - messageViewModel.loadData(); - }; - // load loadPageSelection = (): void => { const path: string[] = StorageModel.getPath( @@ -168,21 +56,6 @@ export default class ChatViewModel { }); }; - loadSecondaryChannels = (): void => { - this.secondaryChannels.clear(); - for (const secondaryChannel of this.chatModel.info.secondaryChannels.sort( - localeCompare - )) { - this.secondaryChannels.add(secondaryChannel); - } - }; - - loadMessages = (): void => { - for (const chatMessage of this.chatModel.messages) { - this.addChatMessage(chatMessage); - } - }; - // init constructor( chatModel: ChatModel, @@ -196,34 +69,22 @@ export default class ChatViewModel { this.settingsViewModel = settingsViewModel; this.chatListViewModel = chatListViewModel; + // page viewModels + this.taskPageViewModel = new TaskPageViewModel( + this.chatModel.fileModel.taskModel, + this.storageModel + ); + this.messagePageViewModel = new MessagePageViewModel(this); + this.settingsPageViewModel = new SettingsPageViewModel(this); + // handlers chatModel.setMessageHandler((chatMessage) => { - this.addChatMessage(chatMessage); + this.messagePageViewModel.addChatMessage(chatMessage); }); // load - this.primaryChannel.value = chatModel.info.primaryChannel; - this.primaryChannelInput.value = chatModel.info.primaryChannel; - - this.encryptionKeyInput.value = chatModel.info.encryptionKey; - this.cannotSetEncryptionKey = React.createProxyState( - [this.encryptionKeyInput], - () => this.encryptionKeyInput.value == this.chatModel.info.encryptionKey - ); - - this.color.value = chatModel.color; - - this.loadSecondaryChannels(); this.loadPageSelection(); this.updateIndex(); - - // guards - this.cannotSendMessage = React.createProxyState( - [this.settingsViewModel.username, this.composingMessage], - () => - this.settingsViewModel.username.value == "" || - this.composingMessage.value == "" - ); } } diff --git a/src/ViewModel/Pages/messagePageViewModel.ts b/src/ViewModel/Pages/messagePageViewModel.ts new file mode 100644 index 00000000..512d7b74 --- /dev/null +++ b/src/ViewModel/Pages/messagePageViewModel.ts @@ -0,0 +1,78 @@ +import * as React from "bloatless-react"; + +import { ChatMessage } from "../../Model/Chat/chatModel"; +import ChatMessageViewModel from "../Chat/chatMessageViewModel"; +import ChatViewModel from "../Chat/chatViewModel"; + +export default class MessagePageViewModel { + chatViewModel: ChatViewModel; + + // state + chatMessageViewModels: React.MapState = + new React.MapState(); + composingMessage: React.State = new React.State(""); + + // guards + cannotSendMessage: React.State; + + // methods + addChatMessage = (chatMessage: ChatMessage): void => { + const chatMessageModel = new ChatMessageViewModel( + this, + chatMessage, + chatMessage.sender == this.chatViewModel.settingsViewModel.username.value + ); + + const existingChatMessageViewModel: ChatMessageViewModel | undefined = + this.chatMessageViewModels.value.get(chatMessage.id); + if (existingChatMessageViewModel != undefined) { + existingChatMessageViewModel.body.value = chatMessage.body; + existingChatMessageViewModel.status.value = chatMessage.status; + } else { + this.chatMessageViewModels.set(chatMessage.id, chatMessageModel); + } + }; + + // messaging + sendMessage = (): void => { + if (this.cannotSendMessage.value == true) return; + + this.sendMessageFromBody(this.composingMessage.value); + this.composingMessage.value = ""; + }; + + sendMessageFromBody = (body: string): void => { + this.chatViewModel.chatModel.sendMessage(body); + }; + + decryptMessage = async ( + messageViewModel: ChatMessageViewModel + ): Promise => { + const chatMessage: ChatMessage = messageViewModel.chatMessage; + await this.chatViewModel.chatModel.decryptMessage(chatMessage); + this.chatViewModel.chatModel.addMessage(chatMessage); + messageViewModel.loadData(); + }; + + // load + loadData = (): void => { + this.cannotSendMessage = React.createProxyState( + [this.chatViewModel.settingsViewModel.username, this.composingMessage], + () => + this.chatViewModel.settingsViewModel.username.value == "" || + this.composingMessage.value == "" + ); + }; + + loadMessages = (): void => { + for (const chatMessage of this.chatViewModel.chatModel.messages) { + this.addChatMessage(chatMessage); + } + }; + + // init + constructor(chatViewModel: ChatViewModel) { + this.chatViewModel = chatViewModel; + this.loadData(); + } +} diff --git a/src/ViewModel/Pages/settingsPageViewModel.ts b/src/ViewModel/Pages/settingsPageViewModel.ts new file mode 100644 index 00000000..f3cf3bdb --- /dev/null +++ b/src/ViewModel/Pages/settingsPageViewModel.ts @@ -0,0 +1,124 @@ +import * as React from "bloatless-react"; + +import ChatViewModel from "../Chat/chatViewModel"; +import { Color } from "../../colors"; + +export default class SettingsPageViewModel { + chatViewModel: ChatViewModel; + + // state + primaryChannel: React.State = new React.State(""); + primaryChannelInput: React.State = new React.State(""); + + secondaryChannels: React.ListState = new React.ListState(); + newSecondaryChannelInput: React.State = new React.State(""); + + encryptionKeyInput: React.State = new React.State(""); + shouldShowEncryptionKey: React.State = new React.State(false); + encryptionKeyInputType: React.State<"text" | "password"> = + React.createProxyState([this.shouldShowEncryptionKey], () => + this.shouldShowEncryptionKey.value == true ? "text" : "password" + ); + + color: React.State = new React.State(Color.Standard); + + // guards + cannotSetPrimaryChannel: React.State = React.createProxyState( + [this.primaryChannel, this.primaryChannelInput], + () => + this.primaryChannelInput.value == "" || + this.primaryChannelInput.value == this.primaryChannel.value + ); + cannotAddSecondaryChannel: React.State = React.createProxyState( + [this.newSecondaryChannelInput], + () => this.newSecondaryChannelInput.value == "" + ); + cannotSetEncryptionKey: React.State; + + // methods + setPrimaryChannel = (): void => { + this.chatViewModel.chatModel.setPrimaryChannel( + this.primaryChannelInput.value + ); + this.primaryChannel.value = + this.chatViewModel.chatModel.info.primaryChannel; + this.chatViewModel.chatListViewModel.updateIndices(); + }; + + addSecondaryChannel = (): void => { + this.secondaryChannels.add(this.newSecondaryChannelInput.value); + this.newSecondaryChannelInput.value = ""; + this.storeSecondaryChannels(); + this.loadSecondaryChannels(); + }; + + removeSecondaryChannel = (secondaryChannel: string): void => { + this.secondaryChannels.remove(secondaryChannel); + this.storeSecondaryChannels(); + }; + + storeSecondaryChannels = (): void => { + this.chatViewModel.chatModel.setSecondaryChannels([ + ...this.secondaryChannels.value.values(), + ]); + }; + + setEncryptionKey = (): void => { + this.chatViewModel.chatModel.setEncryptionKey( + this.encryptionKeyInput.value + ); + + // disable button + this.encryptionKeyInput.callSubscriptions(); + }; + + setColor = (newColor: Color): void => { + this.color.value = newColor; + this.chatViewModel.chatModel.setColor(newColor); + }; + + remove = (): void => { + this.chatViewModel.close(); + this.chatViewModel.chatModel.delete(); + this.chatViewModel.chatListViewModel.loadChats(); + }; + + // load + loadViewRelevantData = (): void => { + this.primaryChannel.value = + this.chatViewModel.chatModel.info.primaryChannel; + + this.color.value = this.chatViewModel.chatModel.color; + + this.cannotSetEncryptionKey = React.createProxyState( + [this.encryptionKeyInput], + () => + this.encryptionKeyInput.value == + this.chatViewModel.chatModel.info.encryptionKey + ); + }; + + loadData = (): void => { + this.primaryChannelInput.value = + this.chatViewModel.chatModel.info.primaryChannel; + + this.loadSecondaryChannels(); + + this.encryptionKeyInput.value = + this.chatViewModel.chatModel.info.encryptionKey; + }; + + loadSecondaryChannels = (): void => { + this.secondaryChannels.clear(); + for (const secondaryChannel of this.chatViewModel.chatModel + .secondaryChannels) { + this.secondaryChannels.add(secondaryChannel); + } + }; + + // init + constructor(chatViewModel: ChatViewModel) { + this.chatViewModel = chatViewModel; + this.loadViewRelevantData(); + } +} diff --git a/src/ViewModel/Files/taskViewModel.ts b/src/ViewModel/Pages/taskPageViewModel.ts similarity index 87% rename from src/ViewModel/Files/taskViewModel.ts rename to src/ViewModel/Pages/taskPageViewModel.ts index de250cfa..442f2850 100644 --- a/src/ViewModel/Files/taskViewModel.ts +++ b/src/ViewModel/Pages/taskPageViewModel.ts @@ -2,14 +2,12 @@ import * as React from "bloatless-react"; import TaskModel, { BoardInfoFileContent, - TaskFileContent, } from "../../Model/Files/taskModel"; import StorageModel from "../../Model/Global/storageModel"; -export default class TaskViewModel { +export default class TaskPageViewModel { taskModel: TaskModel; - storageModel: StorageModel; // state newBoardNameInput: React.State = new React.State(""); @@ -33,6 +31,5 @@ export default class TaskViewModel { // init constructor(taskModel: TaskModel, storageModel: StorageModel) { this.taskModel = taskModel; - this.storageModel = storageModel; } }