mirror of
https://github.com/sd-webui/stable-diffusion-webui.git
synced 2024-12-14 14:52:31 +03:00
refactor: python js interface (#381)
* refactor js interface * rename call_SD to call_JS * add invocation example to call_JS * serialize args before passing them to js * allow override of x
This commit is contained in:
parent
8212d8e5de
commit
773aa60e8a
@ -1,4 +1,6 @@
|
||||
from os import path
|
||||
import json
|
||||
|
||||
|
||||
def readTextFile(*args):
|
||||
dir = path.dirname(__file__)
|
||||
@ -7,31 +9,25 @@ def readTextFile(*args):
|
||||
data = f.read()
|
||||
return data
|
||||
|
||||
|
||||
def css(opt):
|
||||
styling = readTextFile("css", "styles.css")
|
||||
if not opt.no_progressbar_hiding:
|
||||
styling += readTextFile("css", "no_progress_bar.css")
|
||||
return styling
|
||||
|
||||
|
||||
def js(opt):
|
||||
data = readTextFile("js", "index.js")
|
||||
data = "(z) => {" + data + "; return z ?? [] }"
|
||||
return data
|
||||
|
||||
|
||||
# Wrap the typical SD method call into async closure for ease of use
|
||||
# If you call frontend method without wrapping
|
||||
# DONT FORGET to bind input argument if you need it: SD.with(x)
|
||||
def w(sd_method_call):
|
||||
return f"async (x) => {{ return await SD.with(x).{sd_method_call} ?? x ?? []; }}"
|
||||
|
||||
def js_move_image(from_id, to_id):
|
||||
return w(f"moveImageFromGallery('{from_id}', '{to_id}')")
|
||||
|
||||
def js_copy_to_clipboard(from_id):
|
||||
return w(f"copyImageFromGalleryToClipboard('{from_id}')")
|
||||
|
||||
def js_painterro_launch(to_id):
|
||||
return w(f"Painterro.init('{to_id}')")
|
||||
|
||||
def js_img2img_submit(prompt_row_id):
|
||||
return w(f"clickFirstVisibleButton('{prompt_row_id}')")
|
||||
# Supplies the js function with a params object
|
||||
# That includes all the passed arguments and input from Gradio: x
|
||||
# Example call in Gradio component's event handler (pass the result to _js arg):
|
||||
# _js=call_JS("myJsMethod", arg1="string", arg2=100, arg3=[])
|
||||
def call_JS(sd_method, **kwargs):
|
||||
param_str = json.dumps(kwargs)
|
||||
return f"async (x) => {{ return await SD.{sd_method}({{ x, ...{param_str} }}) ?? []; }}"
|
||||
|
@ -1,6 +1,5 @@
|
||||
import gradio as gr
|
||||
from frontend.css_and_js import *
|
||||
from frontend.css_and_js import css
|
||||
from frontend.css_and_js import css, js, call_JS
|
||||
import frontend.ui_functions as uifn
|
||||
|
||||
def draw_gradio_ui(opt, img2img=lambda x: x, txt2img=lambda x: x, txt2img_defaults={}, RealESRGAN=True, GFPGAN=True,
|
||||
@ -47,10 +46,13 @@ def draw_gradio_ui(opt, img2img=lambda x: x, txt2img=lambda x: x, txt2img_defaul
|
||||
gr.Markdown(
|
||||
'Select an image from the gallery, then click one of the buttons below to perform an action.')
|
||||
with gr.Row():
|
||||
output_txt2img_copy_clipboard = gr.Button("Copy to clipboard").click(fn=None,
|
||||
inputs=output_txt2img_gallery,
|
||||
outputs=[],
|
||||
_js=js_copy_to_clipboard('txt2img_gallery_output'))
|
||||
output_txt2img_copy_clipboard = gr.Button("Copy to clipboard")\
|
||||
.click(fn=None,
|
||||
inputs=output_txt2img_gallery,
|
||||
outputs=[],
|
||||
_js=call_JS("copyImageFromGalleryToClipboard",
|
||||
fromId="txt2img_gallery_output")
|
||||
)
|
||||
output_txt2img_copy_to_input_btn = gr.Button("Push to img2img")
|
||||
if RealESRGAN is not None:
|
||||
output_txt2img_to_upscale_esrgan = gr.Button("Upscale w/ ESRGAN")
|
||||
@ -60,11 +62,13 @@ def draw_gradio_ui(opt, img2img=lambda x: x, txt2img=lambda x: x, txt2img_defaul
|
||||
with gr.Row():
|
||||
output_txt2img_copy_params = gr.Button("Copy full parameters").click(
|
||||
inputs=output_txt2img_params, outputs=[],
|
||||
_js='(x) => navigator.clipboard.writeText(x)', fn=None, show_progress=False)
|
||||
fn=None, show_progress=False,
|
||||
_js=call_JS("gradioInputToClipboard")
|
||||
)
|
||||
output_txt2img_seed = gr.Number(label='Seed', interactive=False, visible=False)
|
||||
output_txt2img_copy_seed = gr.Button("Copy only seed").click(
|
||||
inputs=output_txt2img_seed, outputs=[],
|
||||
_js='(x) => navigator.clipboard.writeText(x)', fn=None, show_progress=False)
|
||||
_js=call_JS("gradioInputToClipboard"), fn=None, show_progress=False)
|
||||
output_txt2img_stats = gr.HTML(label='Stats')
|
||||
with gr.Column():
|
||||
|
||||
@ -153,7 +157,7 @@ def draw_gradio_ui(opt, img2img=lambda x: x, txt2img=lambda x: x, txt2img_defaul
|
||||
value=3, visible=False)
|
||||
|
||||
img2img_resize = gr.Radio(label="Resize mode",
|
||||
choices=["Just resize", "Crop and resize", "Resize and fill"],
|
||||
choices=["Just resize"],
|
||||
type="index",
|
||||
value=img2img_resize_modes[img2img_defaults['resize_mode']])
|
||||
|
||||
@ -172,17 +176,18 @@ def draw_gradio_ui(opt, img2img=lambda x: x, txt2img=lambda x: x, txt2img_defaul
|
||||
output_img2img_copy_to_clipboard_btn = gr.Button("Copy to clipboard")
|
||||
output_img2img_copy_to_input_btn = gr.Button("Push to img2img input")
|
||||
output_img2img_copy_to_mask_btn = gr.Button("Push to img2img input mask")
|
||||
|
||||
gr.Markdown("Warning: This will clear your current image and mask settings!")
|
||||
with gr.TabItem("Output info", id="img2img_output_info_tab"):
|
||||
output_img2img_params = gr.Textbox(label="Generation parameters")
|
||||
with gr.Row():
|
||||
output_img2img_copy_params = gr.Button("Copy full parameters").click(
|
||||
inputs=output_img2img_params, outputs=[],
|
||||
_js='(x) => navigator.clipboard.writeText(x)', fn=None, show_progress=False)
|
||||
_js=call_JS("gradioInputToClipboard"), fn=None, show_progress=False)
|
||||
output_img2img_seed = gr.Number(label='Seed', interactive=False, visible=False)
|
||||
output_img2img_copy_seed = gr.Button("Copy only seed").click(
|
||||
inputs=output_img2img_seed, outputs=[],
|
||||
_js='(x) => navigator.clipboard.writeText(x)', fn=None, show_progress=False)
|
||||
_js=call_JS("gradioInputToClipboard"), fn=None, show_progress=False)
|
||||
output_img2img_stats = gr.HTML(label='Stats')
|
||||
gr.Markdown('# img2img settings')
|
||||
|
||||
@ -247,24 +252,32 @@ def draw_gradio_ui(opt, img2img=lambda x: x, txt2img=lambda x: x, txt2img_defaul
|
||||
uifn.copy_img_to_input,
|
||||
[output_txt2img_gallery],
|
||||
[img2img_image_editor, img2img_image_mask, tabs],
|
||||
_js=js_move_image('txt2img_gallery_output', 'img2img_editor')
|
||||
_js=call_JS("moveImageFromGallery",
|
||||
fromId="txt2img_gallery_output",
|
||||
toId="img2img_editor")
|
||||
)
|
||||
|
||||
output_img2img_copy_to_input_btn.click(
|
||||
uifn.copy_img_to_edit,
|
||||
[output_img2img_gallery],
|
||||
[img2img_image_editor, tabs, img2img_image_editor_mode],
|
||||
_js=js_move_image('img2img_gallery_output', 'img2img_editor')
|
||||
_js=call_JS("moveImageFromGallery",
|
||||
fromId="img2img_gallery_output",
|
||||
toId="img2img_editor")
|
||||
)
|
||||
output_img2img_copy_to_mask_btn.click(
|
||||
uifn.copy_img_to_mask,
|
||||
[output_img2img_gallery],
|
||||
[img2img_image_mask, tabs, img2img_image_editor_mode],
|
||||
_js=js_move_image('img2img_gallery_output', 'img2img_editor')
|
||||
_js=call_JS("moveImageFromGallery",
|
||||
fromId="img2img_gallery_output",
|
||||
toId="img2img_editor")
|
||||
)
|
||||
|
||||
output_img2img_copy_to_clipboard_btn.click(fn=None, inputs=output_img2img_gallery, outputs=[],
|
||||
_js=js_copy_to_clipboard('img2img_gallery_output'))
|
||||
_js=call_JS("copyImageFromGalleryToClipboard",
|
||||
fromId="img2img_gallery_output")
|
||||
)
|
||||
|
||||
img2img_btn_mask.click(
|
||||
img2img,
|
||||
@ -287,9 +300,14 @@ def draw_gradio_ui(opt, img2img=lambda x: x, txt2img=lambda x: x, txt2img_defaul
|
||||
|
||||
# GENERATE ON ENTER
|
||||
img2img_prompt.submit(None, None, None,
|
||||
_js=js_img2img_submit("prompt_row"))
|
||||
_js=call_JS("clickFirstVisibleButton",
|
||||
rowId="prompt_row"))
|
||||
|
||||
img2img_painterro_btn.click(None, [img2img_image_editor], [img2img_image_editor, img2img_image_mask], _js=js_painterro_launch('img2img_editor'))
|
||||
img2img_painterro_btn.click(None,
|
||||
[img2img_image_editor],
|
||||
[img2img_image_editor, img2img_image_mask],
|
||||
_js=call_JS("Painterro.init", toId="img2img_editor")
|
||||
)
|
||||
|
||||
img2img_width.change(fn=uifn.update_dimensions_info, inputs=[img2img_width, img2img_height], outputs=img2img_dimensions_info_text_box)
|
||||
img2img_height.change(fn=uifn.update_dimensions_info, inputs=[img2img_width, img2img_height], outputs=img2img_dimensions_info_text_box)
|
||||
@ -338,7 +356,10 @@ def draw_gradio_ui(opt, img2img=lambda x: x, txt2img=lambda x: x, txt2img_defaul
|
||||
uifn.copy_img_to_upscale_esrgan,
|
||||
output_txt2img_gallery,
|
||||
[realesrgan_source, tabs],
|
||||
_js=js_move_image('txt2img_gallery_output', 'img2img_editor'))
|
||||
_js=call_JS("moveImageFromGallery",
|
||||
fromId="txt2img_gallery_output",
|
||||
toId="img2img_editor")
|
||||
)
|
||||
|
||||
gr.HTML("""
|
||||
<div id="90" style="max-width: 100%; font-size: 14px; text-align: center;" class="output-markdown gr-prose border-solid border border-gray-200 rounded gr-panel">
|
||||
|
@ -5,8 +5,8 @@ window.SD = (() => {
|
||||
*/
|
||||
class PainterroClass {
|
||||
static isOpen = false;
|
||||
static async init (toId) {
|
||||
const img = SD.x;
|
||||
static async init ({ x, toId }) {
|
||||
const img = x;
|
||||
const originalImage = Array.isArray(img) ? img[0] : img;
|
||||
|
||||
if (window.Painterro === undefined) {
|
||||
@ -110,42 +110,28 @@ window.SD = (() => {
|
||||
*/
|
||||
class SDClass {
|
||||
el = new ElementCache();
|
||||
x;
|
||||
Painterro = PainterroClass;
|
||||
with (x) {
|
||||
this.x = x;
|
||||
return this;
|
||||
}
|
||||
moveImageFromGallery (fromId, toId) {
|
||||
if (!Array.isArray(this.x) || this.x.length === 0) return;
|
||||
moveImageFromGallery ({ x, fromId, toId }) {
|
||||
if (!Array.isArray(x) || x.length === 0) return;
|
||||
|
||||
this.clearImageInput(this.el.get(`#${toId}`));
|
||||
|
||||
const i = this.#getGallerySelectedIndex(this.el.get(`#${fromId}`));
|
||||
|
||||
return [this.x[i].replace('data:;','data:image/png;')];
|
||||
return [x[i].replace('data:;','data:image/png;')];
|
||||
}
|
||||
async copyImageFromGalleryToClipboard (fromId) {
|
||||
if (!Array.isArray(this.x) || this.x.length === 0) return;
|
||||
async copyImageFromGalleryToClipboard ({ x, fromId }) {
|
||||
if (!Array.isArray(x) || x.length === 0) return;
|
||||
|
||||
const i = this.#getGallerySelectedIndex(this.el.get(`#${fromId}`));
|
||||
|
||||
const data = this.x[i];
|
||||
const data = x[i];
|
||||
const blob = await (await fetch(data.replace('data:;','data:image/png;'))).blob();
|
||||
const item = new ClipboardItem({'image/png': blob});
|
||||
|
||||
try {
|
||||
navigator.clipboard.write([item]);
|
||||
} catch (e) {
|
||||
SDClass.error(e);
|
||||
}
|
||||
|
||||
return this.x;
|
||||
await this.copyToClipboard([item]);
|
||||
}
|
||||
clearImageInput (imageEditor) {
|
||||
imageEditor?.querySelector('.modify-upload button:last-child')?.click();
|
||||
}
|
||||
clickFirstVisibleButton(rowId) {
|
||||
clickFirstVisibleButton({ rowId }) {
|
||||
const generateButtons = this.el.get(`#${rowId}`).querySelectorAll('.gr-button-primary');
|
||||
|
||||
if (!generateButtons) return;
|
||||
@ -161,6 +147,21 @@ window.SD = (() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
async gradioInputToClipboard ({ x }) { return this.copyToClipboard(x); }
|
||||
async copyToClipboard (value) {
|
||||
if (!value || typeof value === 'boolean') return;
|
||||
try {
|
||||
if (Array.isArray(value) &&
|
||||
value.length &&
|
||||
value[0] instanceof ClipboardItem) {
|
||||
await navigator.clipboard.write(value);
|
||||
} else {
|
||||
await navigator.clipboard.writeText(value);
|
||||
}
|
||||
} catch (e) {
|
||||
SDClass.error(e);
|
||||
}
|
||||
}
|
||||
static error (e) {
|
||||
console.error(e);
|
||||
if (typeof e === 'string') {
|
||||
@ -169,6 +170,9 @@ window.SD = (() => {
|
||||
alert(e.message);
|
||||
}
|
||||
}
|
||||
clearImageInput (imageEditor) {
|
||||
imageEditor?.querySelector('.modify-upload button:last-child')?.click();
|
||||
}
|
||||
#getGallerySelectedIndex (gallery) {
|
||||
const selected = gallery.querySelector(`.\\!ring-2`);
|
||||
return selected ? [...selected.parentNode.children].indexOf(selected) : 0;
|
||||
|
Loading…
Reference in New Issue
Block a user