mirror of
https://github.com/lllyasviel/stable-diffusion-webui-forge.git
synced 2026-07-21 21:01:24 +08:00
drop
This commit is contained in:
parent
addf9dcc79
commit
7e1ca521e3
60
javascript/dragdrop.js
vendored
60
javascript/dragdrop.js
vendored
@ -1,25 +1,16 @@
|
||||
// allows drag-dropping files into gradio image elements, and also pasting images from clipboard
|
||||
// allows drag-and-drop files into prompt fields, and also pasting images from clipboard
|
||||
|
||||
function isValidImageList(files) {
|
||||
return (
|
||||
files &&
|
||||
files?.length === 1 &&
|
||||
["image/png", "image/gif", "image/jpeg"].includes(files[0].type)
|
||||
);
|
||||
return files != null && files.length === 1 && files[0].type.startsWith("image");
|
||||
}
|
||||
|
||||
function dropReplaceImage(imgWrap, files) {
|
||||
if (!isValidImageList(files)) {
|
||||
return;
|
||||
}
|
||||
if (!isValidImageList(files)) return;
|
||||
|
||||
const tmpFile = files[0];
|
||||
|
||||
imgWrap
|
||||
.querySelector(
|
||||
".modify-upload button + button, .touch-none + div button + button",
|
||||
)
|
||||
?.click();
|
||||
imgWrap.querySelector(".modify-upload button + button, .touch-none + div button + button")?.click();
|
||||
|
||||
const callback = () => {
|
||||
const fileInput = imgWrap.querySelector('input[type="file"]');
|
||||
if (fileInput) {
|
||||
@ -40,8 +31,7 @@ function dropReplaceImage(imgWrap, files) {
|
||||
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;
|
||||
if (e.dataTransfer.items.length > 0 && e.dataTransfer.items[0].kind == "file") return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -56,10 +46,8 @@ function isURL(url) {
|
||||
}
|
||||
|
||||
function dragDropTargetIsPrompt(target) {
|
||||
if (target?.placeholder && target?.placeholder.indexOf("Prompt") >= 0)
|
||||
return true;
|
||||
if (target?.parentNode?.parentNode?.className?.indexOf("prompt") > 0)
|
||||
return true;
|
||||
if (target?.placeholder && target?.placeholder.indexOf("Prompt") >= 0) return true;
|
||||
if (target?.parentNode?.parentNode?.className?.indexOf("prompt") > 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -67,7 +55,7 @@ window.document.addEventListener("dragover", (e) => {
|
||||
const target = e.composedPath()[0];
|
||||
if (!eventHasFiles(e)) return;
|
||||
|
||||
let targetImage = target.closest('[data-testid="image"]');
|
||||
const targetImage = target.closest('[data-testid="image"]');
|
||||
if (!dragDropTargetIsPrompt(target) && !targetImage) return;
|
||||
|
||||
e.stopPropagation();
|
||||
@ -77,9 +65,7 @@ window.document.addEventListener("dragover", (e) => {
|
||||
|
||||
window.document.addEventListener("drop", async (e) => {
|
||||
const target = e.composedPath()[0];
|
||||
const url =
|
||||
e.dataTransfer.getData("text/uri-list") ||
|
||||
e.dataTransfer.getData("text/plain");
|
||||
const url = e.dataTransfer.getData("text/uri-list") || e.dataTransfer.getData("text/plain");
|
||||
if (!eventHasFiles(e) && !isURL(url)) return;
|
||||
|
||||
if (dragDropTargetIsPrompt(target)) {
|
||||
@ -87,9 +73,7 @@ window.document.addEventListener("drop", async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const isImg2img = get_tab_index("tabs") == 1;
|
||||
let prompt_image_target = isImg2img
|
||||
? "img2img_prompt_image"
|
||||
: "txt2img_prompt_image";
|
||||
const prompt_image_target = isImg2img ? "img2img_prompt_image" : "txt2img_prompt_image";
|
||||
|
||||
const imgParent = gradioApp().getElementById(prompt_image_target);
|
||||
const files = e.dataTransfer.files;
|
||||
@ -115,7 +99,7 @@ window.document.addEventListener("drop", async (e) => {
|
||||
}
|
||||
}
|
||||
|
||||
let targetImage = target.closest('[data-testid="image"]');
|
||||
const targetImage = target.closest('[data-testid="image"]');
|
||||
if (targetImage) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
@ -127,28 +111,18 @@ window.document.addEventListener("drop", async (e) => {
|
||||
|
||||
window.addEventListener("paste", (e) => {
|
||||
const files = e.clipboardData.files;
|
||||
if (!isValidImageList(files)) {
|
||||
return;
|
||||
}
|
||||
if (!isValidImageList(files)) return;
|
||||
|
||||
const visibleImageFields = [
|
||||
...gradioApp().querySelectorAll('[data-testid="image"]'),
|
||||
]
|
||||
const visibleImageFields = [...gradioApp().querySelectorAll('[data-testid="image"]')]
|
||||
.filter((el) => uiElementIsVisible(el))
|
||||
.sort((a, b) => uiElementInSight(b) - uiElementInSight(a));
|
||||
|
||||
if (!visibleImageFields.length) {
|
||||
return;
|
||||
}
|
||||
if (!visibleImageFields.length) return;
|
||||
|
||||
const firstFreeImageField = visibleImageFields.filter(
|
||||
(el) => !el.querySelector("img"),
|
||||
)?.[0];
|
||||
const firstFreeImageField = visibleImageFields.filter((el) => !el.querySelector("img"))?.[0];
|
||||
|
||||
dropReplaceImage(
|
||||
firstFreeImageField
|
||||
? firstFreeImageField
|
||||
: visibleImageFields[visibleImageFields.length - 1],
|
||||
firstFreeImageField ? firstFreeImageField : visibleImageFields[visibleImageFields.length - 1],
|
||||
files,
|
||||
);
|
||||
});
|
||||
|
||||
@ -1,55 +1,27 @@
|
||||
(function () {
|
||||
function extractImageFromHTML(html) {
|
||||
if (!html) return null;
|
||||
const match = html.match(/<img[^>]+src="([^">]+)"/i);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
/** @param {HTMLDivElement} gradioImage */
|
||||
function patchDragAndDrop(gradioImage) {
|
||||
let isDroppingImage = false;
|
||||
|
||||
gradioImage.addEventListener("dragover", (e) => {
|
||||
const dt = e.dataTransfer;
|
||||
isDroppingImage = dt.types.includes("text/uri-list") || dt.types.includes("text/html");
|
||||
if (isDroppingImage) e.preventDefault();
|
||||
});
|
||||
|
||||
gradioImage.addEventListener("drop", async (e) => {
|
||||
const isDroppingImage = dt.types.includes("text/uri-list") || dt.types.includes("text/html");
|
||||
if (!isDroppingImage) return;
|
||||
|
||||
const dt = e.dataTransfer;
|
||||
|
||||
const url = dt.getData("text/uri-list") || extractImageFromHTML(dt.getData("text/html"));
|
||||
if (!url) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
try {
|
||||
const closeButton = gradioImage.querySelector('button[aria-label="Remove Image"]');
|
||||
closeButton.click();
|
||||
|
||||
const res = await fetch(url);
|
||||
const blob = await res.blob();
|
||||
|
||||
const file = new File([blob], "dropped-image", {
|
||||
type: blob.type || "image/png",
|
||||
});
|
||||
|
||||
const newDT = new DataTransfer();
|
||||
newDT.items.add(file);
|
||||
|
||||
const fileInput = gradioImage.querySelector('input[type="file"]');
|
||||
fileInput.files = newDT.files;
|
||||
|
||||
fileInput.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
} catch {
|
||||
console.log("Failed to replace image...");
|
||||
}
|
||||
const closeButton = gradioImage.querySelector('button[aria-label="Remove Image"]');
|
||||
if (closeButton) closeButton.click();
|
||||
});
|
||||
}
|
||||
|
||||
function setup() {
|
||||
if (opts.remove_image_on_hover === false) return;
|
||||
if (opts.remove_image_on_hover === undefined) {
|
||||
setTimeout(setup, 50);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const id of ["extras_image", "pnginfo_image"]) patchDragAndDrop(document.getElementById(id));
|
||||
}
|
||||
|
||||
onUiLoaded(() => {
|
||||
for (const id of ["extras_image", "pnginfo_image"]) patchDragAndDrop(document.getElementById(id));
|
||||
setTimeout(setup, 100);
|
||||
});
|
||||
})();
|
||||
|
||||
@ -425,6 +425,7 @@ options_templates.update(
|
||||
"ctrl_enter_interrupt": OptionInfo(False, "Revert [Ctrl + Enter] to only interrupt the generation").info('the current "intended" behavior is to interrupt the current generation then immediately start a new one'),
|
||||
"quicksettings_accordion": OptionInfo(False, "Place the Quicksettings under an Accordion").needs_reload_ui(),
|
||||
"quicksettings_accordion_starts_closed": OptionInfo(False, "Close the Accordion on startup").info("for the above option").needs_reload_ui(),
|
||||
"remove_image_on_hover": OptionInfo(True, "For image inputs in Extras and PNG Info, remove the current image when dragging another image over it").info("allow you to drag-and-drop images onto the input similar to AUTOMATIC1111 behavior").needs_reload_ui(),
|
||||
"forbidden_knowledge": OptionInfo(False, "Forbidden Knowledge").info('replace "<b>DPM++ 2s a RF</b>" with "<b>Flux Realistic</b>"').needs_restart(),
|
||||
"div_prompt": OptionDiv(),
|
||||
"prompt_box_style": OptionInfo("Default", "Prompt Layout", gr.Radio, {"choices": ("Default", "Compact", "Scrollable", "Accordion")}).html(f"""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user