Compare commits
No commits in common. "main" and "main" have entirely different histories.
@ -37,9 +37,10 @@
|
|||||||
{% include "dialog_help.html" %}
|
{% include "dialog_help.html" %}
|
||||||
{% include "dialog_online.html" %}
|
{% include "dialog_online.html" %}
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import {app} from "/app.js";
|
import { app } from "/app.js";
|
||||||
|
import { Schedule } from "/schedule.js";
|
||||||
|
|
||||||
// --- Cache selectors ---
|
// --- Cache selectors ---
|
||||||
const chatInputField = document.querySelector("chat-input");
|
const chatInputField = document.querySelector("chat-input");
|
||||||
const messagesContainer = document.querySelector(".chat-messages");
|
const messagesContainer = document.querySelector(".chat-messages");
|
||||||
const chatArea = document.querySelector(".chat-area");
|
const chatArea = document.querySelector(".chat-area");
|
||||||
@ -98,8 +99,50 @@ setInterval(() => requestIdleCallback(updateTimes), 30000);
|
|||||||
|
|
||||||
// --- Paste & drag/drop uploads ---
|
// --- Paste & drag/drop uploads ---
|
||||||
const textBox = chatInputField.textarea;
|
const textBox = chatInputField.textarea;
|
||||||
|
textBox.addEventListener("paste", async (e) => {
|
||||||
|
try {
|
||||||
|
e.preventDefault();
|
||||||
|
const uploadButton = chatInputField.fileUploadGrid;
|
||||||
|
|
||||||
function uploadDataTransfer(dt) {
|
const clipboardItems = await navigator.clipboard.read()
|
||||||
|
|
||||||
|
for (const item of clipboardItems) {
|
||||||
|
if (item.types.every(v => v === "text/plain")) {
|
||||||
|
const text = await (await item.getType("text/plain")).text();
|
||||||
|
chatInputField.value += text;
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.types.every(t => t.startsWith('text/'))) {
|
||||||
|
console.log("All types are text:", item.types);
|
||||||
|
const codeType = item.types.find(t => !t.startsWith('text/plain') && !t.startsWith('text/html'));
|
||||||
|
let code = await(await item.getType(codeType ?? 'text/plain')).text();
|
||||||
|
|
||||||
|
const minIndentDepth = code.split('\n').reduce((acc, line) => {
|
||||||
|
if (!line.trim()) return acc;
|
||||||
|
const match = line.match(/^(\s*)/);
|
||||||
|
return match ? Math.min(acc, match[1].length) : acc;
|
||||||
|
}, 9000)
|
||||||
|
|
||||||
|
code = code.split('\n').map(line => line.slice(minIndentDepth)).join('\n')
|
||||||
|
|
||||||
|
chatInputField.value += `\`\`\`${codeType?.split('/')?.[1] ?? ''}\n${code}\n\`\`\`\n`;
|
||||||
|
} else {
|
||||||
|
for (const type of item.types.filter(t => !t.startsWith('text/'))) {
|
||||||
|
const blob = await item.getType(type);
|
||||||
|
const name = type.replace('/', '.')
|
||||||
|
uploadButton.uploadsStarted++
|
||||||
|
uploadButton.createTile(new File([blob], name, {type}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to read clipboard contents: ", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
chatArea.addEventListener("drop", async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const dt = e.dataTransfer;
|
||||||
if (dt.items.length > 0) {
|
if (dt.items.length > 0) {
|
||||||
const uploadButton = chatInputField.fileUploadGrid;
|
const uploadButton = chatInputField.fileUploadGrid;
|
||||||
|
|
||||||
@ -109,58 +152,10 @@ function uploadDataTransfer(dt) {
|
|||||||
if (file) {
|
if (file) {
|
||||||
uploadButton.uploadsStarted++
|
uploadButton.uploadsStarted++
|
||||||
uploadButton.createTile(file)
|
uploadButton.createTile(file)
|
||||||
} else {
|
|
||||||
console.error("Failed to get file from DataTransferItem");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
textBox.addEventListener("paste", async (e) => {
|
|
||||||
try {
|
|
||||||
console.log("Pasted data:", e.clipboardData);
|
|
||||||
if (e.clipboardData.types.every(v => v.startsWith("text/"))) {
|
|
||||||
const codeType = e.clipboardData.types.find(t => !t.startsWith('text/plain') && !t.startsWith('text/html') && !t.startsWith('text/rtf'));
|
|
||||||
const probablyCode = codeType ||e.clipboardData.types.some(t => !t.startsWith('text/plain'));
|
|
||||||
for (const item of e.clipboardData.items) {
|
|
||||||
if (item.kind === "string" && item.type === "text/plain") {
|
|
||||||
e.preventDefault();
|
|
||||||
item.getAsString(text => {
|
|
||||||
const value = chatInputField.value;
|
|
||||||
if (probablyCode) {
|
|
||||||
let code = text;
|
|
||||||
const minIndentDepth = code.split('\n').reduce((acc, line) => {
|
|
||||||
if (!line.trim()) return acc;
|
|
||||||
const match = line.match(/^(\s*)/);
|
|
||||||
return match ? Math.min(acc, match[1].length) : acc;
|
|
||||||
}, 9000);
|
|
||||||
code = code.split('\n').map(line => line.slice(minIndentDepth)).join('\n')
|
|
||||||
text = `\`\`\`${codeType?.split('/')?.[1] ?? ''}\n${code}\n\`\`\`\n`;
|
|
||||||
}
|
|
||||||
const area = chatInputField.textarea
|
|
||||||
if(area){
|
|
||||||
const start = area.selectionStart
|
|
||||||
|
|
||||||
if ("\n" !== value[start - 1]) {
|
|
||||||
text = `\n${text}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.execCommand('insertText', false, text);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
uploadDataTransfer(e.clipboardData);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to read clipboard contents: ", error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
chatArea.addEventListener("drop", async (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
uploadDataTransfer(e.dataTransfer);
|
|
||||||
});
|
});
|
||||||
chatArea.addEventListener("dragover", e => {
|
chatArea.addEventListener("dragover", e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user