// allows drag-and-drop files into prompt fields, and also pasting images from clipboard function isValidImageList(files) { return files != null && files.length === 1 && files[0].type.startsWith("image"); } function dropReplaceImage(imgWrap, files) { if (!isValidImageList(files)) return; const tmpFile = files[0]; imgWrap.querySelector(".modify-upload button + button, .touch-none + div button + button")?.click(); const callback = () => { const fileInput = imgWrap.querySelector('input[type="file"]'); if (fileInput) { if (files.length === 0) { files = new DataTransfer(); files.items.add(tmpFile); fileInput.files = files.files; } else { fileInput.files = files; } fileInput.dispatchEvent(new Event("change")); } }; window.requestAnimationFrame(() => callback()); } function eventHasFiles(e) { if (!e.dataTransfer || !e.dataTransfer.files) return false; if (e.dataTransfer.files.length > 0) return true; if (e.dataTransfer.items.length > 0 && e.dataTransfer.items[0].kind == "file") return true; return false; } function isURL(url) { try { const _ = new URL(url); return true; } catch { return false; } } function dragDropTargetIsPrompt(target) { if (target?.placeholder && target?.placeholder.indexOf("Prompt") >= 0) return true; if (target?.parentNode?.parentNode?.className?.indexOf("prompt") > 0) return true; return false; } window.document.addEventListener("dragover", (e) => { const target = e.composedPath()[0]; if (!eventHasFiles(e)) return; const targetImage = target.closest('[data-testid="image"]'); if (!dragDropTargetIsPrompt(target) && !targetImage) return; e.stopPropagation(); e.preventDefault(); e.dataTransfer.dropEffect = "copy"; }); window.document.addEventListener("drop", async (e) => { const target = e.composedPath()[0]; const url = e.dataTransfer.getData("text/uri-list") || e.dataTransfer.getData("text/plain"); if (!eventHasFiles(e) && !isURL(url)) return; if (dragDropTargetIsPrompt(target)) { e.stopPropagation(); e.preventDefault(); const isImg2img = get_tab_index("tabs") == 1; const prompt_image_target = isImg2img ? "img2img_prompt_image" : "txt2img_prompt_image"; const imgParent = gradioApp().getElementById(prompt_image_target); const files = e.dataTransfer.files; const fileInput = imgParent.querySelector('input[type="file"]'); if (eventHasFiles(e) && fileInput) { fileInput.files = files; fileInput.dispatchEvent(new Event("change")); } else if (url) { try { const request = await fetch(url); if (!request.ok) { console.error("Error fetching URL:", url, request.status); return; } const data = new DataTransfer(); data.items.add(new File([await request.blob()], "image.png")); fileInput.files = data.files; fileInput.dispatchEvent(new Event("change")); } catch (error) { console.error("Error fetching URL:", url, error); return; } } } const targetImage = target.closest('[data-testid="image"]'); if (targetImage) { e.stopPropagation(); e.preventDefault(); const files = e.dataTransfer.files; dropReplaceImage(targetImage, files); return; } }); window.addEventListener("paste", (e) => { const files = e.clipboardData.files; if (!isValidImageList(files)) return; const visibleImageFields = [...gradioApp().querySelectorAll('[data-testid="image"]')] .filter((el) => uiElementIsVisible(el)) .sort((a, b) => uiElementInSight(b) - uiElementInSight(a)); if (!visibleImageFields.length) return; const firstFreeImageField = visibleImageFields.filter((el) => !el.querySelector("img"))?.[0]; dropReplaceImage( firstFreeImageField ? firstFreeImageField : visibleImageFields[visibleImageFields.length - 1], files, ); });