diff --git a/web/css/resolver-main.css b/web/css/resolver-main.css index 0042d5f..2f671fc 100644 --- a/web/css/resolver-main.css +++ b/web/css/resolver-main.css @@ -1418,6 +1418,33 @@ font-size: 10px; letter-spacing: 0.08em; } +.mr-local-matches-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; +} +.mr-local-matches-header > span { + min-width: 0; +} +.mr-local-matches-refresh-btn, +#model-resolver-modal .mr-local-matches-refresh-btn { + width: 26px; + min-width: 26px; + max-width: 26px; + height: 24px; + min-height: 24px; + padding: 0; + flex: 0 0 26px; + font-size: 0; + line-height: 1; +} +.mr-local-matches-refresh-btn .mr-combo-refresh-icon, +#model-resolver-modal .mr-local-matches-refresh-btn .mr-combo-refresh-icon { + width: 13px; + height: 13px; + display: block; +} .mr-missing-browser .mr-muted-note, .mr-missing-browser .mr-no-matches { padding: 9px 10px; @@ -5746,6 +5773,7 @@ } #model-resolver-modal .mr-missing-detail-pane .mr-local-link-btn, #model-resolver-modal .mr-missing-detail-pane .mr-combo-refresh-btn, +#model-resolver-modal .mr-missing-detail-pane .mr-local-matches-refresh-btn, #model-resolver-modal .mr-missing-detail-pane .mr-search-result-action-btn, #model-resolver-modal .mr-missing-detail-pane .mr-download-section .mr-search-button-picker > .mr-btn { background: var(--mr-missing-control-bg, rgba(255,255,255,0.035)); @@ -5757,6 +5785,7 @@ } #model-resolver-modal .mr-missing-detail-pane .mr-local-link-btn:hover:not(:disabled), #model-resolver-modal .mr-missing-detail-pane .mr-combo-refresh-btn:hover:not(:disabled), +#model-resolver-modal .mr-missing-detail-pane .mr-local-matches-refresh-btn:hover:not(:disabled), #model-resolver-modal .mr-missing-detail-pane .mr-search-result-action-btn:hover:not(:disabled), #model-resolver-modal .mr-missing-detail-pane .mr-download-section .mr-search-button-picker > .mr-btn:hover:not(:disabled) { background: var(--mr-missing-control-bg-hover, rgba(255,255,255,0.06)); @@ -5766,6 +5795,7 @@ } #model-resolver-modal .mr-missing-detail-pane .mr-local-link-btn:focus-visible, #model-resolver-modal .mr-missing-detail-pane .mr-combo-refresh-btn:focus-visible, +#model-resolver-modal .mr-missing-detail-pane .mr-local-matches-refresh-btn:focus-visible, #model-resolver-modal .mr-missing-detail-pane .mr-search-result-action-btn:focus-visible, #model-resolver-modal .mr-missing-detail-pane .mr-download-section .mr-search-button-picker > .mr-btn:focus-visible { outline: none; diff --git a/web/resolver/actions/resolve_download_methods.js b/web/resolver/actions/resolve_download_methods.js index b155aa0..3d47a60 100644 --- a/web/resolver/actions/resolve_download_methods.js +++ b/web/resolver/actions/resolve_download_methods.js @@ -938,6 +938,92 @@ export const resolveDownloadMethods = { this.updateBatchFooterButtons?.(); }, + getLocalMatchRefreshTarget(missing = {}) { + return missing.civitai_info?.expected_filename + || missing.expected_filename + || missing.download_source?.filename + || missing.original_path + || missing.name + || ''; + }, + + async refreshLocalMatchesForMissing(missing, { button = null } = {}) { + if (!missing || button?.disabled) return []; + + const targetFilename = String(this.getLocalMatchRefreshTarget(missing) || ''); + if (!targetFilename) { + this.showNotification('No model filename available for local refresh.', 'warning'); + return []; + } + + const minRefreshFeedback = new Promise(resolve => setTimeout(resolve, 420)); + const refreshAnimation = this.startRefreshButtonAnimation?.(button); + const body = this.contentElement?.querySelector(`#local-matches-body-${missing.node_id}-${missing.widget_index}`); + const displayName = targetFilename.split('/').pop()?.split('\\').pop() || targetFilename; + const missingKey = this.getMissingModelKey(missing); + const currentMissing = (this.missingModels || []).find(item => this.getMissingModelKey(item) === missingKey) || missing; + const previousMatches = this.cloneLocalMatches?.(currentMissing.matches || missing.matches || []) || []; + + try { + if (button) { + button.disabled = true; + button.classList.add('mr-btn-is-disabled', 'mr-is-refreshing'); + } + if (body) { + body.innerHTML = `