Delete queue/history item
This commit is contained in:
@@ -331,7 +331,7 @@ export default class ComfyAPI {
|
||||
* @param {string} type The type of item to delete, queue or history
|
||||
* @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] });
|
||||
}
|
||||
|
||||
|
||||
@@ -509,7 +509,35 @@ export default class ComfyApp {
|
||||
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) {
|
||||
if (get(queueState).isInterrupting)
|
||||
return
|
||||
|
||||
queueState.update(s => { s.isInterrupting = true; return s; })
|
||||
await this.api.clearItems(type)
|
||||
.then(() => {
|
||||
|
||||
@@ -85,6 +85,27 @@
|
||||
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() {
|
||||
await app.clearQueue(mode);
|
||||
|
||||
@@ -188,17 +209,7 @@
|
||||
}
|
||||
|
||||
async function interrupt() {
|
||||
if ($queueState.isInterrupting)
|
||||
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 })
|
||||
});
|
||||
await app.interrupt();
|
||||
}
|
||||
|
||||
let showModal = false;
|
||||
@@ -260,7 +271,7 @@
|
||||
{#if mode === "history" && displayMode === "grid"}
|
||||
<ComfyQueueGridDisplay entries={_entries} {showPrompt} {clearQueue} {mode} bind:gridColumns />
|
||||
{:else}
|
||||
<ComfyQueueListDisplay entries={_entries} {showPrompt} {clearQueue} {mode} bind:imageSize />
|
||||
<ComfyQueueListDisplay entries={_entries} {showPrompt} {clearQueue} {mode} {deleteEntry} bind:imageSize />
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="queue-empty">
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
export let entries: QueueUIEntry[] = [];
|
||||
export let showPrompt: (entry: QueueUIEntry) => void;
|
||||
export let clearQueue: () => void;
|
||||
export let deleteEntry: (entry: QueueUIEntry, event: MouseEvent) => void;
|
||||
export let mode: QueueItemType = "queue";
|
||||
export let imageSize: number = 40;
|
||||
</script>
|
||||
@@ -29,6 +30,11 @@
|
||||
<div class="list-entries {mode}-mode" style:--imageSize={imageSize}>
|
||||
{#each entries as entry}
|
||||
<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}
|
||||
<div class="list-entry-images"
|
||||
style="--cols: {Math.ceil(Math.sqrt(Math.min(entry.images.length, 4)))}" >
|
||||
@@ -128,8 +134,9 @@
|
||||
border-top: 1px solid var(--table-border-color);
|
||||
background: var(--panel-background-fill);
|
||||
max-height: 14rem;
|
||||
position: relative;
|
||||
|
||||
&:hover:not(:has(img:hover)) {
|
||||
&:hover:not(:has(img:hover)):not(:has(button:hover)) {
|
||||
cursor: pointer;
|
||||
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 {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
@@ -17,6 +17,7 @@ type QueueStateOps = {
|
||||
progressUpdated: (progress: Progress) => void
|
||||
getQueueEntry: (promptID: PromptID) => QueueEntry | null;
|
||||
afterQueued: (workflowID: WorkflowInstID, promptID: PromptID, number: number, prompt: SerializedPromptInputsAll, extraData: any) => void
|
||||
queueItemDeleted: (type: QueueItemType, id: PromptID) => void;
|
||||
queueCleared: (type: QueueItemType) => void;
|
||||
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]
|
||||
}
|
||||
|
||||
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[]>) {
|
||||
const state = get(store)
|
||||
|
||||
@@ -295,7 +329,7 @@ function createNewQueueEntry(promptID: PromptID, number: number = -1, prompt: Se
|
||||
return {
|
||||
number,
|
||||
queuedAt: new Date(), // Now
|
||||
finishedAt: null,
|
||||
finishedAt: undefined,
|
||||
promptID,
|
||||
prompt,
|
||||
extraData,
|
||||
@@ -364,6 +398,18 @@ function onExecuted(promptID: PromptID, nodeID: ComfyNodeID, outputs: ComfyExecu
|
||||
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) {
|
||||
console.debug("[queueState] queueCleared", type)
|
||||
|
||||
@@ -395,6 +441,7 @@ const queueStateStore: WritableQueueStateStore =
|
||||
executionCached,
|
||||
executionError,
|
||||
afterQueued,
|
||||
queueItemDeleted,
|
||||
queueCleared,
|
||||
getQueueEntry,
|
||||
onExecuted
|
||||
|
||||
Reference in New Issue
Block a user