diff --git a/app.vue b/app.vue index 294c9f9..4c0484a 100644 --- a/app.vue +++ b/app.vue @@ -36,21 +36,32 @@ function contextMenuHandler(e: MouseEvent) { //]); } +let currentTheme = "dark" // default theme +const savedTheme = localStorage.getItem("selectedTheme"); +if (savedTheme) { + currentTheme = savedTheme; +} + +const baseURL = useRuntimeConfig().app.baseURL; + +useHead({ + link: [ + { + rel: "stylesheet", + href: `${baseURL}themes/${currentTheme}.css` + } + ] +}) \ No newline at end of file diff --git a/components/Channel.vue b/components/Channel.vue index 1828641..98f210e 100644 --- a/components/Channel.vue +++ b/components/Channel.vue @@ -23,19 +23,19 @@ const isCurrentChannel = props.uuid == props.currentUuid; .channel-list-link { text-decoration: none; color: inherit; - padding-left: .5dvw; - padding-right: .5dvw; + padding-left: .25em; + padding-right: .25em; } .channel-list-link-container { text-align: left; display: flex; - height: 4dvh; + height: 1.5em; white-space: nowrap; align-items: center; } .current-channel { - background-color: rgb(70, 70, 70); + background-color: var(--sidebar-highlighted-background-color); } \ No newline at end of file diff --git a/components/CropPopup.vue b/components/CropPopup.vue new file mode 100644 index 0000000..12c3a0b --- /dev/null +++ b/components/CropPopup.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/components/MemberEntry.vue b/components/MemberEntry.vue new file mode 100644 index 0000000..ed4cd48 --- /dev/null +++ b/components/MemberEntry.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/components/Message.vue b/components/Message.vue index 9558ce4..d3d4086 100644 --- a/components/Message.vue +++ b/components/Message.vue @@ -10,6 +10,8 @@ {{ author?.display_name || author?.username }} + Yesterday at + {{ date.toLocaleDateString(undefined) }}, {{ date.toLocaleTimeString(undefined, { timeStyle: "short" }) }} @@ -40,6 +42,7 @@ const messageElement = ref(); const dateHidden = ref(true); const date = new Date(props.timestamp); +const currentDate: Date = new Date() console.log("message:", props.text); console.log("author:", props.author); @@ -48,7 +51,16 @@ const sanitized = ref(); onMounted(async () => { const parsed = await parse(props.text, { gfm: true }); - sanitized.value = DOMPurify.sanitize(parsed, { ALLOWED_TAGS: ["strong", "em", "br", "blockquote", "code", "ul", "ol", "li", "a", "h1", "h2", "h3", "h4", "h5", "h6"] }); + sanitized.value = DOMPurify.sanitize(parsed, { + ALLOWED_TAGS: [ + "strong", "em", "br", "blockquote", + "code", "ul", "ol", "li", "a", "h1", + "h2", "h3", "h4", "h5", "h6" + ], + ALLOW_DATA_ATTR: false, + ALLOW_SELF_CLOSE_IN_ATTR: false, + ALLOWED_ATTR: [] + }); console.log("adding listeners") await nextTick(); if (messageElement.value?.classList.contains("grouped-message")) { @@ -75,6 +87,18 @@ console.log("me:", props.me); if (props.author?.uuid == props.me.uuid) { menuItems.push({ name: "Edit", callback: () => { if (messageElement.value) editMessage(messageElement.value, props) } }); } + +function getDayDifference(date1: Date, date2: Date) { + const midnight1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()); + const midnight2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); + + const timeDifference = midnight2.getTime() - midnight1.getTime(); + + const dayDifference = timeDifference / (1000 * 60 * 60 * 24); + + return Math.round(dayDifference); +} + diff --git a/components/MessageArea.vue b/components/MessageArea.vue index 38db13c..832802b 100644 --- a/components/MessageArea.vue +++ b/components/MessageArea.vue @@ -9,11 +9,28 @@
- - +
+ + + +
+ +
+
+
+
+ +
+ + + + +
@@ -108,11 +125,38 @@ function pushMessage(message: MessageResponse) { messages.value.push(message); } +function handleTextboxKeyDown(event: KeyboardEvent) { + if (event.key === "Enter" && event.shiftKey && messageTextboxInput.value) { + // this enters a newline, due to not preventing default + } else if (event.key === "Enter") { + event.preventDefault() + sendMessage(event) + } + + adjustTextboxHeight() +} + +function handleTextboxInput() { + if (messageTextboxInput.value) { + messageInput.value = messageTextboxInput.value.innerText; + } + + adjustTextboxHeight() +} + +// this technically uses pixel units, but it's still set using dynamic units +function adjustTextboxHeight() { + if (messageTextboxInput.value && messageTextboxDisplay.value) { + messageTextboxInput.value.style.height = "auto" + messageTextboxInput.value.style.height = `${messageTextboxInput.value.scrollHeight}px` + } +} + const messages = ref([]); - -const messageInput = ref(); - +const messageInput = ref(""); const messagesElement = ref(); +const messageTextboxInput = ref(); +const messageTextboxDisplay = ref(); if (messagesRes) messages.value = messagesRes; @@ -160,12 +204,21 @@ if (accessToken && apiBase) { function sendMessage(e: Event) { e.preventDefault(); - const text = messageInput.value; - console.log("text:", text); - if (text) { - ws.send(text); - messageInput.value = ""; - console.log("MESSAGE SENT!!!"); + if (messageInput.value && messageInput.value.trim() !== "") { + const message = { + message: messageInput.value.trim().replace(/\n/g, "
") // trim, and replace \n with
+ } + + console.log("message:", message); + ws.send(JSON.stringify(message)); + + // reset input field + messageInput.value = "" + if (messageTextboxInput.value) { + messageTextboxInput.value.innerText = "" + } + + adjustTextboxHeight() } } @@ -241,38 +294,63 @@ router.beforeEach((to, from, next) => { \ No newline at end of file diff --git a/components/Settings/AppSettings/Appearance.vue b/components/Settings/AppSettings/Appearance.vue index 135c0a1..3adfda6 100644 --- a/components/Settings/AppSettings/Appearance.vue +++ b/components/Settings/AppSettings/Appearance.vue @@ -1,14 +1,100 @@ \ No newline at end of file +.theme-preview-container { + margin: .5em; + width: 5em; + height: 5em; +} + +.theme-preview { + width: 5em; + height: 5em; + border-radius: 100%; + border: .1em solid var(--primary-color); + + display: inline-block; + text-align: center; + align-content: center; + cursor: pointer; +} + +.theme-title { + font-size: .8em; + line-height: 5em; /* same height as the parent to centre it vertically */ +} + diff --git a/components/Settings/UserSettings/Account.vue b/components/Settings/UserSettings/Account.vue index 0fe5013..b2ac87a 100644 --- a/components/Settings/UserSettings/Account.vue +++ b/components/Settings/UserSettings/Account.vue @@ -1,33 +1,16 @@