Delete queue/history item

This commit is contained in:
space-nuko
2023-05-22 14:16:31 -05:00
parent a913a92096
commit 40c7eaa7ce
5 changed files with 136 additions and 15 deletions

View File

@@ -331,7 +331,7 @@ export default class ComfyAPI {
* @param {string} type The type of item to delete, queue or history * @param {string} type The type of item to delete, queue or history
* @param {number} id The id of the item to delete * @param {number} id The id of the item to delete
*/ */
async deleteItem(type: QueueItemType, id: number): Promise<Response> { async deleteItem(type: QueueItemType, id: PromptID): Promise<Response> {
return this.postItem(type, { delete: [id] }); return this.postItem(type, { delete: [id] });
} }

View File

@@ -509,7 +509,35 @@ export default class ComfyApp {
this.api.init(); this.api.init();
} }
async interrupt() {
if (get(queueState).isInterrupting)
return
queueState.update(s => { s.isInterrupting = true; return s; })
await this.api.interrupt()
.finally(() => {
queueState.update(s => { s.isInterrupting = true; return s })
});
}
async deleteQueueItem(type: QueueItemType, promptID: PromptID) {
if (get(queueState).isInterrupting)
return
queueState.update(s => { s.isInterrupting = true; return s; })
await this.api.deleteItem(type, promptID)
.then(() => {
queueState.queueItemDeleted(type, promptID);
})
.finally(() => {
queueState.update(s => { s.isInterrupting = false; return s; })
});
}
async clearQueue(type: QueueItemType) { async clearQueue(type: QueueItemType) {
if (get(queueState).isInterrupting)
return
queueState.update(s => { s.isInterrupting = true; return s; }) queueState.update(s => { s.isInterrupting = true; return s; })
await this.api.clearItems(type) await this.api.clearItems(type)
.then(() => { .then(() => {

View File

@@ -85,6 +85,27 @@
changed = false; changed = false;
} }
async function deleteEntry(entry: QueueUIEntry, event: MouseEvent) {
event.preventDefault();
event.stopImmediatePropagation()
// TODO support interrupting from multiple running items!
if (entry.status === "running") {
await app.interrupt();
}
else {
await app.deleteQueueItem(mode, entry.entry.promptID);
}
if (mode === "queue") {
_queuedEntries = []
_runningEntries = []
}
_entries = [];
changed = true;
}
async function clearQueue() { async function clearQueue() {
await app.clearQueue(mode); await app.clearQueue(mode);
@@ -188,17 +209,7 @@
} }
async function interrupt() { async function interrupt() {
if ($queueState.isInterrupting) await app.interrupt();
return
const app = (window as any).app as ComfyApp;
if (!app || !app.api)
return;
await app.api.interrupt()
.then(() => {
queueState.update(s => { s.isInterrupting = true; return s })
});
} }
let showModal = false; let showModal = false;
@@ -260,7 +271,7 @@
{#if mode === "history" && displayMode === "grid"} {#if mode === "history" && displayMode === "grid"}
<ComfyQueueGridDisplay entries={_entries} {showPrompt} {clearQueue} {mode} bind:gridColumns /> <ComfyQueueGridDisplay entries={_entries} {showPrompt} {clearQueue} {mode} bind:gridColumns />
{:else} {:else}
<ComfyQueueListDisplay entries={_entries} {showPrompt} {clearQueue} {mode} bind:imageSize /> <ComfyQueueListDisplay entries={_entries} {showPrompt} {clearQueue} {mode} {deleteEntry} bind:imageSize />
{/if} {/if}
{:else} {:else}
<div class="queue-empty"> <div class="queue-empty">

View File

@@ -7,6 +7,7 @@
export let entries: QueueUIEntry[] = []; export let entries: QueueUIEntry[] = [];
export let showPrompt: (entry: QueueUIEntry) => void; export let showPrompt: (entry: QueueUIEntry) => void;
export let clearQueue: () => void; export let clearQueue: () => void;
export let deleteEntry: (entry: QueueUIEntry, event: MouseEvent) => void;
export let mode: QueueItemType = "queue"; export let mode: QueueItemType = "queue";
export let imageSize: number = 40; export let imageSize: number = 40;
</script> </script>
@@ -29,6 +30,11 @@
<div class="list-entries {mode}-mode" style:--imageSize={imageSize}> <div class="list-entries {mode}-mode" style:--imageSize={imageSize}>
{#each entries as entry} {#each entries as entry}
<div class="list-entry {entry.status}" on:click={(e) => showPrompt(entry, e)}> <div class="list-entry {entry.status}" on:click={(e) => showPrompt(entry, e)}>
<button class="list-entry-delete-button secondary"
on:click={(e) => deleteEntry(entry, e)}
disabled={$queueState.isInterrupting}>
<span></span>
</button>
{#if entry.images.length > 0} {#if entry.images.length > 0}
<div class="list-entry-images" <div class="list-entry-images"
style="--cols: {Math.ceil(Math.sqrt(Math.min(entry.images.length, 4)))}" > style="--cols: {Math.ceil(Math.sqrt(Math.min(entry.images.length, 4)))}" >
@@ -128,8 +134,9 @@
border-top: 1px solid var(--table-border-color); border-top: 1px solid var(--table-border-color);
background: var(--panel-background-fill); background: var(--panel-background-fill);
max-height: 14rem; max-height: 14rem;
position: relative;
&:hover:not(:has(img:hover)) { &:hover:not(:has(img:hover)):not(:has(button:hover)) {
cursor: pointer; cursor: pointer;
background: var(--block-background-fill); background: var(--block-background-fill);
@@ -157,6 +164,34 @@
} }
} }
.list-entry-delete-button {
@include square-button;
display: flex;
position: absolute;
width: 1.4rem;
height: 1.4rem;
text-align: center;
align-items: center;
font-size: 10pt;
justify-content: center;
text-align: center;
top:0;
right:0.5rem;
margin: 0.5rem;
z-index: 1000000000;
opacity: 70%;
background: var(--neutral-700);
color: var(--neutral-300);
&:hover {
opacity: 100%;
color: var(--neutral-100);
}
}
.list-entry-rest { .list-entry-rest {
width: 100%; width: 100%;
position: relative; position: relative;

View File

@@ -17,6 +17,7 @@ type QueueStateOps = {
progressUpdated: (progress: Progress) => void progressUpdated: (progress: Progress) => void
getQueueEntry: (promptID: PromptID) => QueueEntry | null; getQueueEntry: (promptID: PromptID) => QueueEntry | null;
afterQueued: (workflowID: WorkflowInstID, promptID: PromptID, number: number, prompt: SerializedPromptInputsAll, extraData: any) => void afterQueued: (workflowID: WorkflowInstID, promptID: PromptID, number: number, prompt: SerializedPromptInputsAll, extraData: any) => void
queueItemDeleted: (type: QueueItemType, id: PromptID) => void;
queueCleared: (type: QueueItemType) => void; queueCleared: (type: QueueItemType) => void;
onExecuted: (promptID: PromptID, nodeID: ComfyNodeID, output: ComfyExecutionResult) => QueueEntry | null onExecuted: (promptID: PromptID, nodeID: ComfyNodeID, output: ComfyExecutionResult) => QueueEntry | null
} }
@@ -182,6 +183,39 @@ function findEntryInPending(promptID: PromptID): [number, QueueEntry | null, Wri
return [-1, null, null] return [-1, null, null]
} }
function deleteEntry(promptID: PromptID): boolean {
const state = get(store);
let index = get(state.queuePending).findIndex(e => e.promptID === promptID)
let found = false;
if (index !== -1) {
state.queuePending.update(qp => {
qp.splice(index, 1)
return qp;
})
found = true;
}
index = get(state.queueRunning).findIndex(e => e.promptID === promptID)
if (index !== -1) {
state.queueRunning.update(qr => {
qr.splice(index, 1)
return qr;
})
found = true;
}
index = get(state.queueCompleted).findIndex(e => e.entry.promptID === promptID)
if (index !== -1) {
state.queueCompleted.update(qc => {
qc.splice(index, 1)
return qc;
})
found = true;
}
return found;
}
function moveToRunning(index: number, queue: Writable<QueueEntry[]>) { function moveToRunning(index: number, queue: Writable<QueueEntry[]>) {
const state = get(store) const state = get(store)
@@ -295,7 +329,7 @@ function createNewQueueEntry(promptID: PromptID, number: number = -1, prompt: Se
return { return {
number, number,
queuedAt: new Date(), // Now queuedAt: new Date(), // Now
finishedAt: null, finishedAt: undefined,
promptID, promptID,
prompt, prompt,
extraData, extraData,
@@ -364,6 +398,18 @@ function onExecuted(promptID: PromptID, nodeID: ComfyNodeID, outputs: ComfyExecu
return entry_; return entry_;
} }
function queueItemDeleted(type: QueueItemType, id: PromptID) {
console.debug("[queueState] queueItemDeleted", type, id)
store.update(s => {
if (!deleteEntry(id)) {
console.error("[queueState] Queue item to delete not found!", type, id);
}
s.isInterrupting = false;
return s;
})
}
function queueCleared(type: QueueItemType) { function queueCleared(type: QueueItemType) {
console.debug("[queueState] queueCleared", type) console.debug("[queueState] queueCleared", type)
@@ -395,6 +441,7 @@ const queueStateStore: WritableQueueStateStore =
executionCached, executionCached,
executionError, executionError,
afterQueued, afterQueued,
queueItemDeleted,
queueCleared, queueCleared,
getQueueEntry, getQueueEntry,
onExecuted onExecuted