refactor: centralize search row metadata preparation

This commit is contained in:
Dariusz L
2026-08-07 00:27:27 +02:00
parent 30b1bf99e9
commit 613372539b
4 changed files with 49 additions and 38 deletions
+18 -4
View File
@@ -4840,7 +4840,10 @@ test('manual URL table row preserves the explicit provenance boundary', () => {
test('source table rows preserve context-specific source labels', () => {
const getDownloadSourceTableRow = eval(`(${extractMethod(searchPanelMethodsSource, 'getDownloadSourceTableRow')})`);
const getCustomUrlResultTableRow = eval(`(${extractMethod(searchPanelMethodsSource, 'getCustomUrlResultTableRow')})`);
const prepareSearchResultRow = eval(`(${extractMethod(downloadTargetMethodsSource, 'prepareSearchResultRow')})`);
const metadataCalls = { path: [], download: [] };
const dialog = {
prepareSearchResultRow,
getFilenameFromPath(value = '') {
return String(value).split(/[\\/]/).at(-1) || '';
},
@@ -4856,11 +4859,13 @@ test('source table rows preserve context-specific source labels', () => {
getVersionedModelName(name, version) {
return version ? `${name} ${version}` : name;
},
getDownloadPathMetadata() {
return {};
getDownloadPathMetadata(_missing, source) {
metadataCalls.path.push(source);
return { type: 'path' };
},
getDownloadMetadata() {
return {};
getDownloadMetadata(_missing, source, options) {
metadataCalls.download.push({ source, options });
return { type: 'download' };
},
getLocalHashMatchIdentitiesForResult() {
return [];
@@ -4904,6 +4909,13 @@ test('source table rows preserve context-specific source labels', () => {
assert.equal(providerRow.sourceLabel, 'CivitAI');
assert.equal(workflowRow.sourceLabel, 'Workflow URL');
assert.equal(customRow.sourceLabel, 'Custom URL');
assert.deepEqual(providerRow.pathMetadata, { type: 'path' });
assert.deepEqual(providerRow.downloadMetadata, { type: 'download' });
assert.equal(metadataCalls.path[0].filename, 'model.safetensors');
assert.equal(metadataCalls.path[0].model, 'model.safetensors');
assert.equal(metadataCalls.download[0].source.filename, 'model.safetensors');
assert.equal(metadataCalls.download[0].options.filename, 'model.safetensors');
assert.equal(metadataCalls.download[0].options.url, 'https://example.test/download');
});
test('search suggestion does not let a delayed incompatible result replace workflow path context', () => {
@@ -7181,6 +7193,7 @@ test('search result refreshes preserve keyed progress and result DOM', () => {
test('search provider rows preserve a shared result row contract', () => {
const displaySearchResults = eval(`(${extractMethod(resolveDownloadMethodsSource, 'displaySearchResults')})`);
const buildSearchResultRow = eval(`(${extractMethod(searchPanelMethodsSource, 'buildSearchResultRow')})`);
const prepareSearchResultRow = eval(`(${extractMethod(downloadTargetMethodsSource, 'prepareSearchResultRow')})`);
const previousGlobals = {
getModelCardUrl: globalThis.getModelCardUrl,
getCivitaiModelUrl: globalThis.getCivitaiModelUrl,
@@ -7189,6 +7202,7 @@ test('search provider rows preserve a shared result row contract', () => {
const rows = [];
const dialog = {
buildSearchResultRow,
prepareSearchResultRow,
getHashMatchLabelMap() {
return null;
},
@@ -3703,18 +3703,7 @@ export const resolveDownloadMethods = {
const rowKeys = new Set();
const addRow = (row) => {
if (!row) return;
if (!row.pathMetadata) {
row.pathMetadata = this.getDownloadPathMetadata(missing, row.detailsContext || row);
}
if (!row.downloadMetadata) {
row.downloadMetadata = this.getDownloadMetadata(missing, row.detailsContext || row, {
filename: row.downloadFilename || row.filename || '',
category: row.category || missing.category || '',
url: row.downloadUrl || '',
openUrl: row.openUrl || '',
pathMetadata: row.pathMetadata
});
}
row = this.prepareSearchResultRow(missing, row);
const rowKey = `${row.sourceKey}:${row.downloadUrl || row.openUrl || `${row.model}:${row.filename}`}`;
if (rowKeys.has(rowKey)) return;
rowKeys.add(rowKey);
@@ -1248,6 +1248,26 @@ export const downloadTargetMethods = {
};
},
prepareSearchResultRow(missing = {}, row = {}, metadataSource = null, pathMetadataSource = null) {
if (!row || typeof row !== 'object') return row;
const source = metadataSource || row.detailsContext || row;
const pathSource = pathMetadataSource || source;
if (!row.pathMetadata) {
row.pathMetadata = this.getDownloadPathMetadata(missing, pathSource);
}
if (!row.downloadMetadata) {
row.downloadMetadata = this.getDownloadMetadata(missing, source, {
filename: row.downloadFilename || row.filename || '',
category: row.category || missing.category || '',
url: row.downloadUrl || '',
openUrl: row.openUrl || '',
pathMetadata: row.pathMetadata
});
}
return row;
},
getDownloadPathMetadata(missing = {}, source = {}) {
const { merged } = this.getDownloadSourceContext(missing, source, {
respectProvenanceBoundary: false
+10 -22
View File
@@ -1696,13 +1696,6 @@ export const searchPanelMethods = {
fullModelName && fullModelName !== downloadFilename ? downloadFilename : '',
baseModel
].filter(Boolean);
const rowPathMetadata = this.getDownloadPathMetadata(missing, {
...downloadSource,
filename: downloadFilename,
model: modelName,
version: modelParts.version,
category: rowCategory
});
const rowDetailsContext = ['civitai', 'civarchive', 'huggingface'].includes(normalizedSource)
? {
...downloadSource,
@@ -1723,6 +1716,14 @@ export const searchPanelMethods = {
category: rowCategory
}
: null;
const rowPathMetadataSource = {
...downloadSource,
filename: downloadFilename,
model: modelName,
version: modelParts.version,
category: rowCategory
};
const rowMetadataSource = rowDetailsContext || rowPathMetadataSource;
const localHashMatches = Array.isArray(missing.matches)
? missing.matches.filter(match => match?.hash_lookup_source)
: [];
@@ -1738,7 +1739,7 @@ export const searchPanelMethods = {
localHashMatchIdentities
) || '';
return {
const row = {
sourceKey,
sourceLabel,
model: modelName,
@@ -1752,25 +1753,12 @@ export const searchPanelMethods = {
openUrl: modelUrl,
searchedAt: this.getSearchResultTimestamp(downloadSource),
localHashMatchIdentities,
pathMetadata: rowPathMetadata,
downloadMetadata: this.getDownloadMetadata(missing, rowDetailsContext || {
...downloadSource,
filename: downloadFilename,
model: modelName,
version: modelParts.version,
category: rowCategory
}, {
filename: downloadFilename,
category: rowCategory,
url: downloadSource.url,
openUrl: modelUrl,
pathMetadata: rowPathMetadata
}),
detailsContext: rowDetailsContext,
match: isFromWorkflow
? { label: 'Provided', className: 'strong' }
: this.getSearchResultMatchDisplay(downloadSource, 'Known', 'strong', hashMatchLabel)
};
return this.prepareSearchResultRow(missing, row, rowMetadataSource, rowPathMetadataSource);
},
getCustomUrlResultTableRow(missing, result = {}, hashLabelMap = null, localHashMatches = []) {