From dae32fa6e7e451b21ab835c6ad0844728b0a8743 Mon Sep 17 00:00:00 2001 From: marlon-erler Date: Tue, 9 Jul 2024 15:15:17 +0200 Subject: [PATCH] add chat list section --- dist/index.js | 477 ++++++++++++++++++-------------- dist/styles.css | 5 + src/Model/chatModel.ts | 21 +- src/Model/model.ts | 25 +- src/Tabs/messageTab.tsx | 4 +- src/Tabs/settingsTab.tsx | 6 +- src/Views/chatListSection.tsx | 62 +++++ src/Views/connectionSection.tsx | 2 + src/translations.ts | 9 +- 9 files changed, 389 insertions(+), 222 deletions(-) create mode 100644 src/Views/chatListSection.tsx diff --git a/dist/index.js b/dist/index.js index 6de3455c..4b0748e1 100644 --- a/dist/index.js +++ b/dist/index.js @@ -364,6 +364,7 @@ cannotSetChannel; // init constructor(id = UUID()) { + this.id = id; this.primaryChannelInput = restoreState( storageKeys.primaryChannel(id), "" @@ -380,12 +381,12 @@ this.newSecondaryChannelName = new State(""); this.cannotSendMessage = createProxyState( [ - this.primaryChannelInput, + this.currentChannel, this.composingMessage, this.isSubscribed, isConnected ], - () => this.primaryChannelInput.value == "" || this.composingMessage.value == "" || this.isSubscribed.value == false || isConnected.value == false + () => this.currentChannel.value == "" || this.composingMessage.value == "" || this.isSubscribed.value == false || isConnected.value == false ); this.cannotAddSecondaryChannel = createProxyState( [this.newSecondaryChannelName], @@ -418,7 +419,7 @@ ...this.secondaryChannels.value.values() ].map((channel) => channel); const allChannelNames = [ - this.primaryChannelInput.value, + this.currentChannel.value, ...secondaryChannelNames ]; const encrypted = await encryptString( @@ -463,206 +464,20 @@ } }; var chatIds = restoreListState("chat-ids"); - var chatArray = [...chatIds.value.values()].map((id) => new Chat(id)); - var chats = new ListState(chatArray); - - // node_modules/udn-frontend/index.ts - var UDNFrontend = class { - ws; - // HANDLERS - connectionHandler = () => { - }; - disconnectionHandler = () => { - }; - messageHandler = (data) => { - }; - mailboxHandler = (mailboxId2) => { - }; - mailboxConnectionHandler = (mailboxId2) => { - }; - mailboxDeleteHandler = (mailboxId2) => { - }; - // INIT - set onconnect(handler) { - this.connectionHandler = handler; - } - set ondisconnect(handler) { - this.disconnectionHandler = handler; - } - set onmessage(handler) { - this.messageHandler = handler; - } - set onmailboxcreate(handler) { - this.mailboxHandler = handler; - } - set onmailboxconnect(handler) { - this.mailboxConnectionHandler = handler; - } - set onmailboxdelete(handler) { - this.mailboxDeleteHandler = handler; - } - // UTILITY METHODS - send(messageObject) { - if (this.ws == void 0) return false; - const messageString = JSON.stringify(messageObject); - this.ws.send(messageString); - return true; - } - // PUBLIC METHODS - // connection - connect(address) { - try { - this.disconnect(); - this.ws = new WebSocket(address); - this.ws.addEventListener("open", this.connectionHandler); - this.ws.addEventListener("close", this.disconnectionHandler); - this.ws.addEventListener("message", (message) => { - const dataString = message.data.toString(); - const data = JSON.parse(dataString); - if (data.assignedMailboxId) { - return this.mailboxHandler(data.assignedMailboxId); - } else if (data.connectedMailboxId) { - return this.mailboxConnectionHandler(data.connectedMailboxId); - } else if (data.deletedMailbox) { - return this.mailboxDeleteHandler(data.deletedMailbox); - } else { - this.messageHandler(data); - } - }); - } catch (error) { - console.error(error); - } - } - disconnect() { - this.ws?.close(); - } - // message - sendMessage(channel, body) { - const messageObject = { - messageChannel: channel, - messageBody: body - }; - return this.send(messageObject); - } - // subscription - subscribe(channel) { - const messageObject = { - subscribeChannel: channel - }; - return this.send(messageObject); - } - unsubscribe(channel) { - const messageObject = { - unsubscribeChannel: channel - }; - return this.send(messageObject); - } - // mailbox - requestMailbox() { - const messageObject = { - requestingMailboxSetup: true - }; - return this.send(messageObject); - } - connectMailbox(mailboxId2) { - const messageObject = { - requestedMailbox: mailboxId2 - }; - return this.send(messageObject); - } - deleteMailbox(mailboxId2) { - const messageObject = { - deletingMailbox: mailboxId2 - }; - return this.send(messageObject); - } - }; - - // src/Model/model.ts - var UDN = new UDNFrontend(); - var isConnected = new State(false); - var serverAddressInput = restoreState("socket-address", ""); - var didRequestConnection = restoreState( - "did-request-connection", - false - ); - var currentAddress = restoreState("current-address", ""); - var cannotDisonnect = createProxyState( - [isConnected], - () => isConnected.value == false - ); - var cannotConnect = createProxyState( - [serverAddressInput, currentAddress, isConnected], - () => serverAddressInput.value == "" || currentAddress.value == serverAddressInput.value && isConnected.value == true - ); - var cannotResetAddress = createProxyState( - [serverAddressInput, currentAddress], - () => serverAddressInput.value == currentAddress.value - ); - function connect() { - if (cannotConnect.value == true) return; - currentAddress.value = serverAddressInput.value; - isConnected.value = false; - didRequestConnection.value = true; - UDN.connect(serverAddressInput.value); + var chats = new ListState(); + chatIds.value.forEach((id) => chats.add(new Chat(id))); + function createChatWithName(name) { + const newChat = new Chat(); + newChat.currentChannel.value = name; + chatIds.add(newChat.id); + chats.add(newChat); } - function disconnect() { - didRequestConnection.value = false; - if (cannotDisonnect.value == true) return; - UDN.disconnect(); - } - function resetAddressInput() { - serverAddressInput.value = currentAddress.value; - } - UDN.onconnect = () => { - isConnected.value = true; - }; - UDN.onmessage = (data) => { - chats.value.forEach((chat) => { - chat.onmessage(data); + function removeChat(chat) { + Object.values(storageKeys).forEach((cb) => { + localStorage.removeItem(cb(chat.id)); }); - }; - UDN.ondisconnect = () => { - isConnected.value = false; - }; - var mailboxId = restoreState("mailbox-id", ""); - var isMailboxActive = new State(false); - var cannotDeleteMailbox = createProxyState( - [mailboxId, isMailboxActive], - () => mailboxId.value == "" || isMailboxActive.value == false - ); - var cannotRequestMailbox = createProxyState( - [isConnected, isMailboxActive], - () => isConnected.value == false || isMailboxActive.value == true - ); - function requestMailbox() { - if (cannotRequestMailbox.value == true) return; - UDN.requestMailbox(); - } - function deleteMailbox() { - if (cannotDeleteMailbox.value == true) return; - UDN.deleteMailbox(mailboxId.value); - } - UDN.onmailboxcreate = (id) => { - mailboxId.value = id; - UDN.connectMailbox(id); - }; - UDN.onmailboxconnect = () => { - isMailboxActive.value = true; - }; - UDN.onmailboxdelete = () => { - isMailboxActive.value = false; - mailboxId.value = ""; - }; - var isEncryptionUnavailable = window.crypto.subtle == void 0; - var senderName = restoreState("sender-name", ""); - var selectedChat = new State(void 0); - function closeChat() { - selectedChat.value = void 0; - document.getElementById("settings-tab")?.scrollIntoView(); - } - if (serverAddressInput.value != "" && didRequestConnection.value == true) { - connect(); + chats.remove(chat); + chatIds.remove(chat.id); } // src/translations.ts @@ -673,13 +488,17 @@ // overview overview: "Overview", connection: "Connection", - communication: "Communication", - encryption: "Encryption", + chats: "Chats", serverAddress: "Server Address", serverAddressPlaceholder: "wss://192.168.0.69:3000", connectToServer: "Connect", disconnect: "Disonnect", resetAddress: "Reset address", + newChatPrimaryChannel: "Primary channel", + newChatNamePlaceholder: "my-channel", + addChat: "Add", + removeChat: "Remove chat", + // messages noChatSelected: "No chat selected", primaryChannel: "Primary channel", leaveChannel: "Leave", @@ -857,7 +676,7 @@ function clearMessageHistory() { chat.clearMessages(); } - return /* @__PURE__ */ createElement("article", { id: "message-tab" }, /* @__PURE__ */ createElement("header", { class: "padding-0" }, /* @__PURE__ */ createElement("span", { class: "flex-row align-center" }, /* @__PURE__ */ createElement("button", { "aria-label": translation.back, "on:click": closeChat }, /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_back")), /* @__PURE__ */ createElement("span", { "subscribe:innerText": chat.currentChannel })), /* @__PURE__ */ createElement("span", null, /* @__PURE__ */ createElement( + return /* @__PURE__ */ createElement("article", { id: "message-tab" }, /* @__PURE__ */ createElement("header", { class: "padding-0" }, /* @__PURE__ */ createElement("span", { class: "flex-row align-center" }, /* @__PURE__ */ createElement("button", { "aria-label": translation.back, "on:click": closeChatView }, /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_back")), /* @__PURE__ */ createElement("span", { "subscribe:innerText": chat.currentChannel })), /* @__PURE__ */ createElement("span", null, /* @__PURE__ */ createElement( "button", { "aria-label": translation.clearHistory, @@ -869,9 +688,44 @@ return /* @__PURE__ */ createElement("div", { "children:set": messageTabContent }); } + // src/Views/chatListSection.tsx + var chatConverter = (chat) => { + function remove() { + removeChat(chat); + } + return /* @__PURE__ */ createElement("div", { class: "tile padding-0" }, /* @__PURE__ */ createElement("div", { class: "flex-row width-100 justify-apart align-center" }, /* @__PURE__ */ createElement("span", { class: "padding-h ellipsis", "subscribe:innerText": chat.currentChannel }), /* @__PURE__ */ createElement( + "button", + { + class: "danger", + "aria-label": translation.removeChat, + "on:click": remove + }, + /* @__PURE__ */ createElement("span", { class: "icon" }, "delete") + ))); + }; + function ChatListSection() { + return /* @__PURE__ */ createElement("div", { class: "flex-column" }, /* @__PURE__ */ createElement("h2", null, translation.chats), /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "forum"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translation.newChatPrimaryChannel), /* @__PURE__ */ createElement( + "input", + { + "bind:value": newChatName, + placeholder: translation.newChatNamePlaceholder, + "on:enter": createChat + } + ))), /* @__PURE__ */ createElement("div", { class: "flex-row justify-end" }, /* @__PURE__ */ createElement( + "button", + { + class: "primary width-50", + "toggle:disabled": cannotCreateChat, + "on:click": createChat + }, + translation.addChat, + /* @__PURE__ */ createElement("span", { class: "icon" }, "add") + )), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap", "children:append": [chats, chatConverter] })); + } + // src/Views/connectionSection.tsx function ConnectionSection() { - return /* @__PURE__ */ createElement("div", { class: "flex-column" }, /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "cell_tower"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translation.serverAddress), /* @__PURE__ */ createElement( + return /* @__PURE__ */ createElement("div", { class: "flex-column" }, /* @__PURE__ */ createElement("h2", null, translation.connection), /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "cell_tower"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, translation.serverAddress), /* @__PURE__ */ createElement( "input", { "bind:value": serverAddressInput, @@ -927,10 +781,221 @@ // src/Tabs/settingsTab.tsx function SettingsTab() { - return /* @__PURE__ */ createElement("article", { id: "settings-tab", "toggle:connected": isConnected }, /* @__PURE__ */ createElement("header", null, translation.overview), /* @__PURE__ */ createElement("div", null, ConnectionSection())); + return /* @__PURE__ */ createElement("article", { id: "settings-tab", "toggle:connected": isConnected }, /* @__PURE__ */ createElement("header", null, translation.overview), /* @__PURE__ */ createElement("div", { class: "flex-column large-gap" }, ConnectionSection(), ChatListSection())); } + // node_modules/udn-frontend/index.ts + var UDNFrontend = class { + ws; + // HANDLERS + connectionHandler = () => { + }; + disconnectionHandler = () => { + }; + messageHandler = (data) => { + }; + mailboxHandler = (mailboxId2) => { + }; + mailboxConnectionHandler = (mailboxId2) => { + }; + mailboxDeleteHandler = (mailboxId2) => { + }; + // INIT + set onconnect(handler) { + this.connectionHandler = handler; + } + set ondisconnect(handler) { + this.disconnectionHandler = handler; + } + set onmessage(handler) { + this.messageHandler = handler; + } + set onmailboxcreate(handler) { + this.mailboxHandler = handler; + } + set onmailboxconnect(handler) { + this.mailboxConnectionHandler = handler; + } + set onmailboxdelete(handler) { + this.mailboxDeleteHandler = handler; + } + // UTILITY METHODS + send(messageObject) { + if (this.ws == void 0) return false; + const messageString = JSON.stringify(messageObject); + this.ws.send(messageString); + return true; + } + // PUBLIC METHODS + // connection + connect(address) { + try { + this.disconnect(); + this.ws = new WebSocket(address); + this.ws.addEventListener("open", this.connectionHandler); + this.ws.addEventListener("close", this.disconnectionHandler); + this.ws.addEventListener("message", (message) => { + const dataString = message.data.toString(); + const data = JSON.parse(dataString); + if (data.assignedMailboxId) { + return this.mailboxHandler(data.assignedMailboxId); + } else if (data.connectedMailboxId) { + return this.mailboxConnectionHandler(data.connectedMailboxId); + } else if (data.deletedMailbox) { + return this.mailboxDeleteHandler(data.deletedMailbox); + } else { + this.messageHandler(data); + } + }); + } catch (error) { + console.error(error); + } + } + disconnect() { + this.ws?.close(); + } + // message + sendMessage(channel, body) { + const messageObject = { + messageChannel: channel, + messageBody: body + }; + return this.send(messageObject); + } + // subscription + subscribe(channel) { + const messageObject = { + subscribeChannel: channel + }; + return this.send(messageObject); + } + unsubscribe(channel) { + const messageObject = { + unsubscribeChannel: channel + }; + return this.send(messageObject); + } + // mailbox + requestMailbox() { + const messageObject = { + requestingMailboxSetup: true + }; + return this.send(messageObject); + } + connectMailbox(mailboxId2) { + const messageObject = { + requestedMailbox: mailboxId2 + }; + return this.send(messageObject); + } + deleteMailbox(mailboxId2) { + const messageObject = { + deletingMailbox: mailboxId2 + }; + return this.send(messageObject); + } + }; + // src/index.tsx + var UDN = new UDNFrontend(); + var isConnected = new State(false); + var serverAddressInput = restoreState("socket-address", ""); + var didRequestConnection = restoreState( + "did-request-connection", + false + ); + var currentAddress = restoreState("current-address", ""); + var cannotDisonnect = createProxyState( + [isConnected], + () => isConnected.value == false + ); + var cannotConnect = createProxyState( + [serverAddressInput, currentAddress, isConnected], + () => serverAddressInput.value == "" || currentAddress.value == serverAddressInput.value && isConnected.value == true + ); + var cannotResetAddress = createProxyState( + [serverAddressInput, currentAddress], + () => serverAddressInput.value == currentAddress.value + ); + function connect() { + if (cannotConnect.value == true) return; + currentAddress.value = serverAddressInput.value; + isConnected.value = false; + didRequestConnection.value = true; + UDN.connect(serverAddressInput.value); + } + function disconnect() { + didRequestConnection.value = false; + if (cannotDisonnect.value == true) return; + UDN.disconnect(); + } + function resetAddressInput() { + serverAddressInput.value = currentAddress.value; + } + UDN.onconnect = () => { + isConnected.value = true; + }; + UDN.onmessage = (data) => { + chats.value.forEach((chat) => { + chat.onmessage(data); + }); + }; + UDN.ondisconnect = () => { + isConnected.value = false; + }; + var mailboxId = restoreState("mailbox-id", ""); + var isMailboxActive = new State(false); + var cannotDeleteMailbox = createProxyState( + [mailboxId, isMailboxActive], + () => mailboxId.value == "" || isMailboxActive.value == false + ); + var cannotRequestMailbox = createProxyState( + [isConnected, isMailboxActive], + () => isConnected.value == false || isMailboxActive.value == true + ); + function requestMailbox() { + if (cannotRequestMailbox.value == true) return; + UDN.requestMailbox(); + } + function deleteMailbox() { + if (cannotDeleteMailbox.value == true) return; + UDN.deleteMailbox(mailboxId.value); + } + function updateMailbox() { + deleteMailbox(); + updateMailbox(); + } + UDN.onmailboxcreate = (id) => { + mailboxId.value = id; + UDN.connectMailbox(id); + }; + UDN.onmailboxconnect = () => { + isMailboxActive.value = true; + }; + UDN.onmailboxdelete = () => { + isMailboxActive.value = false; + mailboxId.value = ""; + }; + var isEncryptionUnavailable = window.crypto.subtle == void 0; + var senderName = restoreState("sender-name", ""); + var selectedChat = new State(void 0); + var newChatName = new State(""); + var cannotCreateChat = createProxyState( + [newChatName], + () => newChatName.value == "" + ); + function createChat() { + if (cannotCreateChat.value == true) return; + createChatWithName(newChatName.value); + newChatName.value = ""; + } + function closeChatView() { + selectedChat.value = void 0; + document.getElementById("settings-tab")?.scrollIntoView(); + } + if (serverAddressInput.value != "" && didRequestConnection.value == true) { + connect(); + } document.querySelector("main").append(SettingsTab(), MessageTab()); document.querySelector("main").classList.add("split"); })(); diff --git a/dist/styles.css b/dist/styles.css index ec3eafe2..c48e0d43 100644 --- a/dist/styles.css +++ b/dist/styles.css @@ -214,6 +214,7 @@ SIZES --gap-between-tiles: 4px; --gap-in-tab-links: 1rem; --gap-in-controls: 1.2rem; + --large-gap: 2rem; /* margin */ --label-top-padding: 0.25rem; @@ -448,6 +449,10 @@ label.inline, gap: var(--gap-between-tiles) !important; } +.large-gap { + gap: var(--large-gap) !important; +} + header, button { justify-content: space-between; diff --git a/src/Model/chatModel.ts b/src/Model/chatModel.ts index 8a2e2f37..eccde818 100644 --- a/src/Model/chatModel.ts +++ b/src/Model/chatModel.ts @@ -1,6 +1,6 @@ import * as React from "bloatless-react"; -import { UDN, isConnected, senderName } from "./model"; +import { UDN, isConnected, senderName } from "../Model/model"; import { decryptString, encryptString } from "../cryptUtility"; import { Message } from "udn-frontend"; @@ -37,6 +37,9 @@ export class Chat { // init constructor(id: string = React.UUID()) { + this.id = id; + + // channels this.primaryChannelInput = React.restoreState( storageKeys.primaryChannel(id), "" @@ -45,6 +48,7 @@ export class Chat { storageKeys.secondaryChannels(id) ); + // messaging this.encryptionKey = React.restoreState(storageKeys.encyptionKey(id), ""); this.messages = React.restoreListState(storageKeys.messages(id)); @@ -54,15 +58,16 @@ export class Chat { ); this.newSecondaryChannelName = new React.State(""); + // guards this.cannotSendMessage = React.createProxyState( [ - this.primaryChannelInput, + this.currentChannel, this.composingMessage, this.isSubscribed, isConnected, ], () => - this.primaryChannelInput.value == "" || + this.currentChannel.value == "" || this.composingMessage.value == "" || this.isSubscribed.value == false || isConnected.value == false @@ -108,7 +113,7 @@ export class Chat { ...this.secondaryChannels.value.values(), ].map((channel) => channel); const allChannelNames: string[] = [ - this.primaryChannelInput.value, + this.currentChannel.value, ...secondaryChannelNames, ]; @@ -171,14 +176,16 @@ export class Chat { // INIT const chatIds = React.restoreListState("chat-ids"); -const chatArray = [...chatIds.value.values()].map((id) => new Chat(id)); -export const chats = new React.ListState(chatArray); +export const chats = new React.ListState(); + +chatIds.value.forEach((id) => chats.add(new Chat(id))); // METHODS export function createChatWithName(name: string): void { const newChat = new Chat(); - newChat.primaryChannelInput.value = name; + newChat.currentChannel.value = name; chatIds.add(newChat.id); + chats.add(newChat); } export function removeChat(chat: Chat): void { diff --git a/src/Model/model.ts b/src/Model/model.ts index 322c813c..48c99d79 100644 --- a/src/Model/model.ts +++ b/src/Model/model.ts @@ -1,13 +1,12 @@ import * as React from "bloatless-react"; -import { Chat, chats } from "./chatModel"; +import { Chat, chats, createChatWithName } from "./chatModel"; import UDNFrontend from "udn-frontend"; export const UDN = new UDNFrontend(); // CONNECTION -// state export const isConnected = new React.State(false); export const serverAddressInput = React.restoreState("socket-address", ""); @@ -38,7 +37,7 @@ export const cannotResetAddress = React.createProxyState( // methods export function connect(): void { if (cannotConnect.value == true) return; - + currentAddress.value = serverAddressInput.value; isConnected.value = false; @@ -95,6 +94,11 @@ export function deleteMailbox(): void { UDN.deleteMailbox(mailboxId.value); } +export function updateMailbox(): void { + deleteMailbox(); + updateMailbox(); +} + UDN.onmailboxcreate = (id) => { mailboxId.value = id; UDN.connectMailbox(id); @@ -114,8 +118,21 @@ export const isEncryptionUnavailable = window.crypto.subtle == undefined; export const senderName = React.restoreState("sender-name", ""); export const selectedChat = new React.State(undefined); +export const newChatName = new React.State(""); -export function closeChat() { +export const cannotCreateChat = React.createProxyState( + [newChatName], + () => newChatName.value == "" +); + +export function createChat() { + if (cannotCreateChat.value == true) return; + + createChatWithName(newChatName.value); + newChatName.value = ""; +} + +export function closeChatView() { selectedChat.value = undefined; document.getElementById("settings-tab")?.scrollIntoView(); } diff --git a/src/Tabs/messageTab.tsx b/src/Tabs/messageTab.tsx index 6257da82..66aef052 100644 --- a/src/Tabs/messageTab.tsx +++ b/src/Tabs/messageTab.tsx @@ -1,6 +1,6 @@ import * as React from "bloatless-react"; -import { closeChat, selectedChat } from "../Model/model"; +import { closeChatView, selectedChat } from "../Model/model"; import { MessageComposer } from "../Views/messageComposer"; import { ThreadView } from "../Views/threadView"; @@ -25,7 +25,7 @@ export function MessageTab() {
- diff --git a/src/Tabs/settingsTab.tsx b/src/Tabs/settingsTab.tsx index e2624321..96d82831 100644 --- a/src/Tabs/settingsTab.tsx +++ b/src/Tabs/settingsTab.tsx @@ -1,5 +1,6 @@ import * as React from "bloatless-react"; +import { ChatListSection } from "../Views/chatListSection"; import { ConnectionSection } from "../Views/connectionSection"; import { isConnected } from "../Model/model"; import { translation } from "../translations"; @@ -8,7 +9,10 @@ export function SettingsTab() { return (
{translation.overview}
-
{ConnectionSection()}
+
+ {ConnectionSection()} + {ChatListSection()} +
); } diff --git a/src/Views/chatListSection.tsx b/src/Views/chatListSection.tsx new file mode 100644 index 00000000..ca804498 --- /dev/null +++ b/src/Views/chatListSection.tsx @@ -0,0 +1,62 @@ +import * as React from "bloatless-react"; + +import { Chat, chats, removeChat } from "../Model/chatModel"; +import { cannotCreateChat, createChat, newChatName } from "../Model/model"; + +import { translation } from "../translations"; + +const chatConverter: React.ListItemConverter = (chat) => { + function remove() { + removeChat(chat); + } + + return ( +
+
+ + + +
+
+ ); +}; + +export function ChatListSection() { + return ( +
+

{translation.chats}

+ + +
+ +
+ +
+ +
+
+ ); +} diff --git a/src/Views/connectionSection.tsx b/src/Views/connectionSection.tsx index f6861edf..e39da79e 100644 --- a/src/Views/connectionSection.tsx +++ b/src/Views/connectionSection.tsx @@ -19,6 +19,8 @@ import { translation } from "../translations"; export function ConnectionSection() { return (
+

{translation.connection}

+