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);