mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-07-13 20:21:16 -03:00
fix(settings): reject checkpoints↔unet path overlap in extra folder paths with inline error UI
Changes: - Backend: _validate_folder_paths() now checks checkpoints↔unet overlap within the same library using os.path.realpath() for symlink resolution - Backend: set() calls _validate_folder_paths() for both folder_paths and extra_folder_paths before writing - Backend: extracted _normalize_path_set() helper to eliminate duplicated normalization logic - Frontend: inline error display with red border + error message below the conflicting input, no save triggered - Frontend: path normalization (strip trailing slash, lowercase) in pre-check to reduce false negatives vs backend realpath - Frontend: asymmetric error UX — message only on the user-edited side, red border on the pre-existing conflict side - CSS: has-error styles with hardcoded rgba fallback for older browsers - i18n: checkpointUnetOverlap + checkpointUnetOverlapInline keys added to all 10 locale files
This commit is contained in:
@@ -505,7 +505,9 @@
|
|||||||
"saveSuccess": "Zusätzliche Ordnerpfade aktualisiert. Neustart erforderlich, um Änderungen anzuwenden.",
|
"saveSuccess": "Zusätzliche Ordnerpfade aktualisiert. Neustart erforderlich, um Änderungen anzuwenden.",
|
||||||
"saveError": "Fehler beim Aktualisieren der zusätzlichen Ordnerpfade: {message}",
|
"saveError": "Fehler beim Aktualisieren der zusätzlichen Ordnerpfade: {message}",
|
||||||
"validation": {
|
"validation": {
|
||||||
"duplicatePath": "Dieser Pfad ist bereits konfiguriert"
|
"duplicatePath": "Dieser Pfad ist bereits konfiguriert",
|
||||||
|
"checkpointUnetOverlap": "Derselbe Pfad kann nicht für Checkpoints und Diffusionsmodelle verwendet werden: {paths}",
|
||||||
|
"checkpointUnetOverlapInline": "Dieser Pfad wird bereits für einen anderen Modelltyp verwendet. Bitte verwenden Sie separate Ordner für Checkpoints und Diffusionsmodelle."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"priorityTags": {
|
"priorityTags": {
|
||||||
|
|||||||
@@ -505,7 +505,9 @@
|
|||||||
"saveSuccess": "Extra folder paths updated. Restart required to apply changes.",
|
"saveSuccess": "Extra folder paths updated. Restart required to apply changes.",
|
||||||
"saveError": "Failed to update extra folder paths: {message}",
|
"saveError": "Failed to update extra folder paths: {message}",
|
||||||
"validation": {
|
"validation": {
|
||||||
"duplicatePath": "This path is already configured"
|
"duplicatePath": "This path is already configured",
|
||||||
|
"checkpointUnetOverlap": "Cannot use the same path for both checkpoints and diffusion models: {paths}",
|
||||||
|
"checkpointUnetOverlapInline": "This path is also used for a different model type. Use separate folders for checkpoints and diffusion models."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"priorityTags": {
|
"priorityTags": {
|
||||||
|
|||||||
@@ -505,7 +505,9 @@
|
|||||||
"saveSuccess": "Rutas de carpetas adicionales actualizadas. Se requiere reinicio para aplicar los cambios.",
|
"saveSuccess": "Rutas de carpetas adicionales actualizadas. Se requiere reinicio para aplicar los cambios.",
|
||||||
"saveError": "Error al actualizar las rutas de carpetas adicionales: {message}",
|
"saveError": "Error al actualizar las rutas de carpetas adicionales: {message}",
|
||||||
"validation": {
|
"validation": {
|
||||||
"duplicatePath": "Esta ruta ya está configurada"
|
"duplicatePath": "Esta ruta ya está configurada",
|
||||||
|
"checkpointUnetOverlap": "No se puede usar la misma ruta para checkpoints y modelos de difusión: {paths}",
|
||||||
|
"checkpointUnetOverlapInline": "Esta ruta ya se usa para otro tipo de modelo. Use carpetas separadas para checkpoints y modelos de difusión."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"priorityTags": {
|
"priorityTags": {
|
||||||
|
|||||||
@@ -505,7 +505,9 @@
|
|||||||
"saveSuccess": "Chemins de dossiers supplémentaires mis à jour. Redémarrage requis pour appliquer les changements.",
|
"saveSuccess": "Chemins de dossiers supplémentaires mis à jour. Redémarrage requis pour appliquer les changements.",
|
||||||
"saveError": "Échec de la mise à jour des chemins de dossiers supplémentaires: {message}",
|
"saveError": "Échec de la mise à jour des chemins de dossiers supplémentaires: {message}",
|
||||||
"validation": {
|
"validation": {
|
||||||
"duplicatePath": "Ce chemin est déjà configuré"
|
"duplicatePath": "Ce chemin est déjà configuré",
|
||||||
|
"checkpointUnetOverlap": "Impossible d'utiliser le même chemin pour les checkpoints et les modèles de diffusion : {paths}",
|
||||||
|
"checkpointUnetOverlapInline": "Ce chemin est déjà utilisé pour un autre type de modèle. Utilisez des dossiers séparés pour les checkpoints et les modèles de diffusion."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"priorityTags": {
|
"priorityTags": {
|
||||||
|
|||||||
@@ -505,7 +505,9 @@
|
|||||||
"saveSuccess": "נתיבי תיקיות נוספים עודכנו. נדרשת הפעלה מחדש כדי להחיל את השינויים.",
|
"saveSuccess": "נתיבי תיקיות נוספים עודכנו. נדרשת הפעלה מחדש כדי להחיל את השינויים.",
|
||||||
"saveError": "נכשל בעדכון נתיבי תיקיות נוספים: {message}",
|
"saveError": "נכשל בעדכון נתיבי תיקיות נוספים: {message}",
|
||||||
"validation": {
|
"validation": {
|
||||||
"duplicatePath": "נתיב זה כבר מוגדר"
|
"duplicatePath": "נתיב זה כבר מוגדר",
|
||||||
|
"checkpointUnetOverlap": "לא ניתן להשתמש באותו נתיב עבור checkpoints ומודלי דיפוזיה: {paths}",
|
||||||
|
"checkpointUnetOverlapInline": "הנתיב הזה כבר נמצא בשימוש עבור סוג מודל אחר. יש להשתמש בתיקיות נפרדות עבור checkpoints ומודלי דיפוזיה."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"priorityTags": {
|
"priorityTags": {
|
||||||
|
|||||||
@@ -505,7 +505,9 @@
|
|||||||
"saveSuccess": "追加フォルダーパスを更新しました。変更を適用するには再起動が必要です。",
|
"saveSuccess": "追加フォルダーパスを更新しました。変更を適用するには再起動が必要です。",
|
||||||
"saveError": "追加フォルダーパスの更新に失敗しました: {message}",
|
"saveError": "追加フォルダーパスの更新に失敗しました: {message}",
|
||||||
"validation": {
|
"validation": {
|
||||||
"duplicatePath": "このパスはすでに設定されています"
|
"duplicatePath": "このパスはすでに設定されています",
|
||||||
|
"checkpointUnetOverlap": "checkpoints と diffusion models に同じパスは使用できません:{paths}",
|
||||||
|
"checkpointUnetOverlapInline": "このパスは別のモデルタイプですでに使用されています。checkpoints と diffusion models には別々のフォルダを使用してください。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"priorityTags": {
|
"priorityTags": {
|
||||||
|
|||||||
@@ -505,7 +505,9 @@
|
|||||||
"saveSuccess": "추가 폴다 경로가 업데이트되었습니다. 변경 사항을 적용하려면 재시작이 필요합니다.",
|
"saveSuccess": "추가 폴다 경로가 업데이트되었습니다. 변경 사항을 적용하려면 재시작이 필요합니다.",
|
||||||
"saveError": "추가 폴다 경로 업데이트 실패: {message}",
|
"saveError": "추가 폴다 경로 업데이트 실패: {message}",
|
||||||
"validation": {
|
"validation": {
|
||||||
"duplicatePath": "이 경로는 이미 구성되어 있습니다"
|
"duplicatePath": "이 경로는 이미 구성되어 있습니다",
|
||||||
|
"checkpointUnetOverlap": "checkpoints와 diffusion models에 동일한 경로를 사용할 수 없습니다: {paths}",
|
||||||
|
"checkpointUnetOverlapInline": "이 경로는 다른 모델 유형에 이미 사용 중입니다. checkpoints와 diffusion models에 별도의 폴더를 사용하세요."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"priorityTags": {
|
"priorityTags": {
|
||||||
|
|||||||
@@ -505,7 +505,9 @@
|
|||||||
"saveSuccess": "Дополнительные пути к папкам обновлены. Требуется перезапуск для применения изменений.",
|
"saveSuccess": "Дополнительные пути к папкам обновлены. Требуется перезапуск для применения изменений.",
|
||||||
"saveError": "Не удалось обновить дополнительные пути к папкам: {message}",
|
"saveError": "Не удалось обновить дополнительные пути к папкам: {message}",
|
||||||
"validation": {
|
"validation": {
|
||||||
"duplicatePath": "Этот путь уже настроен"
|
"duplicatePath": "Этот путь уже настроен",
|
||||||
|
"checkpointUnetOverlap": "Нельзя использовать один и тот же путь для checkpoints и diffusion models: {paths}",
|
||||||
|
"checkpointUnetOverlapInline": "Этот путь уже используется для другого типа модели. Используйте отдельные папки для checkpoints и diffusion models."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"priorityTags": {
|
"priorityTags": {
|
||||||
|
|||||||
@@ -505,7 +505,9 @@
|
|||||||
"saveSuccess": "额外文件夹路径已更新,需要重启才能生效。",
|
"saveSuccess": "额外文件夹路径已更新,需要重启才能生效。",
|
||||||
"saveError": "更新额外文件夹路径失败:{message}",
|
"saveError": "更新额外文件夹路径失败:{message}",
|
||||||
"validation": {
|
"validation": {
|
||||||
"duplicatePath": "此路径已配置"
|
"duplicatePath": "此路径已配置",
|
||||||
|
"checkpointUnetOverlap": "checkpoints 和 diffusion models 不能使用相同的路径:{paths}",
|
||||||
|
"checkpointUnetOverlapInline": "此路径已被用于另一种模型类型。请为 checkpoints 和 diffusion models 使用不同的文件夹。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"priorityTags": {
|
"priorityTags": {
|
||||||
|
|||||||
@@ -505,7 +505,9 @@
|
|||||||
"saveSuccess": "額外資料夾路徑已更新,需要重啟才能生效。",
|
"saveSuccess": "額外資料夾路徑已更新,需要重啟才能生效。",
|
||||||
"saveError": "更新額外資料夾路徑失敗:{message}",
|
"saveError": "更新額外資料夾路徑失敗:{message}",
|
||||||
"validation": {
|
"validation": {
|
||||||
"duplicatePath": "此路徑已設定"
|
"duplicatePath": "此路徑已設定",
|
||||||
|
"checkpointUnetOverlap": "checkpoints 和 diffusion models 不能使用相同的路徑:{paths}",
|
||||||
|
"checkpointUnetOverlapInline": "此路徑已被用於另一種模型類型。請為 checkpoints 和 diffusion models 使用不同的資料夾。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"priorityTags": {
|
"priorityTags": {
|
||||||
|
|||||||
@@ -630,12 +630,37 @@ class SettingsManager:
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _normalize_path_set(paths: Iterable[str]) -> set[str]:
|
||||||
|
"""Normalize an iterable of paths for set-based overlap comparison.
|
||||||
|
|
||||||
|
Resolves symlinks via ``os.path.realpath`` when the path exists on disk,
|
||||||
|
then applies ``os.path.normcase`` + ``os.path.normpath`` for consistent
|
||||||
|
cross-platform comparison. Non-string / empty entries are skipped.
|
||||||
|
"""
|
||||||
|
result: set[str] = set()
|
||||||
|
for p in paths:
|
||||||
|
if not isinstance(p, str):
|
||||||
|
continue
|
||||||
|
stripped = p.strip()
|
||||||
|
if not stripped:
|
||||||
|
continue
|
||||||
|
if os.path.exists(stripped):
|
||||||
|
stripped = os.path.normpath(os.path.realpath(stripped))
|
||||||
|
result.add(os.path.normcase(stripped))
|
||||||
|
return result
|
||||||
|
|
||||||
def _validate_folder_paths(
|
def _validate_folder_paths(
|
||||||
self,
|
self,
|
||||||
library_name: str,
|
library_name: str,
|
||||||
folder_paths: Mapping[str, Iterable[str]],
|
folder_paths: Mapping[str, Iterable[str]],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Ensure folder paths do not overlap with other libraries."""
|
"""Ensure folder paths do not overlap with other libraries.
|
||||||
|
|
||||||
|
Also detects checkpoints ↔ unet path overlap within the same library
|
||||||
|
(including via symlink resolution), which is a configuration error since
|
||||||
|
these model types must use separate physical folders.
|
||||||
|
"""
|
||||||
libraries = self.settings.get("libraries", {})
|
libraries = self.settings.get("libraries", {})
|
||||||
normalized_new: Dict[str, Dict[str, str]] = {}
|
normalized_new: Dict[str, Dict[str, str]] = {}
|
||||||
for key, values in folder_paths.items():
|
for key, values in folder_paths.items():
|
||||||
@@ -673,6 +698,22 @@ class SettingsManager:
|
|||||||
f"Folder path(s) {collisions} already assigned to library '{other_name}'"
|
f"Folder path(s) {collisions} already assigned to library '{other_name}'"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Checkpoints ↔ unet overlap within the same library
|
||||||
|
ckpt_paths = folder_paths.get("checkpoints", []) or []
|
||||||
|
unet_paths = folder_paths.get("unet", []) or []
|
||||||
|
if ckpt_paths and unet_paths:
|
||||||
|
ckpt_real = self._normalize_path_set(ckpt_paths)
|
||||||
|
unet_real = self._normalize_path_set(unet_paths)
|
||||||
|
overlap = ckpt_real & unet_real
|
||||||
|
if overlap:
|
||||||
|
collisions = ", ".join(sorted(overlap))
|
||||||
|
raise ValueError(
|
||||||
|
f"Path(s) {collisions} are configured for both "
|
||||||
|
f"'checkpoints' and 'unet' (diffusion models). "
|
||||||
|
f"These model types must use separate physical folders. "
|
||||||
|
f"Please remove one of the conflicting entries."
|
||||||
|
)
|
||||||
|
|
||||||
def _update_active_library_entry(
|
def _update_active_library_entry(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
@@ -1547,8 +1588,12 @@ class SettingsManager:
|
|||||||
portable_switch_pending = True
|
portable_switch_pending = True
|
||||||
self._prepare_portable_switch(value)
|
self._prepare_portable_switch(value)
|
||||||
if key == "folder_paths" and isinstance(value, Mapping):
|
if key == "folder_paths" and isinstance(value, Mapping):
|
||||||
|
active_name = self.get_active_library_name()
|
||||||
|
self._validate_folder_paths(active_name, value)
|
||||||
self._update_active_library_entry(folder_paths=value) # type: ignore[arg-type]
|
self._update_active_library_entry(folder_paths=value) # type: ignore[arg-type]
|
||||||
elif key == "extra_folder_paths" and isinstance(value, Mapping):
|
elif key == "extra_folder_paths" and isinstance(value, Mapping):
|
||||||
|
active_name = self.get_active_library_name()
|
||||||
|
self._validate_folder_paths(active_name, value)
|
||||||
self._update_active_library_entry(extra_folder_paths=value) # type: ignore[arg-type]
|
self._update_active_library_entry(extra_folder_paths=value) # type: ignore[arg-type]
|
||||||
elif key == "default_lora_root":
|
elif key == "default_lora_root":
|
||||||
self._update_active_library_entry(default_lora_root=str(value))
|
self._update_active_library_entry(default_lora_root=str(value))
|
||||||
|
|||||||
@@ -1562,6 +1562,29 @@ input:checked + .toggle-slider:before {
|
|||||||
box-shadow: 0 0 0 2px rgba(var(--lora-accent-rgb, 79, 70, 229), 0.1);
|
box-shadow: 0 0 0 2px rgba(var(--lora-accent-rgb, 79, 70, 229), 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.extra-folder-path-row .path-controls .extra-folder-path-input.has-error {
|
||||||
|
border-color: var(--lora-error);
|
||||||
|
background-color: rgba(220, 53, 69, 0.08);
|
||||||
|
background-color: rgba(from var(--lora-error) r g b / 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.extra-folder-path-row .path-controls .extra-folder-path-input.has-error:focus {
|
||||||
|
box-shadow: 0 0 0 2px rgba(220, 53, 69, 0.15);
|
||||||
|
box-shadow: 0 0 0 2px rgba(from var(--lora-error) r g b / 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.extra-folder-path-error {
|
||||||
|
color: var(--lora-error);
|
||||||
|
font-size: 0.8em;
|
||||||
|
margin-top: 4px;
|
||||||
|
line-height: 1.4;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.extra-folder-path-error.visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.extra-folder-path-row .path-controls .remove-path-btn {
|
.extra-folder-path-row .path-controls .remove-path-btn {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
|||||||
@@ -1693,13 +1693,15 @@ export class SettingsManager {
|
|||||||
<input type="text" class="extra-folder-path-input"
|
<input type="text" class="extra-folder-path-input"
|
||||||
placeholder="${translate('settings.extraFolderPaths.pathPlaceholder', {}, '/path/to/models')}" value="${path}"
|
placeholder="${translate('settings.extraFolderPaths.pathPlaceholder', {}, '/path/to/models')}" value="${path}"
|
||||||
onblur="settingsManager.updateExtraFolderPaths('${modelType}')"
|
onblur="settingsManager.updateExtraFolderPaths('${modelType}')"
|
||||||
|
onfocus="settingsManager.clearExtraFolderPathError(this)"
|
||||||
onkeydown="if(event.key === 'Enter') { this.blur(); }" />
|
onkeydown="if(event.key === 'Enter') { this.blur(); }" />
|
||||||
<button type="button" class="remove-path-btn"
|
<button type="button" class="remove-path-btn"
|
||||||
onclick="this.parentElement.parentElement.remove(); settingsManager.updateExtraFolderPaths('${modelType}')"
|
onclick="settingsManager.removeExtraFolderPathRow(this, '${modelType}')"
|
||||||
title="${translate('common.actions.delete', {}, 'Delete')}">
|
title="${translate('common.actions.delete', {}, 'Delete')}">
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-times"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="extra-folder-path-error"></div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
container.appendChild(row);
|
container.appendChild(row);
|
||||||
@@ -1713,7 +1715,63 @@ export class SettingsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearExtraFolderPathError(input) {
|
||||||
|
input.classList.remove('has-error');
|
||||||
|
const row = input.closest('.extra-folder-path-row');
|
||||||
|
if (row) {
|
||||||
|
const errEl = row.querySelector('.extra-folder-path-error');
|
||||||
|
if (errEl) {
|
||||||
|
errEl.classList.remove('visible');
|
||||||
|
errEl.textContent = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_clearAllExtraFolderPathErrors() {
|
||||||
|
document.querySelectorAll('.extra-folder-path-input.has-error').forEach((input) => {
|
||||||
|
input.classList.remove('has-error');
|
||||||
|
});
|
||||||
|
document.querySelectorAll('.extra-folder-path-error.visible').forEach((el) => {
|
||||||
|
el.classList.remove('visible');
|
||||||
|
el.textContent = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_markExtraFolderPathsError(modelType, overlappingPaths, showMessage = false) {
|
||||||
|
const container = document.getElementById(`extraFolderPaths-${modelType}`);
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
const inputs = container.querySelectorAll('.extra-folder-path-input');
|
||||||
|
inputs.forEach((input) => {
|
||||||
|
const val = input.value.trim();
|
||||||
|
if (val && overlappingPaths.includes(val)) {
|
||||||
|
input.classList.add('has-error');
|
||||||
|
if (showMessage) {
|
||||||
|
const row = input.closest('.extra-folder-path-row');
|
||||||
|
if (row) {
|
||||||
|
const errEl = row.querySelector('.extra-folder-path-error');
|
||||||
|
if (errEl) {
|
||||||
|
errEl.textContent = translate('settings.extraFolderPaths.validation.checkpointUnetOverlapInline', {}, 'This path is also used for a different model type. Use separate folders for checkpoints and diffusion models.');
|
||||||
|
errEl.classList.add('visible');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
removeExtraFolderPathRow(btn, modelType) {
|
||||||
|
const row = btn.closest('.extra-folder-path-row');
|
||||||
|
if (row) {
|
||||||
|
row.remove();
|
||||||
|
this.updateExtraFolderPaths(modelType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async updateExtraFolderPaths(changedModelType) {
|
async updateExtraFolderPaths(changedModelType) {
|
||||||
|
// Clear previous errors
|
||||||
|
this._clearAllExtraFolderPathErrors();
|
||||||
|
|
||||||
const extraFolderPaths = {};
|
const extraFolderPaths = {};
|
||||||
|
|
||||||
// Collect paths for all model types
|
// Collect paths for all model types
|
||||||
@@ -1734,6 +1792,32 @@ export class SettingsManager {
|
|||||||
extraFolderPaths[modelType] = paths;
|
extraFolderPaths[modelType] = paths;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Client-side pre-check: checkpoints and unet must not share the same path.
|
||||||
|
// Normalise paths to reduce false negatives vs the backend's realpath + normcase.
|
||||||
|
const normalise = (p) => p.replace(/[/\\]+$/, '').toLowerCase();
|
||||||
|
const ckptSet = new Set((extraFolderPaths.checkpoints || []).map(normalise));
|
||||||
|
const unetSet = new Set((extraFolderPaths.unet || []).map(normalise));
|
||||||
|
const ckptOverlap = (extraFolderPaths.checkpoints || []).filter(p => p && unetSet.has(normalise(p)));
|
||||||
|
const unetOverlap = (extraFolderPaths.unet || []).filter(p => p && ckptSet.has(normalise(p)));
|
||||||
|
const hasOverlap = ckptOverlap.length > 0 || unetOverlap.length > 0;
|
||||||
|
|
||||||
|
if (hasOverlap) {
|
||||||
|
// Error message only on the side the user just edited.
|
||||||
|
// The other side gets red border only (passive conflict indicator).
|
||||||
|
if (changedModelType === 'checkpoints') {
|
||||||
|
this._markExtraFolderPathsError('checkpoints', ckptOverlap, true);
|
||||||
|
this._markExtraFolderPathsError('unet', unetOverlap, false);
|
||||||
|
} else if (changedModelType === 'unet') {
|
||||||
|
this._markExtraFolderPathsError('unet', unetOverlap, true);
|
||||||
|
this._markExtraFolderPathsError('checkpoints', ckptOverlap, false);
|
||||||
|
} else {
|
||||||
|
// Pre-existing conflict from direct config edit — mark both without messages
|
||||||
|
this._markExtraFolderPathsError('checkpoints', ckptOverlap, false);
|
||||||
|
this._markExtraFolderPathsError('unet', unetOverlap, false);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if paths have actually changed
|
// Check if paths have actually changed
|
||||||
const currentPaths = state.global.settings.extra_folder_paths || {};
|
const currentPaths = state.global.settings.extra_folder_paths || {};
|
||||||
const pathsChanged = JSON.stringify(currentPaths) !== JSON.stringify(extraFolderPaths);
|
const pathsChanged = JSON.stringify(currentPaths) !== JSON.stringify(extraFolderPaths);
|
||||||
|
|||||||
Reference in New Issue
Block a user