import { ref } from 'vue'
import { useChatStore } from '@/stores/chat.js'
import { uploadFile } from '@/api/index.js'
export function useFileUpload() {
const chat = useChatStore()
const isDragging = ref(false)
const uploadProgress = ref(0)
const uploading = ref(false)
// ─── Image handling ──────────────────────────────────────────────────────
function addImageFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = (e) => {
chat.pendingImages.push(e.target.result)
resolve()
}
reader.onerror = reject
reader.readAsDataURL(file)
})
}
function removeImage(index) {
chat.pendingImages.splice(index, 1)
}
// ─── File handling ───────────────────────────────────────────────────────
async function addFile(file) {
if (!chat.currentId) return
uploading.value = true
uploadProgress.value = 0
try {
const result = await uploadFile(chat.currentId, file)
chat.pendingFiles.push(result)
} finally {
uploading.value = false
uploadProgress.value = 0
}
}
function removeFile(index) {
chat.pendingFiles.splice(index, 1)
}
// ─── File picker ─────────────────────────────────────────────────────────
async function handleFileInput(event) {
const files = Array.from(event.target.files ?? [])
event.target.value = ''
await processFiles(files)
}
// ─── Image paste ─────────────────────────────────────────────────────────
async function handlePaste(event) {
const items = Array.from(event.clipboardData?.items ?? [])
const imageItems = items.filter(i => i.type.startsWith('image/'))
if (!imageItems.length) return
event.preventDefault()
for (const item of imageItems) {
const file = item.getAsFile()
if (file) await addImageFile(file)
}
}
// ─── Drag and drop ───────────────────────────────────────────────────────
function handleDragEnter(event) {
event.preventDefault()
if (hasFiles(event)) isDragging.value = true
}
function handleDragOver(event) {
event.preventDefault()
}
function handleDragLeave(event) {
// Only clear if leaving the drop zone entirely
if (!event.currentTarget.contains(event.relatedTarget)) {
isDragging.value = false
}
}
async function handleDrop(event) {
event.preventDefault()
isDragging.value = false
const files = Array.from(event.dataTransfer?.files ?? [])
await processFiles(files)
}
// ─── Shared processing ───────────────────────────────────────────────────
async function processFiles(files) {
for (const file of files) {
if (file.type.startsWith('image/')) {
await addImageFile(file)
} else {
await addFile(file)
}
}
}
function clearPending() {
chat.pendingImages = []
chat.pendingFiles = []
}
function hasFiles(event) {
return Array.from(event.dataTransfer?.types ?? []).includes('Files')
}
return {
isDragging,
uploading,
uploadProgress,
handleFileInput,
handlePaste,
handleDragEnter,
handleDragOver,
handleDragLeave,
handleDrop,
removeImage,
removeFile,
clearPending
}
}