Fixes for UI
This commit is contained in:
@@ -82,6 +82,7 @@ export default class ComfyGraphCanvas extends LGraphCanvas {
|
||||
|
||||
let state = get(queueState);
|
||||
let ss = get(selectionState);
|
||||
const isRunningNode = node.id === state.runningNodeID
|
||||
|
||||
let color = null;
|
||||
let thickness = 1;
|
||||
@@ -92,16 +93,22 @@ export default class ComfyGraphCanvas extends LGraphCanvas {
|
||||
if (ss.currentHoveredNodes.has(node.id)) {
|
||||
color = "lightblue";
|
||||
}
|
||||
else if (node.id === +state.runningNodeID) {
|
||||
else if (isRunningNode) {
|
||||
color = "#0f0";
|
||||
}
|
||||
|
||||
if (color) {
|
||||
this.drawNodeOutline(node, ctx, state.progress, size, fgColor, bgColor, color, thickness)
|
||||
this.drawNodeOutline(node, ctx, size, fgColor, bgColor, color, thickness)
|
||||
}
|
||||
|
||||
if (isRunningNode && state.progress) {
|
||||
ctx.fillStyle = "green";
|
||||
ctx.fillRect(0, 0, size[0] * (state.progress.value / state.progress.max), 6);
|
||||
ctx.fillStyle = bgColor;
|
||||
}
|
||||
}
|
||||
|
||||
private drawNodeOutline(node: LGraphNode, ctx: CanvasRenderingContext2D, progress?: Progress, size: Vector2, fgColor: string, bgColor: string, outlineColor: string, outlineThickness: number) {
|
||||
private drawNodeOutline(node: LGraphNode, ctx: CanvasRenderingContext2D, size: Vector2, fgColor: string, bgColor: string, outlineColor: string, outlineThickness: number) {
|
||||
const shape = node.shape || BuiltInSlotShape.ROUND_SHAPE;
|
||||
ctx.lineWidth = outlineThickness;
|
||||
ctx.globalAlpha = 0.8;
|
||||
@@ -131,12 +138,6 @@ export default class ComfyGraphCanvas extends LGraphCanvas {
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = fgColor;
|
||||
ctx.globalAlpha = 1;
|
||||
|
||||
if (progress) {
|
||||
ctx.fillStyle = "green";
|
||||
ctx.fillRect(0, 0, size[0] * (progress.value / progress.max), 6);
|
||||
ctx.fillStyle = bgColor;
|
||||
}
|
||||
}
|
||||
|
||||
private alignToGrid(node: LGraphNode, ctx: CanvasRenderingContext2D) {
|
||||
|
||||
@@ -137,45 +137,22 @@ export class ImageViewer {
|
||||
}
|
||||
}
|
||||
|
||||
setupGalleryImageForLightbox(e: HTMLImageElement) {
|
||||
if (e.dataset.modded === "true")
|
||||
showLightbox(source: HTMLImageElement) {
|
||||
const initiallyZoomed = true
|
||||
this.modalZoomSet(this.modalImage, initiallyZoomed)
|
||||
|
||||
const galleryElem = source.closest<HTMLDivElement>("div.block")
|
||||
console.debug("[ImageViewer] showModal", event, source, galleryElem);
|
||||
if (!galleryElem || ImageViewer.all_gallery_buttons(galleryElem).length === 0) {
|
||||
console.error("No buttons found on gallery element!", galleryElem)
|
||||
return;
|
||||
}
|
||||
|
||||
e.dataset.modded = "true";
|
||||
e.style.cursor = 'pointer'
|
||||
e.style.userSelect = 'none'
|
||||
|
||||
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1
|
||||
|
||||
// For Firefox, listening on click first switched to next image then shows the lightbox.
|
||||
// If you know how to fix this without switching to mousedown event, please.
|
||||
// For other browsers the event is click to make it possiblr to drag picture.
|
||||
var event = isFirefox ? 'mousedown' : 'click'
|
||||
|
||||
e.addEventListener(event, (evt) => {
|
||||
// if (!opts.js_modal_lightbox || evt.button != 0) return;
|
||||
|
||||
const initiallyZoomed = true
|
||||
this.modalZoomSet(this.modalImage, initiallyZoomed)
|
||||
evt.preventDefault()
|
||||
|
||||
const source = evt.target as HTMLImageElement;
|
||||
|
||||
const galleryElem = source.closest<HTMLDivElement>("div.block")
|
||||
console.debug("[ImageViewer] showModal", event, source, galleryElem);
|
||||
if (!galleryElem || ImageViewer.all_gallery_buttons(galleryElem).length === 0) {
|
||||
console.error("No buttons found on gallery element!", galleryElem)
|
||||
return;
|
||||
}
|
||||
|
||||
let urls = ImageViewer.get_gallery_urls(galleryElem)
|
||||
const [_currentButton, index] = ImageViewer.selected_gallery_button(galleryElem)
|
||||
console.warn("Gallery!", index, urls, galleryElem)
|
||||
|
||||
this.showModal(urls, index, galleryElem)
|
||||
evt.stopPropagation();
|
||||
}, true);
|
||||
let urls = ImageViewer.get_gallery_urls(galleryElem)
|
||||
const [_currentButton, index] = ImageViewer.selected_gallery_button(galleryElem)
|
||||
console.warn("Gallery!", index, urls, galleryElem)
|
||||
|
||||
this.showModal(urls, index, galleryElem)
|
||||
}
|
||||
|
||||
modalZoomSet(modalImage: HTMLImageElement, enable: boolean) {
|
||||
|
||||
@@ -65,9 +65,11 @@
|
||||
dateStr = formatDate(date);
|
||||
}
|
||||
|
||||
const subgraphs: string[] | null = entry.extraData?.extra_pnginfo?.comfyBoxSubgraphs;
|
||||
|
||||
let message = "Prompt";
|
||||
if (entry.extraData.subgraphs)
|
||||
message = `Prompt: ${entry.extraData.subgraphs.join(', ')}`
|
||||
if (subgraphs?.length > 0)
|
||||
message = `Prompt: ${subgraphs.join(', ')}`
|
||||
|
||||
let submessage = `Nodes: ${Object.keys(entry.prompt).length}`
|
||||
if (Object.keys(entry.outputs).length > 0) {
|
||||
@@ -156,12 +158,14 @@
|
||||
}
|
||||
|
||||
let showModal = false;
|
||||
let expandAll = false;
|
||||
let selectedPrompt = null;
|
||||
let selectedImages = [];
|
||||
function showPrompt(entry: QueueUIEntry, e: MouseEvent) {
|
||||
selectedPrompt = entry.entry.prompt;
|
||||
selectedImages = entry.images;
|
||||
showModal = true;
|
||||
expandAll = false
|
||||
}
|
||||
|
||||
$: if(!showModal)
|
||||
@@ -180,8 +184,16 @@
|
||||
<h1 style="padding-bottom: 1rem;">Prompt Details</h1>
|
||||
</div>
|
||||
{#if selectedPrompt}
|
||||
<PromptDisplay prompt={selectedPrompt} images={selectedImages} />
|
||||
<PromptDisplay prompt={selectedPrompt} images={selectedImages} {expandAll} />
|
||||
{/if}
|
||||
<div slot="buttons" let:closeDialog>
|
||||
<Button variant="secondary" on:click={closeDialog}>
|
||||
Close
|
||||
</Button>
|
||||
<Button variant="secondary" on:click={() => (expandAll = !expandAll)}>
|
||||
Expand All
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<div class="queue">
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
}
|
||||
|
||||
function doClose() {
|
||||
showModal = false;
|
||||
dialog.close();
|
||||
dispatch("close")
|
||||
}
|
||||
@@ -41,7 +42,7 @@
|
||||
<slot name="header" />
|
||||
<slot />
|
||||
<div class="button-row">
|
||||
<slot name="buttons">
|
||||
<slot name="buttons" {closeDialog}>
|
||||
<!-- svelte-ignore a11y-autofocus -->
|
||||
<Button variant="secondary" on:click={doClose}>Close</Button>
|
||||
</slot>
|
||||
|
||||
@@ -6,16 +6,20 @@
|
||||
import { JSON as JSONIcon, Copy, Check } from "@gradio/icons";
|
||||
import Accordion from "$lib/components/gradio/app/Accordion.svelte";
|
||||
import Gallery from "$lib/components/gradio/gallery/Gallery.svelte";
|
||||
import type { Styles } from "@gradio/utils";
|
||||
import { ImageViewer } from "$lib/ImageViewer";
|
||||
import type { Styles } from "@gradio/utils";
|
||||
|
||||
const splitLength = 50;
|
||||
|
||||
export let prompt: SerializedPromptInputsAll;
|
||||
export let images: string[] = [];
|
||||
export let isMobile: boolean = false;
|
||||
export let expandAll: boolean = false;
|
||||
|
||||
let galleryStyle: Styles = {
|
||||
grid_cols: [2],
|
||||
object_fit: "cover",
|
||||
height: "var(--size-96)"
|
||||
}
|
||||
|
||||
function isInputLink(input: SerializedPromptInput): boolean {
|
||||
@@ -59,6 +63,11 @@
|
||||
copyFeedback(nodeID, inputName);
|
||||
}
|
||||
}
|
||||
|
||||
function onGalleryImageClicked(e: CustomEvent<HTMLImageElement>) {
|
||||
// TODO dialog renders over it
|
||||
// ImageViewer.instance.showLightbox(e.detail)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="prompt-display">
|
||||
@@ -70,7 +79,7 @@
|
||||
{#if filtered.length > 0}
|
||||
<div class="accordion">
|
||||
<Block padding={true}>
|
||||
<Accordion label="Node {i+1}: {classType}" open={false}>
|
||||
<Accordion label="Node {i+1}: {classType}" open={expandAll}>
|
||||
{#each filtered as [inputName, input]}
|
||||
<Block>
|
||||
<button class="copy-button" on:click={() => handleCopy(nodeID, inputName, input)}>
|
||||
@@ -121,6 +130,7 @@
|
||||
style={galleryStyle}
|
||||
root={""}
|
||||
root_url={""}
|
||||
on:clicked={onGalleryImageClicked}
|
||||
/>
|
||||
</Block>
|
||||
</div>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
select: SelectData;
|
||||
clicked: HTMLImageElement
|
||||
}>();
|
||||
|
||||
// tracks whether the value of the gallery was reset
|
||||
@@ -142,6 +143,14 @@
|
||||
|
||||
let height = 0;
|
||||
let window_height = 0;
|
||||
|
||||
let imgElem = null;
|
||||
|
||||
function onClick() {
|
||||
// selected_image = next
|
||||
if (imgElem)
|
||||
dispatch("clicked", imgElem)
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window bind:innerHeight={window_height} />
|
||||
@@ -166,7 +175,8 @@
|
||||
<ModifyUpload on:clear={() => (selected_image = null)} />
|
||||
|
||||
<img
|
||||
on:click={() => (selected_image = next)}
|
||||
on:click={onClick}
|
||||
bind:this={imgElem}
|
||||
src={_value[selected_image][0].data}
|
||||
alt={_value[selected_image][1] || ""}
|
||||
title={_value[selected_image][1] || null}
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
let mobileLightbox = null;
|
||||
|
||||
function showMobileLightbox(event: Event) {
|
||||
function showMobileLightbox(source: HTMLImageElement) {
|
||||
if (!f7)
|
||||
return
|
||||
|
||||
@@ -58,16 +58,14 @@
|
||||
mobileLightbox = null;
|
||||
}
|
||||
|
||||
const source = (event.target || event.srcElement) as HTMLImageElement;
|
||||
const galleryElem = source.closest<HTMLDivElement>("div.block")
|
||||
console.debug("[ImageViewer] showModal", event, source, galleryElem);
|
||||
console.debug("[ImageViewer] showModal", source, galleryElem);
|
||||
if (!galleryElem || ImageViewer.all_gallery_buttons(galleryElem).length === 0) {
|
||||
console.error("No buttons found on gallery element!", galleryElem)
|
||||
return;
|
||||
}
|
||||
|
||||
const allGalleryButtons = ImageViewer.all_gallery_buttons(galleryElem);
|
||||
const selectedSource = source.src
|
||||
|
||||
const images = allGalleryButtons.map(button => {
|
||||
return {
|
||||
@@ -84,47 +82,18 @@
|
||||
type: 'popup',
|
||||
});
|
||||
mobileLightbox.open(selected_image)
|
||||
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
function setupImageForMobileLightbox(e: HTMLImageElement) {
|
||||
if (e.dataset.modded === "true")
|
||||
return;
|
||||
|
||||
e.dataset.modded = "true";
|
||||
e.style.cursor = "pointer";
|
||||
e.style.userSelect = "none";
|
||||
|
||||
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1
|
||||
|
||||
// For Firefox, listening on click first switched to next image then shows the lightbox.
|
||||
// If you know how to fix this without switching to mousedown event, please.
|
||||
// For other browsers the event is click to make it possiblr to drag picture.
|
||||
var event = isFirefox ? 'mousedown' : 'click'
|
||||
|
||||
e.addEventListener(event, (evt) => {
|
||||
evt.preventDefault()
|
||||
showMobileLightbox(evt)
|
||||
}, true);
|
||||
function onClicked(e: CustomEvent<HTMLImageElement>) {
|
||||
if (isMobile) {
|
||||
showMobileLightbox(e.detail)
|
||||
}
|
||||
else {
|
||||
ImageViewer.instance.showLightbox(e.detail)
|
||||
}
|
||||
}
|
||||
|
||||
function onSelect(e: CustomEvent<GradioSelectData>) {
|
||||
// Setup lightbox
|
||||
// Wait for gradio gallery to show the large preview image, if no timeout then
|
||||
// the event might fire too early
|
||||
|
||||
const callback = isMobile ? setupImageForMobileLightbox
|
||||
: ImageViewer.instance.setupGalleryImageForLightbox.bind(ImageViewer.instance)
|
||||
|
||||
setTimeout(() => {
|
||||
const images = element.querySelectorAll<HTMLImageElement>('div.block div > img')
|
||||
if (images != null) {
|
||||
images.forEach(callback);
|
||||
}
|
||||
ImageViewer.instance.refreshImages();
|
||||
}, 200)
|
||||
|
||||
// Update index
|
||||
node.setProperty("index", e.detail.index as number)
|
||||
}
|
||||
@@ -176,6 +145,7 @@
|
||||
root={""}
|
||||
root_url={""}
|
||||
on:select={onSelect}
|
||||
on:clicked={onClicked}
|
||||
bind:imageWidth={$imageWidth}
|
||||
bind:imageHeight={$imageHeight}
|
||||
bind:selected_image
|
||||
|
||||
Reference in New Issue
Block a user