mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-09-20 18:51:26 -03:00
feat(sidebar): delete folders from the sidebar (#999)
Folders created from the sidebar had no in-app way back out: the only
removal path was to leave ComfyUI, delete the directory by hand and
rescan. A typo'd folder also polluted the move/download destination
picker permanently, since it reads the same all_folders source.
Adds POST /api/lm/{prefix}/delete-folder, restricted to directories
whose subtree holds no model weight files — a folder-level cascade would
bypass the per-model lifecycle bookkeeping (metadata sidecars, previews,
cache entries, pending-delete staging, recipe references). The service
walks the directory itself instead of trusting the possibly stale cache,
reports what it would remove (models / files / subfolders / symlinks),
and refuses library roots, top-level symlinks (shutil.rmtree rejects
those) and folders holding a staged delete, whose manifest would be
invalidated by the move. Symbolic links inside the subtree are counted
but never followed.
ModelScanner.remove_known_folder mirrors add_known_folder: the removed
subtree leaves all_folders while ancestors are kept (every recorded
ancestor exists on disk in its own right), stale cache entries under the
prefix are purged and the folder list recomputed. The handler broadcasts
models_changed so destination pickers drop the folder too.
The sidebar entry is a destructive context-menu item. The modal opens in
a confirm state for model-free folders and an explanatory one when the
subtree still holds models, decided from the models-only set that already
dims empty nodes; a stale tree is caught by the 409 not_empty/busy
conflict. Truly empty folders get the existing 20s undo affordance,
implemented by re-creating the directory.
This commit is contained in:
@@ -1263,6 +1263,26 @@
|
||||
"unsupported": "[TODO: Translate] Folder creation is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"deleteFolder": "[TODO: Translate] Delete folder",
|
||||
"deleteFolderModal": {
|
||||
"title": "[TODO: Translate] Delete folder?",
|
||||
"message": "[TODO: Translate] The folder and everything inside it will be permanently removed from disk.",
|
||||
"folderLabel": "[TODO: Translate] Folder",
|
||||
"emptyNote": "[TODO: Translate] This folder contains no models. Any other files it holds will be deleted too.",
|
||||
"notEmptyTitle": "[TODO: Translate] Folder is not empty",
|
||||
"notEmptyMessage": "[TODO: Translate] This folder still contains models. Delete or move them first — deleting a folder never cascades over model files.",
|
||||
"confirm": "[TODO: Translate] Delete folder"
|
||||
},
|
||||
"deleteFolderResult": {
|
||||
"success": "[TODO: Translate] Folder \"{name}\" deleted",
|
||||
"successWithFiles": "[TODO: Translate] Folder \"{name}\" deleted along with {count} other item(s)",
|
||||
"restored": "[TODO: Translate] Folder restored",
|
||||
"failed": "[TODO: Translate] Failed to delete folder: {message}",
|
||||
"notEmpty": "[TODO: Translate] This folder still contains models. Refresh the sidebar and try again.",
|
||||
"busy": "[TODO: Translate] A deletion is still pending inside this folder. Wait for the undo window to expire.",
|
||||
"unsupported": "[TODO: Translate] Folder deletion is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"dragDrop": {
|
||||
"unableToResolveRoot": "Zielpfad für das Verschieben konnte nicht ermittelt werden.",
|
||||
"moveUnsupported": "Verschieben wird für dieses Element nicht unterstützt.",
|
||||
|
||||
@@ -1263,6 +1263,26 @@
|
||||
"unsupported": "Folder creation is not supported on this page",
|
||||
"noRoot": "No model root is configured"
|
||||
},
|
||||
"deleteFolder": "Delete folder",
|
||||
"deleteFolderModal": {
|
||||
"title": "Delete folder?",
|
||||
"message": "The folder and everything inside it will be permanently removed from disk.",
|
||||
"folderLabel": "Folder",
|
||||
"emptyNote": "This folder contains no models. Any other files it holds will be deleted too.",
|
||||
"notEmptyTitle": "Folder is not empty",
|
||||
"notEmptyMessage": "This folder still contains models. Delete or move them first — deleting a folder never cascades over model files.",
|
||||
"confirm": "Delete folder"
|
||||
},
|
||||
"deleteFolderResult": {
|
||||
"success": "Folder \"{name}\" deleted",
|
||||
"successWithFiles": "Folder \"{name}\" deleted along with {count} other item(s)",
|
||||
"restored": "Folder restored",
|
||||
"failed": "Failed to delete folder: {message}",
|
||||
"notEmpty": "This folder still contains models. Refresh the sidebar and try again.",
|
||||
"busy": "A deletion is still pending inside this folder. Wait for the undo window to expire.",
|
||||
"unsupported": "Folder deletion is not supported on this page",
|
||||
"noRoot": "No model root is configured"
|
||||
},
|
||||
"dragDrop": {
|
||||
"unableToResolveRoot": "Unable to determine destination path for move.",
|
||||
"moveUnsupported": "Move is not supported for this item.",
|
||||
|
||||
@@ -1263,6 +1263,26 @@
|
||||
"unsupported": "[TODO: Translate] Folder creation is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"deleteFolder": "[TODO: Translate] Delete folder",
|
||||
"deleteFolderModal": {
|
||||
"title": "[TODO: Translate] Delete folder?",
|
||||
"message": "[TODO: Translate] The folder and everything inside it will be permanently removed from disk.",
|
||||
"folderLabel": "[TODO: Translate] Folder",
|
||||
"emptyNote": "[TODO: Translate] This folder contains no models. Any other files it holds will be deleted too.",
|
||||
"notEmptyTitle": "[TODO: Translate] Folder is not empty",
|
||||
"notEmptyMessage": "[TODO: Translate] This folder still contains models. Delete or move them first — deleting a folder never cascades over model files.",
|
||||
"confirm": "[TODO: Translate] Delete folder"
|
||||
},
|
||||
"deleteFolderResult": {
|
||||
"success": "[TODO: Translate] Folder \"{name}\" deleted",
|
||||
"successWithFiles": "[TODO: Translate] Folder \"{name}\" deleted along with {count} other item(s)",
|
||||
"restored": "[TODO: Translate] Folder restored",
|
||||
"failed": "[TODO: Translate] Failed to delete folder: {message}",
|
||||
"notEmpty": "[TODO: Translate] This folder still contains models. Refresh the sidebar and try again.",
|
||||
"busy": "[TODO: Translate] A deletion is still pending inside this folder. Wait for the undo window to expire.",
|
||||
"unsupported": "[TODO: Translate] Folder deletion is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"dragDrop": {
|
||||
"unableToResolveRoot": "No se puede determinar la ruta de destino para el movimiento.",
|
||||
"moveUnsupported": "El movimiento no es compatible con este elemento.",
|
||||
|
||||
@@ -1263,6 +1263,26 @@
|
||||
"unsupported": "[TODO: Translate] Folder creation is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"deleteFolder": "[TODO: Translate] Delete folder",
|
||||
"deleteFolderModal": {
|
||||
"title": "[TODO: Translate] Delete folder?",
|
||||
"message": "[TODO: Translate] The folder and everything inside it will be permanently removed from disk.",
|
||||
"folderLabel": "[TODO: Translate] Folder",
|
||||
"emptyNote": "[TODO: Translate] This folder contains no models. Any other files it holds will be deleted too.",
|
||||
"notEmptyTitle": "[TODO: Translate] Folder is not empty",
|
||||
"notEmptyMessage": "[TODO: Translate] This folder still contains models. Delete or move them first — deleting a folder never cascades over model files.",
|
||||
"confirm": "[TODO: Translate] Delete folder"
|
||||
},
|
||||
"deleteFolderResult": {
|
||||
"success": "[TODO: Translate] Folder \"{name}\" deleted",
|
||||
"successWithFiles": "[TODO: Translate] Folder \"{name}\" deleted along with {count} other item(s)",
|
||||
"restored": "[TODO: Translate] Folder restored",
|
||||
"failed": "[TODO: Translate] Failed to delete folder: {message}",
|
||||
"notEmpty": "[TODO: Translate] This folder still contains models. Refresh the sidebar and try again.",
|
||||
"busy": "[TODO: Translate] A deletion is still pending inside this folder. Wait for the undo window to expire.",
|
||||
"unsupported": "[TODO: Translate] Folder deletion is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"dragDrop": {
|
||||
"unableToResolveRoot": "Impossible de déterminer le chemin de destination pour le déplacement.",
|
||||
"moveUnsupported": "Le déplacement n'est pas pris en charge pour cet élément.",
|
||||
|
||||
@@ -1263,6 +1263,26 @@
|
||||
"unsupported": "[TODO: Translate] Folder creation is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"deleteFolder": "[TODO: Translate] Delete folder",
|
||||
"deleteFolderModal": {
|
||||
"title": "[TODO: Translate] Delete folder?",
|
||||
"message": "[TODO: Translate] The folder and everything inside it will be permanently removed from disk.",
|
||||
"folderLabel": "[TODO: Translate] Folder",
|
||||
"emptyNote": "[TODO: Translate] This folder contains no models. Any other files it holds will be deleted too.",
|
||||
"notEmptyTitle": "[TODO: Translate] Folder is not empty",
|
||||
"notEmptyMessage": "[TODO: Translate] This folder still contains models. Delete or move them first — deleting a folder never cascades over model files.",
|
||||
"confirm": "[TODO: Translate] Delete folder"
|
||||
},
|
||||
"deleteFolderResult": {
|
||||
"success": "[TODO: Translate] Folder \"{name}\" deleted",
|
||||
"successWithFiles": "[TODO: Translate] Folder \"{name}\" deleted along with {count} other item(s)",
|
||||
"restored": "[TODO: Translate] Folder restored",
|
||||
"failed": "[TODO: Translate] Failed to delete folder: {message}",
|
||||
"notEmpty": "[TODO: Translate] This folder still contains models. Refresh the sidebar and try again.",
|
||||
"busy": "[TODO: Translate] A deletion is still pending inside this folder. Wait for the undo window to expire.",
|
||||
"unsupported": "[TODO: Translate] Folder deletion is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"dragDrop": {
|
||||
"unableToResolveRoot": "לא ניתן לקבוע את נתיב היעד להעברה.",
|
||||
"moveUnsupported": "העברה אינה נתמכת עבור פריט זה.",
|
||||
|
||||
@@ -1263,6 +1263,26 @@
|
||||
"unsupported": "[TODO: Translate] Folder creation is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"deleteFolder": "[TODO: Translate] Delete folder",
|
||||
"deleteFolderModal": {
|
||||
"title": "[TODO: Translate] Delete folder?",
|
||||
"message": "[TODO: Translate] The folder and everything inside it will be permanently removed from disk.",
|
||||
"folderLabel": "[TODO: Translate] Folder",
|
||||
"emptyNote": "[TODO: Translate] This folder contains no models. Any other files it holds will be deleted too.",
|
||||
"notEmptyTitle": "[TODO: Translate] Folder is not empty",
|
||||
"notEmptyMessage": "[TODO: Translate] This folder still contains models. Delete or move them first — deleting a folder never cascades over model files.",
|
||||
"confirm": "[TODO: Translate] Delete folder"
|
||||
},
|
||||
"deleteFolderResult": {
|
||||
"success": "[TODO: Translate] Folder \"{name}\" deleted",
|
||||
"successWithFiles": "[TODO: Translate] Folder \"{name}\" deleted along with {count} other item(s)",
|
||||
"restored": "[TODO: Translate] Folder restored",
|
||||
"failed": "[TODO: Translate] Failed to delete folder: {message}",
|
||||
"notEmpty": "[TODO: Translate] This folder still contains models. Refresh the sidebar and try again.",
|
||||
"busy": "[TODO: Translate] A deletion is still pending inside this folder. Wait for the undo window to expire.",
|
||||
"unsupported": "[TODO: Translate] Folder deletion is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"dragDrop": {
|
||||
"unableToResolveRoot": "移動先のパスを特定できません。",
|
||||
"moveUnsupported": "この項目の移動はサポートされていません。",
|
||||
|
||||
@@ -1263,6 +1263,26 @@
|
||||
"unsupported": "[TODO: Translate] Folder creation is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"deleteFolder": "[TODO: Translate] Delete folder",
|
||||
"deleteFolderModal": {
|
||||
"title": "[TODO: Translate] Delete folder?",
|
||||
"message": "[TODO: Translate] The folder and everything inside it will be permanently removed from disk.",
|
||||
"folderLabel": "[TODO: Translate] Folder",
|
||||
"emptyNote": "[TODO: Translate] This folder contains no models. Any other files it holds will be deleted too.",
|
||||
"notEmptyTitle": "[TODO: Translate] Folder is not empty",
|
||||
"notEmptyMessage": "[TODO: Translate] This folder still contains models. Delete or move them first — deleting a folder never cascades over model files.",
|
||||
"confirm": "[TODO: Translate] Delete folder"
|
||||
},
|
||||
"deleteFolderResult": {
|
||||
"success": "[TODO: Translate] Folder \"{name}\" deleted",
|
||||
"successWithFiles": "[TODO: Translate] Folder \"{name}\" deleted along with {count} other item(s)",
|
||||
"restored": "[TODO: Translate] Folder restored",
|
||||
"failed": "[TODO: Translate] Failed to delete folder: {message}",
|
||||
"notEmpty": "[TODO: Translate] This folder still contains models. Refresh the sidebar and try again.",
|
||||
"busy": "[TODO: Translate] A deletion is still pending inside this folder. Wait for the undo window to expire.",
|
||||
"unsupported": "[TODO: Translate] Folder deletion is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"dragDrop": {
|
||||
"unableToResolveRoot": "이동할 대상 경로를 확인할 수 없습니다.",
|
||||
"moveUnsupported": "이 항목은 이동을 지원하지 않습니다.",
|
||||
|
||||
@@ -1263,6 +1263,26 @@
|
||||
"unsupported": "[TODO: Translate] Folder creation is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"deleteFolder": "[TODO: Translate] Delete folder",
|
||||
"deleteFolderModal": {
|
||||
"title": "[TODO: Translate] Delete folder?",
|
||||
"message": "[TODO: Translate] The folder and everything inside it will be permanently removed from disk.",
|
||||
"folderLabel": "[TODO: Translate] Folder",
|
||||
"emptyNote": "[TODO: Translate] This folder contains no models. Any other files it holds will be deleted too.",
|
||||
"notEmptyTitle": "[TODO: Translate] Folder is not empty",
|
||||
"notEmptyMessage": "[TODO: Translate] This folder still contains models. Delete or move them first — deleting a folder never cascades over model files.",
|
||||
"confirm": "[TODO: Translate] Delete folder"
|
||||
},
|
||||
"deleteFolderResult": {
|
||||
"success": "[TODO: Translate] Folder \"{name}\" deleted",
|
||||
"successWithFiles": "[TODO: Translate] Folder \"{name}\" deleted along with {count} other item(s)",
|
||||
"restored": "[TODO: Translate] Folder restored",
|
||||
"failed": "[TODO: Translate] Failed to delete folder: {message}",
|
||||
"notEmpty": "[TODO: Translate] This folder still contains models. Refresh the sidebar and try again.",
|
||||
"busy": "[TODO: Translate] A deletion is still pending inside this folder. Wait for the undo window to expire.",
|
||||
"unsupported": "[TODO: Translate] Folder deletion is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"dragDrop": {
|
||||
"unableToResolveRoot": "Не удалось определить путь назначения для перемещения.",
|
||||
"moveUnsupported": "Перемещение этого элемента не поддерживается.",
|
||||
|
||||
@@ -1263,6 +1263,26 @@
|
||||
"unsupported": "[TODO: Translate] Folder creation is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"deleteFolder": "[TODO: Translate] Delete folder",
|
||||
"deleteFolderModal": {
|
||||
"title": "[TODO: Translate] Delete folder?",
|
||||
"message": "[TODO: Translate] The folder and everything inside it will be permanently removed from disk.",
|
||||
"folderLabel": "[TODO: Translate] Folder",
|
||||
"emptyNote": "[TODO: Translate] This folder contains no models. Any other files it holds will be deleted too.",
|
||||
"notEmptyTitle": "[TODO: Translate] Folder is not empty",
|
||||
"notEmptyMessage": "[TODO: Translate] This folder still contains models. Delete or move them first — deleting a folder never cascades over model files.",
|
||||
"confirm": "[TODO: Translate] Delete folder"
|
||||
},
|
||||
"deleteFolderResult": {
|
||||
"success": "[TODO: Translate] Folder \"{name}\" deleted",
|
||||
"successWithFiles": "[TODO: Translate] Folder \"{name}\" deleted along with {count} other item(s)",
|
||||
"restored": "[TODO: Translate] Folder restored",
|
||||
"failed": "[TODO: Translate] Failed to delete folder: {message}",
|
||||
"notEmpty": "[TODO: Translate] This folder still contains models. Refresh the sidebar and try again.",
|
||||
"busy": "[TODO: Translate] A deletion is still pending inside this folder. Wait for the undo window to expire.",
|
||||
"unsupported": "[TODO: Translate] Folder deletion is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"dragDrop": {
|
||||
"unableToResolveRoot": "无法确定移动的目标路径。",
|
||||
"moveUnsupported": "此条目不支持移动。",
|
||||
|
||||
@@ -1263,6 +1263,26 @@
|
||||
"unsupported": "[TODO: Translate] Folder creation is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"deleteFolder": "[TODO: Translate] Delete folder",
|
||||
"deleteFolderModal": {
|
||||
"title": "[TODO: Translate] Delete folder?",
|
||||
"message": "[TODO: Translate] The folder and everything inside it will be permanently removed from disk.",
|
||||
"folderLabel": "[TODO: Translate] Folder",
|
||||
"emptyNote": "[TODO: Translate] This folder contains no models. Any other files it holds will be deleted too.",
|
||||
"notEmptyTitle": "[TODO: Translate] Folder is not empty",
|
||||
"notEmptyMessage": "[TODO: Translate] This folder still contains models. Delete or move them first — deleting a folder never cascades over model files.",
|
||||
"confirm": "[TODO: Translate] Delete folder"
|
||||
},
|
||||
"deleteFolderResult": {
|
||||
"success": "[TODO: Translate] Folder \"{name}\" deleted",
|
||||
"successWithFiles": "[TODO: Translate] Folder \"{name}\" deleted along with {count} other item(s)",
|
||||
"restored": "[TODO: Translate] Folder restored",
|
||||
"failed": "[TODO: Translate] Failed to delete folder: {message}",
|
||||
"notEmpty": "[TODO: Translate] This folder still contains models. Refresh the sidebar and try again.",
|
||||
"busy": "[TODO: Translate] A deletion is still pending inside this folder. Wait for the undo window to expire.",
|
||||
"unsupported": "[TODO: Translate] Folder deletion is not supported on this page",
|
||||
"noRoot": "[TODO: Translate] No model root is configured"
|
||||
},
|
||||
"dragDrop": {
|
||||
"unableToResolveRoot": "無法確定移動的目標路徑。",
|
||||
"moveUnsupported": "此項目不支援移動。",
|
||||
|
||||
Reference in New Issue
Block a user