Files
2026-04-30 10:45:05 +02:00

127 lines
4.6 KiB
JavaScript

import { state } from './state.js';
const el = id => document.getElementById(id);
// ─── Upload dispatch ──────────────────────────────────────────────────────────
export async function uploadFile(file) {
const s = state.settings;
const backend = s.uploadBackend || 'none';
if (backend === 'none') {
showUploadError('No upload backend configured. Open ⚙ Settings to set one up.');
return;
}
setUploadState('uploading');
try {
let url;
if (backend === 'filehost') url = await uploadToFilehost(file, s.filehostUrl);
else if (backend === 'imgur') url = await uploadToImgur(file, s.imgurClientId);
setUploadState('ok');
setTimeout(() => setUploadState('idle'), 2000);
const input = el('chat-input');
const pos = input.selectionStart || input.value.length;
const sep = input.value.length > 0 && !input.value.endsWith(' ') ? ' ' : '';
input.value = input.value.slice(0, pos) + sep + url + input.value.slice(pos);
input.focus();
input.selectionStart = input.selectionEnd = pos + sep.length + url.length;
} catch (err) {
setUploadState('err');
setTimeout(() => setUploadState('idle'), 3000);
showUploadError(`Upload failed: ${err.message}`);
}
}
async function uploadToFilehost(file, baseUrl) {
if (!baseUrl) throw new Error('Filehost URL not configured in Settings.');
const url = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/';
const form = new FormData();
form.append('file', file, file.name);
const res = await fetch(url, { method: 'POST', body: form });
if (!res.ok) throw new Error(`Server returned ${res.status}`);
const text = (await res.text()).trim();
if (!text.startsWith('http')) throw new Error(`Unexpected response: ${text}`);
return text;
}
async function uploadToImgur(file, clientId) {
if (!clientId) throw new Error('Imgur Client ID not configured in Settings.');
const form = new FormData();
form.append('image', file);
const res = await fetch('https://api.imgur.com/3/image', {
method: 'POST',
headers: { Authorization: `Client-ID ${clientId}` },
body: form,
});
const json = await res.json();
if (!json.success) throw new Error(json.data?.error || 'Imgur upload failed');
return json.data.link;
}
function setUploadState(s) {
const btn = el('upload-btn');
btn.classList.remove('uploading', 'upload-ok', 'upload-err');
if (s === 'uploading') { btn.classList.add('uploading'); btn.textContent = '⏳'; }
else if (s === 'ok') { btn.classList.add('upload-ok'); btn.textContent = '✓'; }
else if (s === 'err') { btn.classList.add('upload-err'); btn.textContent = '✗'; }
else { btn.textContent = '📎'; }
}
function showUploadError(msg) {
const box = el('messages');
if (!box) return;
const row = document.createElement('div');
row.className = 'msg-row msg-system';
row.style.color = 'var(--status-disc)';
row.innerHTML =
`<span class="msg-time"></span>` +
`<span class="msg-prefix">upload</span>` +
`<span class="msg-sep"></span>` +
`<span class="msg-text">${msg}</span>`;
box.appendChild(row);
if (state.scroll.pinned) box.scrollTop = box.scrollHeight;
}
// ─── Drag & drop and clipboard paste ─────────────────────────────────────────
export function initDragDrop() {
let dragCounter = 0;
window.addEventListener('dragenter', e => {
if (!e.dataTransfer.types.includes('Files')) return;
dragCounter++;
el('drag-overlay').style.display = 'flex';
});
window.addEventListener('dragleave', () => {
dragCounter--;
if (dragCounter <= 0) {
dragCounter = 0;
el('drag-overlay').style.display = 'none';
}
});
window.addEventListener('dragover', e => {
if (!e.dataTransfer.types.includes('Files')) return;
e.preventDefault();
});
window.addEventListener('drop', e => {
e.preventDefault();
dragCounter = 0;
el('drag-overlay').style.display = 'none';
if (!state.connected) return;
const files = [...e.dataTransfer.files];
if (files.length) uploadFile(files[0]);
});
// Paste image from clipboard
el('chat-input').addEventListener('paste', e => {
const items = [...(e.clipboardData?.items || [])];
const imageItem = items.find(i => i.kind === 'file' && i.type.startsWith('image/'));
if (!imageItem) return;
e.preventDefault();
const file = imageItem.getAsFile();
if (file) uploadFile(file);
});
}