diff --git a/web/linker.js b/web/linker.js
index f1228d4..cf68098 100644
--- a/web/linker.js
+++ b/web/linker.js
@@ -262,6 +262,56 @@ class LinkerManagerDialog extends ComfyDialog {
return html;
}
+ formatSearchResultMeta(result = {}, options = {}) {
+ const filename = options.filename || result.filename || '';
+ const secondaryText = options.secondaryText || '';
+ const confidenceValue = result.confidence;
+ const confidenceDisplay = typeof confidenceValue === 'number'
+ ? `${Math.round(confidenceValue)}% match`
+ : '';
+ const sizeDisplay = result.size
+ ? (typeof result.size === 'number' ? this.formatBytes(result.size) : result.size)
+ : '';
+
+ let html = `
`;
+ if (filename) {
+ html += `${filename}`;
+ }
+ if (confidenceDisplay) {
+ html += ` ${confidenceDisplay}`;
+ }
+ if (sizeDisplay) {
+ html += ` [${sizeDisplay}]`;
+ }
+ if (secondaryText) {
+ html += ` ${secondaryText}`;
+ }
+ html += `
`;
+ return html;
+ }
+
+ renderOnlineSearchResultCard({
+ statusClass,
+ title,
+ result,
+ filename,
+ secondaryText = '',
+ actionHtml = '',
+ topLineHtml = ''
+ }) {
+ let html = ``;
+ html += `
${title}`;
+ if (topLineHtml) {
+ html += topLineHtml;
+ }
+ html += this.formatSearchResultMeta(result, { filename, secondaryText });
+ if (actionHtml) {
+ html += `
${actionHtml}
`;
+ }
+ html += `
`;
+ return html;
+ }
+
buildContextMenuModelData(model = {}, fallbackName = '') {
const resolvedPath = model.path || model.resolved_path || '';
const filename = model.filename || fallbackName || resolvedPath.split(/[\/\\]/).pop() || '';
@@ -6011,53 +6061,45 @@ class LinkerManagerDialog extends ComfyDialog {
// Popular models result (highest priority)
if (popular) {
- html += ``;
- html += `
Found in Popular Models`;
- html += `
`;
- html += ``;
- html += `
`;
+ const popularFilename = popular.filename || missing.original_path?.split('/').pop()?.split('\\').pop() || '';
+ const actionHtml = ``;
+ html += this.renderOnlineSearchResultCard({
+ statusClass: 'ml-status-success',
+ title: 'Found in Popular Models',
+ result: popular,
+ filename: popularFilename,
+ secondaryText: popular.name || '',
+ actionHtml
+ });
}
// Model list result (ComfyUI Manager database with fuzzy matching)
if (modelListResult && modelListResult.url) {
- const confidence = modelListResult.confidence ? ` (${modelListResult.confidence}%)` : '';
const matchType = modelListResult.match_type === 'exact' ? 'Exact match' : 'Similar model';
const statusClass = modelListResult.match_type === 'exact' ? 'ml-status-success' : 'ml-status-info';
-
- html += ``;
- html += `
${matchType} in Model Database${confidence}`;
- html += `
`;
- html += `${modelListResult.filename}`;
- if (modelListResult.name) {
- html += ` ${modelListResult.name}`;
- }
- if (modelListResult.size) {
- html += ` [${modelListResult.size}]`;
- }
- html += `
`;
- html += `
`;
- html += ``;
- html += `
`;
+ const actionHtml = ``;
+ html += this.renderOnlineSearchResultCard({
+ statusClass,
+ title: `${matchType} in Model Database`,
+ result: modelListResult,
+ filename: modelListResult.filename,
+ secondaryText: modelListResult.name || '',
+ actionHtml
+ });
}
// HuggingFace result
if (hfResult && hfResult.url) {
const hfRepo = hfResult.repo_id || hfResult.repo || '';
- html += ``;
- html += `
Found on HuggingFace`;
- html += `
`;
- html += `${hfResult.filename} `;
- html += `${hfRepo}`;
- html += `
`;
- html += `
`;
- html += ``;
- html += `
`;
+ const actionHtml = ``;
+ html += this.renderOnlineSearchResultCard({
+ statusClass: 'ml-status-info',
+ title: 'Found on HuggingFace',
+ result: hfResult,
+ filename: hfResult.filename,
+ secondaryText: hfRepo,
+ actionHtml
+ });
}
// CivitAI result
@@ -6067,36 +6109,17 @@ class LinkerManagerDialog extends ComfyDialog {
const downloadFilename = missing.civitai_info?.expected_filename || civitaiResult.filename || civitaiResult.name;
// Build display name with version if available
const modelName = missing.civitai_info?.version_name ? `${missing.civitai_info.model_name} v${missing.civitai_info.version_name}` : (civitaiResult.name || 'Model');
- const confidenceDisplay = typeof civitaiResult.confidence === 'number'
- ? `${Math.round(civitaiResult.confidence)}% match`
- : '';
- const sizeDisplay = civitaiResult.size
- ? (typeof civitaiResult.size === 'number'
- ? this.formatBytes(civitaiResult.size)
- : civitaiResult.size)
- : '';
- html += ``;
- html += `
Found on CivitAI`;
- html += `
`;
- // Model name as clickable button/link
- html += ` `;
- html += `${civitaiResult.type || ''}`;
- html += `
`;
- html += `
`;
- html += `${downloadFilename}`;
- if (confidenceDisplay) {
- html += ` ${confidenceDisplay}`;
- }
- if (sizeDisplay) {
- html += ` [${sizeDisplay}]`;
- }
- html += `
`;
- html += `
`;
- // Download button - use expected_filename from URN resolution
- html += ``;
- html += `
`;
+ const topLineHtml = ` ${civitaiResult.type || ''}
`;
+ const actionHtml = ``;
+ html += this.renderOnlineSearchResultCard({
+ statusClass: 'ml-status-warning',
+ title: 'Found on CivitAI',
+ result: civitaiResult,
+ filename: downloadFilename,
+ secondaryText: '',
+ topLineHtml,
+ actionHtml
+ });
}
html += '';