diff --git a/web/css/resolver-shell.css b/web/css/resolver-shell.css
index 7752412..8a68355 100644
--- a/web/css/resolver-shell.css
+++ b/web/css/resolver-shell.css
@@ -682,6 +682,11 @@
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22);
}
+/* The Missing Models preview already provides the panel's horizontal padding. */
+#model-resolver-modal .mr-missing-detail-pane .mr-download-progress-slot .mr-download-queue-item {
+ margin: 0;
+}
+
.mr-queue-item.mr-download-queue-item:last-child {
border-bottom: 1px solid var(--mr-border-strong);
}
diff --git a/web/resolver/actions/queue_methods.js b/web/resolver/actions/queue_methods.js
index b3648cb..0012708 100644
--- a/web/resolver/actions/queue_methods.js
+++ b/web/resolver/actions/queue_methods.js
@@ -1173,12 +1173,15 @@ export const queueMethods = {
});
},
- renderQueueDownloadsHtml(downloads) {
+ renderQueueDownloadsHtml(
+ downloads,
+ { wrap = true, showWorkflowAction = true, showWorkflowDetails = true } = {}
+ ) {
if (!downloads.length) {
return '
No active downloads.
';
}
- let html = '';
+ let html = wrap ? '
' : '';
for (const { downloadId, info } of downloads) {
const progress = typeof this.applyPendingDownloadStatus === 'function'
? this.applyPendingDownloadStatus(info, info.lastProgress || {})
@@ -1251,7 +1254,9 @@ export const queueMethods = {
);
html += actionButton('mr-download-queue-cancel', 'Cancel download', 'x');
html += actionButton('mr-download-queue-open-folder', 'Open download folder', 'folderOpen', !hasFolderAction);
- html += actionButton('mr-download-queue-switch-workflow', 'Switch to workflow', 'internalLink', !hasWorkflowAction);
+ if (showWorkflowAction) {
+ html += actionButton('mr-download-queue-switch-workflow', 'Switch to workflow', 'workflowBack', !hasWorkflowAction);
+ }
html += actionButton('mr-download-queue-more', 'More download actions', 'info', !contextModel);
html += `
`;
html += `
`;
@@ -1275,10 +1280,12 @@ export const queueMethods = {
html += ``;
html += ``;
html += ``;
- html += `Workflow${this.escapeHtml([workflowLabel, ...detailParts].filter(Boolean).join(' · '))}
`;
+ if (showWorkflowDetails) {
+ html += `Workflow${this.escapeHtml([workflowLabel, ...detailParts].filter(Boolean).join(' · '))}
`;
+ }
html += ``;
}
- html += '';
+ if (wrap) html += '';
return html;
},
diff --git a/web/resolver/actions/resolve_download_methods.js b/web/resolver/actions/resolve_download_methods.js
index 026f309..20a1a54 100644
--- a/web/resolver/actions/resolve_download_methods.js
+++ b/web/resolver/actions/resolve_download_methods.js
@@ -1091,29 +1091,59 @@ export const resolveDownloadMethods = {
if (event?.type === 'pointerdown') {
button._handledPointerAction = true;
}
- handler();
+ handler(event);
};
button.addEventListener('pointerdown', run);
button.addEventListener('click', run);
};
- progressDiv.querySelectorAll('.cancel-download-btn, .cancel-download-btn-pending').forEach(cancelBtn => {
+ progressDiv.querySelectorAll('.cancel-download-btn, .cancel-download-btn-pending, .mr-download-queue-cancel').forEach(cancelBtn => {
bindInstantAction(cancelBtn, () => {
const targetDownloadId = cancelBtn.dataset.downloadId || downloadId;
if (targetDownloadId) this.cancelDownload(targetDownloadId);
});
});
- progressDiv.querySelectorAll('.pause-download-btn').forEach(pauseBtn => {
+ progressDiv.querySelectorAll('.pause-download-btn, .mr-download-queue-pause').forEach(pauseBtn => {
bindInstantAction(pauseBtn, () => {
const targetDownloadId = pauseBtn.dataset.downloadId || downloadId;
if (targetDownloadId) this.pauseDownload(targetDownloadId);
});
});
- progressDiv.querySelectorAll('.resume-download-btn').forEach(resumeBtn => {
+ progressDiv.querySelectorAll('.resume-download-btn, .mr-download-queue-resume').forEach(resumeBtn => {
bindInstantAction(resumeBtn, () => {
const targetDownloadId = resumeBtn.dataset.downloadId || downloadId;
if (targetDownloadId) this.resumeDownload(targetDownloadId);
});
});
+ const getDownloadContext = (button) => {
+ const targetDownloadId = button?.dataset?.downloadId || downloadId;
+ const info = this.activeDownloads?.[targetDownloadId];
+ if (!targetDownloadId || !info) return null;
+ const progress = typeof this.applyPendingDownloadStatus === 'function'
+ ? this.applyPendingDownloadStatus(info, info.lastProgress || {})
+ : (info.lastProgress || {});
+ const workflowLabel = this.getDownloadWorkflowLabel?.(info) || 'Current workflow';
+ return this.getDownloadQueueContext?.(progress, info, workflowLabel, targetDownloadId)
+ || this.getDownloadFolderContext?.(progress, info)
+ || null;
+ };
+ progressDiv.querySelectorAll('.mr-download-queue-open-folder').forEach(folderBtn => {
+ bindInstantAction(folderBtn, () => {
+ const context = getDownloadContext(folderBtn);
+ if (context) this.openContainingFolder?.(context);
+ });
+ });
+ progressDiv.querySelectorAll('.mr-download-queue-switch-workflow').forEach(workflowBtn => {
+ bindInstantAction(workflowBtn, () => {
+ const context = getDownloadContext(workflowBtn);
+ if (context) this.switchToDownloadWorkflow?.(context);
+ });
+ });
+ progressDiv.querySelectorAll('.mr-download-queue-more').forEach(moreBtn => {
+ bindInstantAction(moreBtn, (event) => {
+ const item = moreBtn.closest('.mr-download-queue-item');
+ if (item) window.MLOpenContextMenu?.(event, item);
+ });
+ });
},
renderDownloadSnapshotMarkup(downloadId, snapshot) {
@@ -1123,51 +1153,22 @@ export const resolveDownloadMethods = {
const shouldRenderProgress = this.isDownloadProgressStatus(status, isActive);
if (shouldRenderProgress) {
- const canCancel = Boolean(downloadId);
- const backend = String(progress.download_backend || snapshot.downloadBackend || snapshot.download_backend || '').toLowerCase();
- const isAria2 = backend === 'aria2';
- const isPaused = status === 'paused';
- const presentation = this.getDownloadProgressPresentation(progress, { unknownTotal: 'Unknown' });
- const {
- percent,
- downloadedText: downloaded,
- totalText: total,
- progressMeta,
- percentLabel,
- logicalDownloadedText: logicalDownloaded,
- logicalTotalText: logicalTotal,
- } = presentation;
- const leftText = presentation.isFinalizing
- ? `Finalizing file: ${logicalDownloaded} / ${logicalTotal}`
- : (presentation.totalSize
- ? `${downloaded} / ${total} (${percentLabel}%)${isPaused ? ' - Paused' : ''}`
- : 'Connecting...');
- let actionClass = canCancel ? 'cancel-download-btn mr-btn mr-btn-danger mr-btn-sm' : '';
- let actionText = canCancel ? 'Cancel' : '';
- let actionsHtml = '';
- if (canCancel && isAria2 && isPaused) {
- actionClass = 'resume-download-btn mr-btn mr-btn-primary mr-btn-sm';
- actionText = 'Resume';
- } else if (canCancel && isAria2 && status === 'downloading') {
- actionClass = 'pause-download-btn mr-btn mr-btn-secondary mr-btn-sm';
- actionText = 'Pause';
- }
- if (canCancel && isAria2 && (isPaused || status === 'downloading')) {
- const safeDownloadId = this.escapeHtml(String(downloadId));
- const toggleButton = isPaused
- ? ``
- : ``;
- actionsHtml = `${toggleButton}`;
- }
- return this.renderProgressWithAction({
- percent,
- leftText,
- rightText: progressMeta,
- actionClass,
- actionText,
- actionDataAttr: canCancel ? `data-download-id="${downloadId}"` : '',
- actionsHtml,
- contextMenuModel: this.getDownloadFolderContext(progress, snapshot)
+ const info = {
+ ...snapshot,
+ missing: snapshot.missing || {},
+ lastProgress: progress,
+ lastStatus: status,
+ filename: progress.filename || snapshot.filename || 'Download',
+ category: snapshot.category || progress.category || '',
+ downloadBackend: progress.download_backend || snapshot.downloadBackend || snapshot.download_backend || '',
+ downloadDirectory: progress.directory || snapshot.downloadDirectory || '',
+ downloadPath: progress.path || snapshot.downloadPath || '',
+ workflowLabel: snapshot.workflowLabel || snapshot.workflow_label || 'Current workflow'
+ };
+ return this.renderQueueDownloadsHtml([{ downloadId, info }], {
+ wrap: false,
+ showWorkflowAction: false,
+ showWorkflowDetails: false
});
}
diff --git a/web/resolver/resolver_dialog.js b/web/resolver/resolver_dialog.js
index 4a61876..c5e4871 100644
--- a/web/resolver/resolver_dialog.js
+++ b/web/resolver/resolver_dialog.js
@@ -222,7 +222,7 @@ export class ResolverManagerDialog extends ComfyDialog {
onclick: () => this.handleContextMenuAction('switchWorkflow')
}, [
$el("span.mr-context-menu-item-icon", {
- innerHTML: getSvgIcon('internalLink', 'currentColor', 'mr-context-menu-item-svg')
+ innerHTML: getSvgIcon('workflowBack', 'currentColor', 'mr-context-menu-item-svg')
}),
$el("span", { textContent: "Switch to Workflow" })
]),
diff --git a/web/utils/icon_utils.js b/web/utils/icon_utils.js
index 14de397..49ecc03 100644
--- a/web/utils/icon_utils.js
+++ b/web/utils/icon_utils.js
@@ -31,8 +31,9 @@ const SVG_ICONS = {
shield: ``,
copy: ``,
externalLink: ``,
- moreCircle: ``,
+ moreCircle: ``,
internalLink: ``,
+ workflowBack: ``,
database: ``,
wrench: ``,
comfyui: ``,