From f7fda2d2c951a07bccc927a333b7feaa527556c2 Mon Sep 17 00:00:00 2001 From: BordedDev <> Date: Tue, 6 May 2025 23:14:52 +0200 Subject: [PATCH] Added paste support Added file drop support --- src/snek/templates/web.html | 73 +++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 15 deletions(-) diff --git a/src/snek/templates/web.html b/src/snek/templates/web.html index fa5e03e..50e30e5 100644 --- a/src/snek/templates/web.html +++ b/src/snek/templates/web.html @@ -30,13 +30,8 @@ function getInputField(){ return document.querySelector("textarea") } - - function initInputField(textBox) { - textBox.addEventListener('change', (e) => { - e.preventDefault(); - this.dispatchEvent(new CustomEvent('change', { detail: e.target.value, bubbles: true })); - }); + function initInputField(textBox) { textBox.addEventListener('keydown', (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); @@ -47,11 +42,59 @@ } } }); + + textBox.addEventListener("paste", async (e) => { + try { + const clipboardItems = await navigator.clipboard.read(); + + // DataTransfer needs to be used to modify the files list of the input + const dt = new DataTransfer(); + + for (const clipboardItem of clipboardItems) { + const fileTypes = clipboardItem.types.filter(type => !type.startsWith('text/')) + for (const fileType of fileTypes) { + + const blob = await clipboardItem.getType(fileType); + // Do something with the image blob. + dt.items.add(new File([blob], "image.png", { type: fileType })); + } + } + + if (dt.items.length > 0) { + const uploadButton = document.querySelector("upload-button"); + const input = uploadButton.shadowRoot.querySelector('.file-input') + input.files = dt.files; + + await uploadButton.uploadFiles(); + } + } catch (error) { + console.error("Failed to read clipboard contents: ", error); + } + }); + + const chatInput = document.querySelector(".chat-area") + chatInput.addEventListener("drop", async (e) => { + e.preventDefault(); + + const dt = e.dataTransfer; + if (dt.items.length > 0) { + const uploadButton = document.querySelector("upload-button"); + const input = uploadButton.shadowRoot.querySelector('.file-input') + input.files = dt.files; + + await uploadButton.uploadFiles(); + } + }) + chatInput.addEventListener("dragover", async (e) => { + e.preventDefault(); + e.dataTransfer.dropEffect = "link"; + }) + textBox.focus(); } function replyMessage(message) { - const field = getInputField() + const field = getInputField() field.value = "```markdown\n> " + (message || '') + "\n```\n"; field.focus(); } @@ -63,7 +106,7 @@ const text = messageDiv.querySelector(".text").innerText; const time = document.createElement("span"); time.innerText = app.timeDescription(container.dataset.created_at); - + container.replaceChildren(time); const reply = document.createElement("a"); reply.innerText = " reply"; @@ -85,7 +128,7 @@ rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); } - + const messagesContainer = document.querySelector(".chat-messages"); function isScrolledPastHalf() { @@ -108,9 +151,9 @@ if (!isScrolledPastHalf()) { return; } - + isLoadingExtra = true; - + const messages = await app.rpc.getMessages(channelUid, 0, firstMessage.dataset.created_at); messages.forEach((message) => { @@ -140,7 +183,7 @@ } }); lastMessage = messagesContainer.querySelector(".message:last-child"); - if (doScrollDown) { + if (doScrollDown) { lastMessage?.scrollIntoView({ block: "end", inline: "nearest" }); const inputBox = document.querySelector(".chat-input"); inputBox.scrollIntoView({ block: "end", inline: "nearest" }); @@ -161,14 +204,14 @@ const mentionText = '@{{ user.username.value }}'; return mentions.length > 0 && mentions.indexOf(mentionText) == -1; } - + app.addEventListener("channel-message", (data) => { if (data.channel_uid !== channelUid) { if(!isMentionForSomeoneElse(data.message)){ channelSidebar.notify(data); app.playSound("messageOtherChannel"); } - + return; } if (data.username !== "{{ user.username.value }}") { @@ -178,7 +221,7 @@ app.playSound("message"); } } - + const messagesContainer = document.querySelector(".chat-messages"); lastMessage = messagesContainer.querySelector(".message:last-child"); const doScrollDownBecauseLastMessageIsVisible = !lastMessage || isElementVisible(lastMessage);