feat: improve download category inference and auto-fill for download targets

This commit is contained in:
Dariusz L
2026-06-20 01:40:17 +02:00
parent 1a4156f00d
commit 7a670e3b71
4 changed files with 325 additions and 42 deletions
File diff suppressed because one or more lines are too long
@@ -1421,7 +1421,7 @@ export const resolveDownloadMethods = {
*/
async searchOnline(missing, { workflowKey = this.getWorkflowScopedQueueKey(), forceSearch = false } = {}) {
let filename = missing.original_path?.split('/').pop()?.split('\\').pop() || '';
let category = missing.category || '';
let category = missing.category || this.getNodeTypeDownloadCategory?.(missing.node_type) || '';
const state = this.getSearchStateForWorkflow(workflowKey, missing);
const missingSearchKey = this.getMissingSearchKey(missing);
const backgroundJobKey = this.getBackgroundSearchJobKey(workflowKey, missingSearchKey);
@@ -2083,6 +2083,7 @@ export const resolveDownloadMethods = {
if (popular) {
const popularFilename = popular.filename || missing.original_path?.split('/').pop()?.split('\\').pop() || '';
const missingCategory = this.getMissingDownloadCategory?.(missing, 'checkpoints') || missing.category || 'checkpoints';
const popularSize = popular.size
|| (
modelListResult
@@ -2101,13 +2102,14 @@ export const resolveDownloadMethods = {
size: this.formatSearchResultSize({ ...popular, size: popularSize }),
downloadUrl: popular.url,
downloadFilename: popularFilename,
category: popular.directory || missing.category,
category: popular.directory || missingCategory,
openUrl: this.getModelCardUrl(popular.url),
searchedAt: this.getSearchResultTimestamp(popular)
});
}
if (modelListResult && modelListResult.url) {
const missingCategory = this.getMissingDownloadCategory?.(missing, 'checkpoints') || missing.category || 'checkpoints';
addRow({
sourceKey: 'model-list',
sourceLabel: 'Local Database',
@@ -2118,7 +2120,7 @@ export const resolveDownloadMethods = {
size: this.formatSearchResultSize(modelListResult),
downloadUrl: modelListResult.url,
downloadFilename: modelListResult.filename,
category: modelListResult.directory || missing.category,
category: modelListResult.directory || missingCategory,
openUrl: this.getModelCardUrl(modelListResult.url),
searchedAt: this.getSearchResultTimestamp(modelListResult)
});
@@ -2127,6 +2129,7 @@ export const resolveDownloadMethods = {
if (hfResult && hfResult.url) {
const hfRepo = hfResult.repo_id || hfResult.repo || '';
const hfModelUrl = hfRepo ? `https://huggingface.co/${hfRepo}` : this.getModelCardUrl(hfResult.url);
const missingCategory = this.getMissingDownloadCategory?.(missing, 'checkpoints') || missing.category || 'checkpoints';
addRow({
sourceKey: 'huggingface',
sourceLabel: 'HuggingFace',
@@ -2137,7 +2140,7 @@ export const resolveDownloadMethods = {
size: this.formatSearchResultSize(hfResult),
downloadUrl: hfResult.url,
downloadFilename: hfResult.filename,
category: missing.category,
category: missingCategory,
openUrl: hfModelUrl,
searchedAt: this.getSearchResultTimestamp(hfResult)
});
@@ -2146,6 +2149,10 @@ export const resolveDownloadMethods = {
if (civarchiveResult && civarchiveResult.download_url) {
const archiveFilename = civarchiveResult.filename || missing.original_path?.split('/').pop()?.split('\\').pop() || '';
const archiveName = civarchiveResult.name || archiveFilename || 'Model';
const archiveCategory = this.getSourceResultDownloadCategory?.(
civarchiveResult,
this.getMissingDownloadCategory?.(missing, 'checkpoints') || 'checkpoints'
) || this.getMissingDownloadCategory?.(missing, 'checkpoints') || 'checkpoints';
const archiveSecondary = [
archiveName && archiveName !== archiveFilename ? archiveFilename : '',
civarchiveResult.platform || '',
@@ -2162,14 +2169,14 @@ export const resolveDownloadMethods = {
size: this.formatSearchResultSize(civarchiveResult),
downloadUrl: civarchiveResult.download_url,
downloadFilename: archiveFilename,
category: missing.category,
category: archiveCategory,
openUrl: civarchiveResult.url,
searchedAt: this.getSearchResultTimestamp(civarchiveResult),
detailsContext: {
...civarchiveResult,
details_source: 'civarchive',
missing_key: this.getMissingModelKey(missing),
category: missing.category
category: archiveCategory
}
});
}
@@ -2177,6 +2184,10 @@ export const resolveDownloadMethods = {
if (loraManagerArchiveResult && loraManagerArchiveResult.download_url) {
const archiveFilename = loraManagerArchiveResult.filename || missing.original_path?.split('/').pop()?.split('\\').pop() || '';
const archiveName = loraManagerArchiveResult.name || archiveFilename;
const archiveCategory = this.getSourceResultDownloadCategory?.(
loraManagerArchiveResult,
this.getMissingDownloadCategory?.(missing, 'loras') || 'loras'
) || this.getMissingDownloadCategory?.(missing, 'loras') || 'loras';
addRow({
sourceKey: 'lora-archive',
sourceLabel: 'LoRA Archive',
@@ -2188,7 +2199,7 @@ export const resolveDownloadMethods = {
size: this.formatSearchResultSize(loraManagerArchiveResult),
downloadUrl: loraManagerArchiveResult.download_url || '',
downloadFilename: archiveFilename,
category: missing.category,
category: archiveCategory,
openUrl: loraManagerArchiveResult.url || this.getModelCardUrl(loraManagerArchiveResult.download_url),
searchedAt: this.getSearchResultTimestamp(loraManagerArchiveResult),
detailsContext: {
@@ -2196,15 +2207,19 @@ export const resolveDownloadMethods = {
source: 'lora_manager_archive',
details_source: 'lora_manager_archive',
missing_key: this.getMissingModelKey(missing),
category: missing.category
category: archiveCategory
}
});
}
if (civitaiResult && civitaiResult.download_url) {
const modelUrl = civitaiResult.url || (civitaiResult.model_id ? `https://civitai.com/models/${civitaiResult.model_id}${civitaiResult.version_id ? `?modelVersionId=${civitaiResult.version_id}` : ''}` : '');
const downloadFilename = missing.civitai_info?.expected_filename || civitaiResult.filename || civitaiResult.name;
const modelName = missing.civitai_info?.model_name || civitaiResult.name || downloadFilename || 'Model';
const downloadFilename = civitaiResult.filename || missing.civitai_info?.expected_filename || civitaiResult.name;
const modelName = civitaiResult.name || missing.civitai_info?.model_name || downloadFilename || 'Model';
const civitaiCategory = this.getSourceResultDownloadCategory?.(
civitaiResult,
this.getMissingDownloadCategory?.(missing, 'checkpoints') || 'checkpoints'
) || this.getMissingDownloadCategory?.(missing, 'checkpoints') || 'checkpoints';
const civitaiSecondary = [
civitaiResult.type || '',
civitaiResult.base_model || missing.civitai_info?.base_model || ''
@@ -2213,14 +2228,14 @@ export const resolveDownloadMethods = {
sourceKey: 'civitai',
sourceLabel: 'CivitAI',
model: modelName,
version: missing.civitai_info?.version_name || civitaiResult.version_name || '',
version: civitaiResult.version_name || missing.civitai_info?.version_name || '',
filename: downloadFilename,
secondary: civitaiSecondary,
match: this.getSearchResultMatchDisplay(civitaiResult),
size: this.formatSearchResultSize(civitaiResult),
downloadUrl: civitaiResult.download_url,
downloadFilename,
category: missing.category,
category: civitaiCategory,
openUrl: modelUrl,
searchedAt: this.getSearchResultTimestamp(civitaiResult),
detailsContext: {
@@ -2229,7 +2244,7 @@ export const resolveDownloadMethods = {
filename: downloadFilename,
details_source: 'civitai',
missing_key: this.getMissingModelKey(missing),
category: missing.category
category: civitaiCategory
}
});
}
+286 -22
View File
@@ -109,6 +109,8 @@ export const downloadTargetMethods = {
checkpoint: 'checkpoints',
lora: 'loras',
embedding: 'embeddings',
textualinversion: 'embeddings',
textual_inversion: 'embeddings',
upscaler: 'upscale_models',
unet: 'diffusion_models',
diffusion_model: 'diffusion_models',
@@ -138,6 +140,128 @@ export const downloadTargetMethods = {
return categoryMap[token] || token || 'checkpoints';
},
getKnownDownloadCategorySet() {
const directories = this.downloadDirectories || {};
return new Set([
...Object.keys(directories),
...this.getDefaultDownloadCategoryKeys()
].map(key => this.normalizeDownloadCategory(key)).filter(Boolean));
},
getSourceResultDownloadCategory(source = {}, fallbackCategory = '') {
const sourceData = source && typeof source === 'object' ? source : {};
const knownCategories = this.getKnownDownloadCategorySet();
const candidates = [
sourceData.model_type,
sourceData.modelType,
sourceData.type,
sourceData.category,
sourceData.directory,
fallbackCategory
];
for (const candidate of candidates) {
if (candidate === undefined || candidate === null || String(candidate).trim() === '') continue;
const normalized = this.normalizeDownloadCategory(candidate);
if (normalized && knownCategories.has(normalized)) {
return normalized;
}
}
const defaultCategory = this.normalizeDownloadCategory('checkpoints');
return knownCategories.has(defaultCategory)
? defaultCategory
: this.normalizeDownloadCategory(fallbackCategory || 'checkpoints');
},
getNodeTypeDownloadCategory(nodeType = '') {
const normalizedNodeType = String(nodeType || '').trim();
const exactMap = {
CheckpointLoaderSimple: 'checkpoints',
CheckpointLoader: 'checkpoints',
UNETLoader: 'diffusion_models',
UNETLoaderAdvanced: 'diffusion_models',
VAELoader: 'vae',
VAELoaderKJ: 'vae',
LoraLoader: 'loras',
LoraLoaderModelOnly: 'loras',
LoraLoaderBypass: 'loras',
LoraLoaderBypassModelOnly: 'loras',
LoraLoaderV2: 'loras',
ControlNetLoader: 'controlnet',
CLIPLoader: 'text_encoders',
DualCLIPLoader: 'text_encoders',
TripleCLIPLoader: 'text_encoders',
UpscaleModelLoader: 'upscale_models',
LTXVAudioVAELoader: 'checkpoints',
LowVRAMAudioVAELoader: 'checkpoints'
};
if (exactMap[normalizedNodeType]) {
return exactMap[normalizedNodeType];
}
const token = normalizedNodeType.toLowerCase();
if (!token) return '';
if (token.includes('lora')) return 'loras';
if (token.includes('vae')) return 'vae';
if (token.includes('checkpoint')) return 'checkpoints';
if (token.includes('unet') || token.includes('diffusion')) return 'diffusion_models';
if (token.includes('controlnet')) return 'controlnet';
if (token.includes('upscale')) return 'upscale_models';
if (token.includes('embedding') || token.includes('textualinversion')) return 'embeddings';
if (token.includes('clip')) return 'text_encoders';
return '';
},
getMissingNodeTypeDownloadCategory(missing = {}) {
return this.getNodeTypeDownloadCategory(missing.locate_node_type)
|| this.getNodeTypeDownloadCategory(missing.promoted_inner_node_type)
|| this.getNodeTypeDownloadCategory(missing.node_type)
|| '';
},
shouldPreserveSavedDownloadCategory(missing = {}, saved = {}, inferredCategory = '') {
if (!saved?.categoryTouched) return false;
if (saved.category === undefined || saved.category === null || String(saved.category).trim() === '') return false;
const savedCategory = this.normalizeDownloadCategory(saved.category || '');
if (!savedCategory) return false;
const nodeCategory = this.getMissingNodeTypeDownloadCategory(missing);
const rawMissingCategory = missing.category || missing.directory || '';
const missingCategory = rawMissingCategory ? this.normalizeDownloadCategory(rawMissingCategory) : '';
const strongInferredCategory = nodeCategory || (missingCategory && missingCategory !== 'checkpoints' ? missingCategory : '');
const inferred = this.normalizeDownloadCategory(inferredCategory || nodeCategory || '');
if (
savedCategory === 'checkpoints'
&& inferred
&& inferred !== 'checkpoints'
&& strongInferredCategory
) {
return false;
}
return true;
},
getMissingDownloadCategory(missing = {}, fallbackCategory = 'checkpoints') {
const knownCategories = this.getKnownDownloadCategorySet();
const candidates = [
this.getMissingNodeTypeDownloadCategory(missing),
missing.category,
missing.directory,
fallbackCategory
];
for (const candidate of candidates) {
if (candidate === undefined || candidate === null || String(candidate).trim() === '') continue;
const normalized = this.normalizeDownloadCategory(candidate);
if (normalized && knownCategories.has(normalized)) {
return normalized;
}
}
return this.normalizeDownloadCategory(fallbackCategory || 'checkpoints');
},
getCategoryDisplayName(category = '') {
category = this.normalizeDownloadCategory(category);
const displayNames = {
@@ -845,8 +969,19 @@ export const downloadTargetMethods = {
},
getDownloadTargetKey(missing = {}) {
return this.getMissingModelKey?.(missing)
const baseKey = this.getMissingModelKey?.(missing)
|| `${missing.node_id}:${missing.widget_index}:${missing.subgraph_id || ''}:${missing.is_top_level !== false ? 'T' : 'F'}`;
const modelIdentity = [
missing.original_path,
missing.expected_filename,
missing.name,
missing.workflow_url
].find(value => value !== undefined && value !== null && String(value).trim());
if (!modelIdentity) {
return baseKey;
}
const identityKey = encodeURIComponent(String(modelIdentity).trim()).slice(0, 240);
return `${baseKey}:${identityKey}`;
},
getSavedDownloadTargetSelection(missing = {}) {
@@ -874,10 +1009,39 @@ export const downloadTargetMethods = {
const state = this.searchResultCache?.get(this.getMissingSearchKey?.(missing));
const results = state?.results || {};
const merged = {};
const hasObjectValues = (value) => (
value
&& typeof value === 'object'
&& !Array.isArray(value)
&& Object.keys(value).length > 0
);
const mergeSuggestionValue = (key, value) => {
if (value === undefined || value === null || value === '') return;
if (Array.isArray(value)) {
if (value.length > 0) {
merged[key] = value;
}
return;
}
if (typeof value === 'object') {
if (hasObjectValues(value)) {
merged[key] = value;
}
return;
}
merged[key] = value;
};
for (const source of ['popular', 'model_list', 'huggingface', 'civitai', 'civarchive', 'lora_manager_archive']) {
const result = this.getFirstSearchResult(results[source]);
if (result && typeof result === 'object') {
Object.assign(merged, result);
Object.entries(result).forEach(([key, value]) => {
mergeSuggestionValue(key, value);
});
merged.category = this.getSourceResultDownloadCategory(
result,
merged.category || missing.category || ''
);
}
}
return merged;
@@ -961,7 +1125,21 @@ export const downloadTargetMethods = {
const civitaiInfo = missing.civitai_info || {};
const civitaiSearch = missing.civitai_search_result || {};
const searchSuggestion = this.getCachedSearchSuggestionData(missing);
const localMatches = Array.isArray(missing.matches) ? missing.matches : [];
const bestLocalMatch = localMatches
.filter(match => match && typeof match === 'object')
.sort((a, b) => Number(b.confidence || 0) - Number(a.confidence || 0))[0] || null;
const bestLocalModel = bestLocalMatch?.model || {};
const bestLocalPath = bestLocalModel.relative_path
|| bestLocalModel.path
|| bestLocalMatch?.path
|| '';
const bestLocalFilename = bestLocalModel.filename
|| bestLocalMatch?.filename
|| '';
const rawValues = [
bestLocalPath,
bestLocalFilename,
source.filename,
source.name,
source.model_name,
@@ -1070,36 +1248,96 @@ export const downloadTargetMethods = {
|| findMatch((entry, candidate) => entry.normalizedSegments.some(segment => segment === candidate.normalized));
},
getTemplateSubfolderSuggestionFromMetadata(missing = {}, category = '') {
const normalizedCategory = this.normalizeDownloadCategory(category);
const template = this.getDownloadPathTemplates()[normalizedCategory] || '';
if (!template) return null;
const metadata = this.getDownloadPathMetadata(missing, { category: normalizedCategory });
const tags = Array.isArray(metadata.tags)
? metadata.tags.filter(Boolean)
: String(metadata.tags || '').split(/[,;]+/).map(tag => tag.trim()).filter(Boolean);
const creator = metadata.creator && typeof metadata.creator === 'object'
? (metadata.creator.username || metadata.creator.name || '')
: (typeof metadata.creator === 'string' ? metadata.creator : '');
const author = metadata.author
|| creator
|| (metadata.repo_id && String(metadata.repo_id).includes('/') ? String(metadata.repo_id).split('/')[0] : '');
const modelName = metadata.model_name
|| metadata.name
|| metadata.filename?.replace(/\.[^.]+$/, '')
|| '';
const versionName = metadata.version_name || metadata.versionName || metadata.version || '';
const requirements = [
[template.includes('{base_model}'), Boolean(metadata.base_model || metadata.baseModel)],
[template.includes('{first_tag}'), tags.length > 0],
[template.includes('{author}'), Boolean(author)],
[template.includes('{model_name}'), Boolean(modelName)],
[template.includes('{version_name}'), Boolean(versionName)]
];
if (requirements.some(([required, available]) => required && !available)) {
return null;
}
const value = this.calculateDownloadPathTemplateSubfolder(normalizedCategory, metadata);
return value
? { value, label: `${value} (metadata)`, baseDirectory: '' }
: null;
},
getSuggestedDownloadCategory(missing = {}, fallbackCategory = 'checkpoints') {
const searchSuggestion = this.getCachedSearchSuggestionData(missing);
return this.getSourceResultDownloadCategory(
searchSuggestion || {},
this.getMissingDownloadCategory(missing, fallbackCategory || 'checkpoints')
);
},
getSuggestedDownloadSubfolder(missing, category, folders = []) {
const mode = this.getDownloadPathMode();
if (mode === 'manual') {
return null;
}
if (mode === 'template') {
const value = this.calculateDownloadPathTemplateSubfolder(
category,
this.getDownloadPathMetadata(missing, { category })
);
return value
? { value, label: `${value} (template)`, baseDirectory: '' }
: null;
}
const folderEntries = this.getFolderSuggestionEntries(folders);
if (mode === 'template') {
return this.getTemplateSubfolderSuggestionFromMetadata(missing, category)
|| this.getSuggestedLoraSubfolder(missing, category, folderEntries)
|| this.getSuggestedExistingSubfolderByModelName(missing, folderEntries);
}
return this.getSuggestedLoraSubfolder(missing, category, folderEntries)
|| this.getSuggestedExistingSubfolderByModelName(missing, folderEntries);
|| this.getSuggestedExistingSubfolderByModelName(missing, folderEntries)
|| this.getTemplateSubfolderSuggestionFromMetadata(missing, category);
},
async applySuggestedDownloadSubfolder(missing, categoryEl, subfolderEl) {
if (!this.isAutoFillSubfolderEnabled()) return;
if (!categoryEl || !subfolderEl || subfolderEl.value.trim()) return;
if (!categoryEl || !subfolderEl) return;
const saved = this.getSavedDownloadTargetSelection(missing);
if (saved?.subfolderTouched) return;
const category = this.normalizeDownloadCategory(this.getDropdownValue(categoryEl));
let category = this.normalizeDownloadCategory(this.getDropdownValue(categoryEl));
const suggestedCategory = this.getSuggestedDownloadCategory(missing, category);
const preserveSavedCategory = this.shouldPreserveSavedDownloadCategory(missing, saved, category);
if (suggestedCategory && suggestedCategory !== category && !preserveSavedCategory) {
category = suggestedCategory;
this.setDropdownValue(categoryEl, category, this.getCategoryDisplayName(category));
subfolderEl.value = '';
subfolderEl.dataset.baseDirectory = '';
this.saveDownloadTargetSelection(missing, {
category,
subfolder: '',
subfolderBaseDirectory: '',
categoryTouched: false,
subfolderTouched: false
});
this.syncDownloadTargetFolderContext(categoryEl, subfolderEl);
}
await this.ensureDownloadSubfoldersLoaded(category);
const latestSaved = this.getSavedDownloadTargetSelection(missing);
if (latestSaved?.subfolderTouched || subfolderEl.value.trim()) return;
if (latestSaved?.subfolderTouched) return;
const folders = this.getAvailableSubfolders(category);
const suggestion = this.getSuggestedDownloadSubfolder(missing, category, folders);
@@ -1119,21 +1357,38 @@ export const downloadTargetMethods = {
async forceSuggestedDownloadSubfolder(missing, categoryEl, subfolderEl) {
if (!categoryEl || !subfolderEl) return;
const category = this.normalizeDownloadCategory(this.getDropdownValue(categoryEl));
const saved = this.getSavedDownloadTargetSelection(missing);
const originalCategory = this.normalizeDownloadCategory(this.getDropdownValue(categoryEl));
let category = originalCategory;
const suggestedCategory = this.getSuggestedDownloadCategory(missing, category);
const preserveSavedCategory = this.shouldPreserveSavedDownloadCategory(missing, saved, originalCategory);
if (suggestedCategory && suggestedCategory !== category && !preserveSavedCategory) {
category = suggestedCategory;
}
await this.ensureDownloadSubfoldersLoaded(category);
const folders = this.getAvailableSubfolders(category);
const suggestion = this.getSuggestedDownloadSubfolder(missing, category, folders);
let folders = this.getAvailableSubfolders(category);
let suggestion = this.getSuggestedDownloadSubfolder(missing, category, folders);
if (!suggestion && suggestedCategory && suggestedCategory !== category) {
category = suggestedCategory;
await this.ensureDownloadSubfoldersLoaded(category);
folders = this.getAvailableSubfolders(category);
suggestion = this.getSuggestedDownloadSubfolder(missing, category, folders);
}
if (!suggestion) {
this.showNotification?.('No subfolder suggestion available for this model.', 'info');
return;
}
this.setDropdownValue(categoryEl, category, this.getCategoryDisplayName(category));
subfolderEl.value = suggestion.value || '';
subfolderEl.dataset.baseDirectory = suggestion.baseDirectory || '';
this.saveDownloadTargetSelection(missing, {
category,
subfolder: suggestion.value || '',
subfolderBaseDirectory: suggestion.baseDirectory || '',
categoryTouched: Boolean(preserveSavedCategory && category === originalCategory),
subfolderTouched: true
});
this.syncDownloadTargetFolderContext(categoryEl, subfolderEl);
@@ -1178,9 +1433,14 @@ export const downloadTargetMethods = {
const categoryListId = `download-category-list-${missing.node_id}-${missing.widget_index}`;
const subfolderListId = `download-subfolder-list-${missing.node_id}-${missing.widget_index}`;
const saved = this.getSavedDownloadTargetSelection(missing);
const selectedCategory = this.normalizeDownloadCategory(saved?.category || defaultCategory || 'checkpoints');
const selectedSubfolder = saved ? saved.subfolder || '' : '';
const selectedSubfolderBaseDirectory = saved ? saved.subfolderBaseDirectory || '' : '';
const inferredCategory = this.getMissingDownloadCategory(missing, defaultCategory || 'checkpoints');
const preserveSavedCategory = this.shouldPreserveSavedDownloadCategory(missing, saved, inferredCategory);
const selectedCategory = this.normalizeDownloadCategory(
preserveSavedCategory ? (saved.category || inferredCategory) : inferredCategory
);
const preserveSavedSubfolder = Boolean(saved?.subfolderTouched);
const selectedSubfolder = preserveSavedSubfolder ? saved.subfolder || '' : '';
const selectedSubfolderBaseDirectory = preserveSavedSubfolder ? saved.subfolderBaseDirectory || '' : '';
let html = `<div class="mr-download-target">`;
html += `<div class="mr-download-target-grid">`;
@@ -1205,7 +1465,10 @@ export const downloadTargetMethods = {
getDownloadTargetSelection(missing, fallbackCategory = 'checkpoints') {
const categoryEl = this.contentElement?.querySelector(`#download-category-${missing.node_id}-${missing.widget_index}`);
const subfolderEl = this.contentElement?.querySelector(`#download-subfolder-${missing.node_id}-${missing.widget_index}`);
const category = this.normalizeDownloadCategory(this.getDropdownValue(categoryEl) || fallbackCategory || 'checkpoints');
const category = this.normalizeDownloadCategory(
this.getDropdownValue(categoryEl)
|| this.getMissingDownloadCategory(missing, fallbackCategory || 'checkpoints')
);
const subfolder = (subfolderEl?.value || '').trim();
const subfolderBaseDirectory = subfolder ? subfolderEl?.dataset.baseDirectory || '' : '';
this.saveDownloadTargetSelection(missing, {
@@ -1310,6 +1573,7 @@ export const downloadTargetMethods = {
category: value,
subfolder: '',
subfolderBaseDirectory: '',
categoryTouched: true,
subfolderTouched: false
});
subfolderEl.dataset.baseDirectory = '';
+10 -6
View File
@@ -1196,6 +1196,10 @@ export const searchPanelMethods = {
const modelName = modelParts.name || downloadFilename;
const fullModelName = this.getVersionedModelName(modelName, modelParts.version);
const baseModel = downloadSource.base_model || missing.civitai_info?.base_model || '';
const rowCategory = this.getSourceResultDownloadCategory?.(
downloadSource,
downloadSource.directory || downloadSource.category || this.getMissingDownloadCategory?.(missing, 'checkpoints') || 'checkpoints'
) || downloadSource.directory || downloadSource.category || this.getMissingDownloadCategory?.(missing, 'checkpoints') || 'checkpoints';
const secondaryParts = [
sourceSecondary,
fullModelName && fullModelName !== downloadFilename ? downloadFilename : '',
@@ -1206,7 +1210,7 @@ export const searchPanelMethods = {
filename: downloadFilename,
model: modelName,
version: modelParts.version,
category: downloadSource.directory || downloadSource.category || missing.category || 'checkpoints'
category: rowCategory
});
const rowDetailsContext = ['civitai', 'civarchive'].includes(String(source).toLowerCase())
? {
@@ -1218,7 +1222,7 @@ export const searchPanelMethods = {
name: modelName,
filename: downloadFilename,
missing_key: this.getMissingModelKey(missing),
category: missing.category
category: rowCategory
}
: null;
@@ -1235,7 +1239,7 @@ export const searchPanelMethods = {
size: this.formatSearchResultSize(downloadSource),
downloadUrl: downloadSource.url,
downloadFilename,
category: downloadSource.directory || downloadSource.category || missing.category || 'checkpoints',
category: rowCategory,
openUrl: modelUrl,
searchedAt: this.getSearchResultTimestamp(downloadSource),
pathMetadata: rowPathMetadata,
@@ -1244,10 +1248,10 @@ export const searchPanelMethods = {
filename: downloadFilename,
model: modelName,
version: modelParts.version,
category: downloadSource.directory || downloadSource.category || missing.category || 'checkpoints'
category: rowCategory
}, {
filename: downloadFilename,
category: downloadSource.directory || downloadSource.category || missing.category || 'checkpoints',
category: rowCategory,
url: downloadSource.url,
openUrl: modelUrl,
pathMetadata: rowPathMetadata
@@ -1261,7 +1265,7 @@ export const searchPanelMethods = {
html += this.renderSearchControls(missing, { buttonText: 'Search Again' });
html += this.renderDownloadTargetControls(
missing,
downloadSource.directory || downloadSource.category || missing.category || 'checkpoints'
downloadSource.directory || downloadSource.category || this.getMissingDownloadCategory?.(missing, 'checkpoints') || 'checkpoints'
);
html += `</div>`;