diff --git a/dist/index.js b/dist/index.js index 7540d9f1..48978348 100644 --- a/dist/index.js +++ b/dist/index.js @@ -381,7 +381,9 @@ sendMessage: "Send", clearHistory: "Clear history", encryptionUnavailableTitle: "Encryption is not available", - encryptionUnavailableMessage: "Obtain this app via HTTPS or continue without encryption" + encryptionUnavailableMessage: "Obtain this app via HTTPS or continue without encryption", + copyMessage: "Copy message", + deleteMessage: "Delete message" }; var allTranslations = { en: englishTranslations, @@ -539,6 +541,9 @@ function clearMessageHistory() { messages.clear(); } + function deleteMessage(message) { + messages.remove(message); + } function setChannel() { if (cannotSetChannel.value == true) return; if (currentPrimaryChannel != void 0) { @@ -644,10 +649,22 @@ // src/Views/threadView.tsx var messageConverter = (message) => { - return /* @__PURE__ */ createElement("div", { class: "tile width-100 flex-no" }, /* @__PURE__ */ createElement("div", { class: "flex-column" }, /* @__PURE__ */ createElement("span", { class: "secondary" }, message.sender, "@", message.channel), /* @__PURE__ */ createElement("b", null, message.body), /* @__PURE__ */ createElement("span", { class: "secondary" }, new Date(message.isoDate).toLocaleString()))); + function copyMessage() { + navigator.clipboard.writeText(message.body); + } + function remove() { + deleteMessage(message); + } + return /* @__PURE__ */ createElement("div", { class: "tile width-100 flex-no padding-0" }, /* @__PURE__ */ createElement("div", { class: "flex-column" }, /* @__PURE__ */ createElement("div", { class: "flex-row justify-apart align-center secondary" }, /* @__PURE__ */ createElement("span", { class: "padding-h" }, message.sender, "@", message.channel), /* @__PURE__ */ createElement("span", null, /* @__PURE__ */ createElement("button", { "aria-label": translation.copyMessage, "on:click": copyMessage }, /* @__PURE__ */ createElement("span", { class: "icon" }, "content_copy")), /* @__PURE__ */ createElement("button", { "aria-label": translation.deleteMessage, "on:click": remove }, /* @__PURE__ */ createElement("span", { class: "icon" }, "delete")))), /* @__PURE__ */ createElement("div", { class: "flex-column padding" }, /* @__PURE__ */ createElement("b", null, message.body), /* @__PURE__ */ createElement("span", { class: "secondary" }, new Date(message.isoDate).toLocaleString())))); }; function ThreadView() { - return /* @__PURE__ */ createElement("div", { class: "flex-column gap", "subscribe:children": [messages, messageConverter] }); + return /* @__PURE__ */ createElement( + "div", + { + class: "flex-column gap", + "subscribe:children": [messages, messageConverter] + } + ); } // src/Tabs/messageTab.tsx @@ -799,15 +816,7 @@ // src/Tabs/settingsTab.tsx function SettingsTab() { - return /* @__PURE__ */ createElement("article", { id: "settings-tab", "toggle:connected": isConnected }, /* @__PURE__ */ createElement("header", null, translation.settings), /* @__PURE__ */ createElement("div", null, ConnectionSection(), CommunicationSection(), EncryptionSection(), /* @__PURE__ */ createElement("hr", { class: "mobile-only" }), /* @__PURE__ */ createElement( - "a", - { - href: "#message-tab", - class: "mobile-only width-100 flex-row justify-end control-gap" - }, - translation.messages, - /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward") - ))); + return /* @__PURE__ */ createElement("article", { id: "settings-tab", "toggle:connected": isConnected }, /* @__PURE__ */ createElement("header", null, translation.settings), /* @__PURE__ */ createElement("div", null, ConnectionSection(), CommunicationSection(), EncryptionSection())); } // src/index.tsx diff --git a/dist/styles.css b/dist/styles.css index 453235d0..4020198e 100644 --- a/dist/styles.css +++ b/dist/styles.css @@ -575,6 +575,10 @@ textarea, padding: var(--modal-padding); } +.padding-top { + padding-top: var(--control-padding) !important; +} + article > div { padding-top: calc(var(--header-height) + var(--content-margin)); } @@ -591,6 +595,10 @@ label.tile:has(> span.icon) input { padding-left: 0px; } +.padding-bottom { + padding-bottom: var(--control-padding) !important; +} + article > div { padding-bottom: calc( var(--menu-height-mobile) + var(--control-height) + var(--content-padding) diff --git a/src/Views/threadView.tsx b/src/Views/threadView.tsx index 6bb59970..2a714b7a 100644 --- a/src/Views/threadView.tsx +++ b/src/Views/threadView.tsx @@ -1,21 +1,40 @@ import * as React from "bloatless-react"; -import { - Message, - messages, -} from "../model"; +import { Message, deleteMessage, messages } from "../model"; + +import { translation } from "../translations"; const messageConverter: React.ListItemConverter = (message) => { + function copyMessage() { + navigator.clipboard.writeText(message.body); + } + + function remove() { + deleteMessage(message); + } + return ( -
+
- - {message.sender}@{message.channel} - - {message.body} - - {new Date(message.isoDate).toLocaleString()} - +
+ + {message.sender}@{message.channel} + + + + + +
+
+ {message.body} + + {new Date(message.isoDate).toLocaleString()} + +
); @@ -23,6 +42,9 @@ const messageConverter: React.ListItemConverter = (message) => { export function ThreadView() { return ( -
+
); } diff --git a/src/model.ts b/src/model.ts index 2e36f940..9bb29ffe 100644 --- a/src/model.ts +++ b/src/model.ts @@ -139,10 +139,14 @@ export async function sendMessage(): Promise { messageBody.value = ""; } -export function clearMessageHistory() { +export function clearMessageHistory(): void { messages.clear(); } +export function deleteMessage(message: Message): void { + messages.remove(message); +} + export function setChannel(): void { if (cannotSetChannel.value == true) return; diff --git a/src/translations.ts b/src/translations.ts index e3e8dd47..a8c68469 100644 --- a/src/translations.ts +++ b/src/translations.ts @@ -33,6 +33,8 @@ const englishTranslations = { encryptionUnavailableTitle: "Encryption is not available", encryptionUnavailableMessage: "Obtain this app via HTTPS or continue without encryption", + copyMessage: "Copy message", + deleteMessage: "Delete message", }; const allTranslations: { [key: string]: typeof englishTranslations } = {