From 282454140f1a02653fe3a674c7e3771def0ad242 Mon Sep 17 00:00:00 2001 From: Adam French Date: Mon, 6 Apr 2026 22:55:46 +0100 Subject: [PATCH] Remove max height from image in chat and change breakpoint for mobile --- vue/src/components/util/Chat.vue | 268 +++++++++++++++++-------------- vue/src/views/home/Home.vue | 2 +- 2 files changed, 148 insertions(+), 122 deletions(-) diff --git a/vue/src/components/util/Chat.vue b/vue/src/components/util/Chat.vue index de4b33a..3a2f618 100644 --- a/vue/src/components/util/Chat.vue +++ b/vue/src/components/util/Chat.vue @@ -19,177 +19,203 @@ const SCROLL_THRESHOLD = 100; let resizeObserver = null; function scrollToBottom() { - if (messagesContainer.value) { - messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight; - } + if (messagesContainer.value) { + messagesContainer.value.scrollTop = + messagesContainer.value.scrollHeight; + } } function scrollToBottomIfNear() { - if (isNearBottom.value) { - scrollToBottom(); - } + if (isNearBottom.value) { + scrollToBottom(); + } } function onScroll() { - if (!messagesContainer.value) return; - const { scrollHeight, scrollTop, clientHeight } = messagesContainer.value; - isNearBottom.value = scrollHeight - scrollTop - clientHeight < SCROLL_THRESHOLD; + if (!messagesContainer.value) return; + const { scrollHeight, scrollTop, clientHeight } = messagesContainer.value; + isNearBottom.value = + scrollHeight - scrollTop - clientHeight < SCROLL_THRESHOLD; } function goToBottom() { - isNearBottom.value = true; - scrollToBottom(); + isNearBottom.value = true; + scrollToBottom(); } watch( - () => messages.value.length, - () => { - nextTick(scrollToBottomIfNear); - }, + () => messages.value.length, + () => { + nextTick(scrollToBottomIfNear); + }, ); function sendMessage() { - const text = messageInput.value.trim(); - if (!text) return; - isNearBottom.value = true; - messagesStore.sendMessage(text); - messageInput.value = ""; + const text = messageInput.value.trim(); + if (!text) return; + isNearBottom.value = true; + messagesStore.sendMessage(text); + messageInput.value = ""; } async function onFileSelected(e) { - const file = e.target.files[0]; - if (!file) return; - isNearBottom.value = true; - await messagesStore.uploadAndSendFile(file); - fileInput.value.value = ""; + const file = e.target.files[0]; + if (!file) return; + isNearBottom.value = true; + await messagesStore.uploadAndSendFile(file); + fileInput.value.value = ""; } function isImageUrl(url) { - return /\.(jpg|jpeg|png|gif|webp)$/i.test(url); + return /\.(jpg|jpeg|png|gif|webp)$/i.test(url); } function isVideoUrl(url) { - return /\.(mp4|webm|ogg|mov)$/i.test(url); + return /\.(mp4|webm|ogg|mov)$/i.test(url); } function isSafeFileUrl(url) { - return typeof url === "string" && url.startsWith("/uploads/"); + return typeof url === "string" && url.startsWith("/uploads/"); } const urlRegex = /(https?:\/\/[^\s<]+)/g; function parseMessageParts(text) { - const parts = []; - let lastIndex = 0; - let match; - while ((match = urlRegex.exec(text)) !== null) { - if (match.index > lastIndex) { - parts.push({ - type: "text", - value: text.slice(lastIndex, match.index), - }); + const parts = []; + let lastIndex = 0; + let match; + while ((match = urlRegex.exec(text)) !== null) { + if (match.index > lastIndex) { + parts.push({ + type: "text", + value: text.slice(lastIndex, match.index), + }); + } + parts.push({ type: "link", value: match[1] }); + lastIndex = urlRegex.lastIndex; } - parts.push({ type: "link", value: match[1] }); - lastIndex = urlRegex.lastIndex; - } - if (lastIndex < text.length) { - parts.push({ type: "text", value: text.slice(lastIndex) }); - } - return parts; + if (lastIndex < text.length) { + parts.push({ type: "text", value: text.slice(lastIndex) }); + } + return parts; } onMounted(() => { - messagesStore.connect(); + messagesStore.connect(); - if (messagesContainer.value) { - messagesContainer.value.addEventListener("scroll", onScroll, { passive: true }); - } + if (messagesContainer.value) { + messagesContainer.value.addEventListener("scroll", onScroll, { + passive: true, + }); + } - if (messagesInner.value) { - resizeObserver = new ResizeObserver(scrollToBottomIfNear); - resizeObserver.observe(messagesInner.value); - } + if (messagesInner.value) { + resizeObserver = new ResizeObserver(scrollToBottomIfNear); + resizeObserver.observe(messagesInner.value); + } - scrollToBottom(); + scrollToBottom(); }); onUnmounted(() => { - messagesStore.disconnect(); + messagesStore.disconnect(); - if (messagesContainer.value) { - messagesContainer.value.removeEventListener("scroll", onScroll); - } + if (messagesContainer.value) { + messagesContainer.value.removeEventListener("scroll", onScroll); + } - if (resizeObserver) { - resizeObserver.disconnect(); - resizeObserver = null; - } + if (resizeObserver) { + resizeObserver.disconnect(); + resizeObserver = null; + } });