feat(chat): support pasting images directly into the chat box
This commit is contained in:
@@ -437,6 +437,58 @@ export function ChatArea() {
|
|||||||
return () => clearInterval(t);
|
return () => clearInterval(t);
|
||||||
}, [slowmodeRemaining]);
|
}, [slowmodeRemaining]);
|
||||||
|
|
||||||
|
const handlePaste = async (e: React.ClipboardEvent<HTMLInputElement>) => {
|
||||||
|
const items = e.clipboardData.items;
|
||||||
|
let imageFile: File | null = null;
|
||||||
|
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].type.startsWith('image/')) {
|
||||||
|
imageFile = items[i].getAsFile();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageFile) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', imageFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/v1/upload', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData,
|
||||||
|
credentials: 'include'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) throw new Error('Upload failed');
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
const imageUrl = data.url;
|
||||||
|
|
||||||
|
// Insert into input
|
||||||
|
const imgMarkdown = ``;
|
||||||
|
|
||||||
|
const inputEl = inputRef.current;
|
||||||
|
if (inputEl) {
|
||||||
|
const start = inputEl.selectionStart || 0;
|
||||||
|
const end = inputEl.selectionEnd || 0;
|
||||||
|
const newValue = input.slice(0, start) + imgMarkdown + input.slice(end);
|
||||||
|
setInput(newValue);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
inputEl.focus();
|
||||||
|
inputEl.setSelectionRange(start + imgMarkdown.length, start + imgMarkdown.length);
|
||||||
|
}, 0);
|
||||||
|
} else {
|
||||||
|
setInput(prev => prev + (prev.length > 0 && !prev.endsWith(' ') ? ' ' : '') + imgMarkdown);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to upload image:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
const cursor = e.target.selectionStart ?? value.length;
|
const cursor = e.target.selectionStart ?? value.length;
|
||||||
@@ -851,6 +903,7 @@ export function ChatArea() {
|
|||||||
type="text"
|
type="text"
|
||||||
value={input}
|
value={input}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
|
onPaste={handlePaste}
|
||||||
placeholder="type a message..."
|
placeholder="type a message..."
|
||||||
className="terminal-input w-full"
|
className="terminal-input w-full"
|
||||||
disabled={!activeChannelId || slowmodeRemaining > 0}
|
disabled={!activeChannelId || slowmodeRemaining > 0}
|
||||||
|
|||||||
Reference in New Issue
Block a user