mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-08-14 09:43:22 -03:00
refactor(delete): make undo unconditional, remove undo toggle and button delay
- Remove delete_undo_enabled setting (backend default, frontend state, settings modal UI, 10 locales); staged deletes with 30s undo are now the only delete path and stale settings keys are silently ignored - Remove the 1500ms delete-button arm delay (armDeleteButton) from all delete modals; misclicks are recoverable via the undo toast - Delete modal always shows the recoverable warning - Log the first staged file path in staging log lines for easier support
This commit is contained in:
@@ -203,7 +203,7 @@ export class BaseModelApiClient {
|
||||
}
|
||||
const batchId = data.batch_id || null;
|
||||
if (!batchId) {
|
||||
// Not staged (undo disabled or staging failed): keep the legacy toast.
|
||||
// Not staged (staging failed): keep the legacy toast.
|
||||
// When staged, the caller shows the undo action toast instead.
|
||||
showToast('toast.api.deleteSuccess', { type: this.apiConfig.config.displayName }, 'success');
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Duplicates Manager Component
|
||||
import { showToast, showActionToast } from '../utils/uiHelpers.js';
|
||||
import { handleUndoDelete } from '../utils/undoHelpers.js';
|
||||
import { armDeleteButton } from '../utils/modalUtils.js';
|
||||
import { translate } from '../utils/i18nHelpers.js';
|
||||
import { RecipeCard } from './RecipeCard.js';
|
||||
import { state, getCurrentPageState } from '../state/index.js';
|
||||
@@ -449,7 +448,6 @@ export class DuplicatesManager {
|
||||
|
||||
// Use the modal manager to show the confirmation modal
|
||||
modalManager.showModal('duplicateDeleteModal');
|
||||
armDeleteButton(document.getElementById('duplicateDeleteModal'));
|
||||
} catch (error) {
|
||||
console.error('Error preparing delete:', error);
|
||||
showToast('toast.duplicates.deleteError', { message: error.message }, 'error');
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Model Duplicates Manager Component for LoRAs and Checkpoints
|
||||
import { showToast, showActionToast } from '../utils/uiHelpers.js';
|
||||
import { handleUndoDelete } from '../utils/undoHelpers.js';
|
||||
import { armDeleteButton } from '../utils/modalUtils.js';
|
||||
import { translate } from '../utils/i18nHelpers.js';
|
||||
import { state, getCurrentPageState } from '../state/index.js';
|
||||
import { formatDate } from '../utils/formatters.js';
|
||||
@@ -703,7 +702,6 @@ export class ModelDuplicatesManager {
|
||||
|
||||
// Use the modal manager to show the confirmation modal
|
||||
modalManager.showModal('modelDuplicateDeleteModal');
|
||||
armDeleteButton(document.getElementById('modelDuplicateDeleteModal'));
|
||||
} catch (error) {
|
||||
console.error('Error preparing delete:', error);
|
||||
showToast('toast.duplicates.deleteError', { message: error.message }, 'error');
|
||||
|
||||
@@ -9,7 +9,6 @@ import { bulkManager } from '../managers/BulkManager.js';
|
||||
import { NSFW_LEVELS, getBaseModelAbbreviation, getMatureBlurThreshold } from '../utils/constants.js';
|
||||
import { translate } from '../utils/i18nHelpers.js';
|
||||
import { handleUndoDelete } from '../utils/undoHelpers.js';
|
||||
import { armDeleteButton } from '../utils/modalUtils.js';
|
||||
|
||||
class RecipeCard {
|
||||
constructor(recipe, clickHandler) {
|
||||
@@ -366,7 +365,7 @@ class RecipeCard {
|
||||
</div>
|
||||
<div class="delete-info">
|
||||
<h3>${this.recipe.title}</h3>
|
||||
<p>This action cannot be undone.</p>
|
||||
<p>This action can be undone for 30 seconds.</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="delete-note">Note: Deleting this recipe will not affect the LoRA files used in it.</p>
|
||||
@@ -378,13 +377,8 @@ class RecipeCard {
|
||||
`;
|
||||
|
||||
// Show the modal with custom content and setup callbacks
|
||||
let deleteArmTimer = null;
|
||||
modalManager.showModal('deleteModal', deleteModalContent, () => {
|
||||
// This is the onClose callback
|
||||
if (deleteArmTimer) {
|
||||
clearTimeout(deleteArmTimer);
|
||||
deleteArmTimer = null;
|
||||
}
|
||||
const deleteModal = document.getElementById('deleteModal');
|
||||
const deleteBtn = deleteModal.querySelector('.delete-btn');
|
||||
deleteBtn.textContent = 'Delete';
|
||||
@@ -404,8 +398,6 @@ class RecipeCard {
|
||||
cancelBtn.onclick = () => modalManager.closeModal('deleteModal');
|
||||
deleteBtn.onclick = () => this.confirmDeleteRecipe();
|
||||
|
||||
deleteArmTimer = armDeleteButton(deleteModal);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error showing delete confirmation:', error);
|
||||
showToast('toast.recipes.deleteConfirmationError', {}, 'error');
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { state, getCurrentPageState } from '../state/index.js';
|
||||
import { showToast, showActionToast, copyToClipboard, sendLoraToWorkflow, sendEmbeddingToWorkflow, buildLoraSyntax, getNSFWLevelName } from '../utils/uiHelpers.js';
|
||||
import { handleUndoDelete } from '../utils/undoHelpers.js';
|
||||
import { armDeleteButton } from '../utils/modalUtils.js';
|
||||
import { updateCardsForBulkMode } from '../components/shared/ModelCard.js';
|
||||
import { modalManager } from './ModalManager.js';
|
||||
import { getModelApiClient, resetAndReload } from '../api/modelApiFactory.js';
|
||||
@@ -630,7 +629,6 @@ export class BulkManager {
|
||||
}
|
||||
|
||||
modalManager.showModal('bulkDeleteModal');
|
||||
armDeleteButton(document.getElementById('bulkDeleteModal'));
|
||||
}
|
||||
|
||||
async confirmBulkDelete() {
|
||||
|
||||
@@ -1111,12 +1111,6 @@ export class SettingsManager {
|
||||
includeTriggerWordsCheckbox.checked = state.global.settings.include_trigger_words || false;
|
||||
}
|
||||
|
||||
// Set delete undo setting (defaults to enabled)
|
||||
const deleteUndoEnabledCheckbox = document.getElementById('deleteUndoEnabled');
|
||||
if (deleteUndoEnabledCheckbox) {
|
||||
deleteUndoEnabledCheckbox.checked = state.global.settings.delete_undo_enabled ?? true;
|
||||
}
|
||||
|
||||
// Set lora syntax format
|
||||
const loraSyntaxFormatSelect = document.getElementById('loraSyntaxFormat');
|
||||
if (loraSyntaxFormatSelect) {
|
||||
|
||||
@@ -58,7 +58,6 @@ const DEFAULT_SETTINGS_BASE = Object.freeze({
|
||||
strip_lora_on_copy: false,
|
||||
use_new_license_icons: true,
|
||||
group_by_model: false,
|
||||
delete_undo_enabled: true,
|
||||
llm_provider: 'openai',
|
||||
llm_api_key: '',
|
||||
llm_api_base: '',
|
||||
|
||||
@@ -3,31 +3,11 @@ import { getModelApiClient, resetAndReload } from '../api/modelApiFactory.js';
|
||||
import { showActionToast } from './uiHelpers.js';
|
||||
import { translate } from './i18nHelpers.js';
|
||||
import { handleUndoDelete } from './undoHelpers.js';
|
||||
import { state } from '../state/index.js';
|
||||
import { formatFileSize } from '../components/shared/utils.js';
|
||||
|
||||
const DELETE_BUTTON_ARM_DELAY_MS = 1500;
|
||||
|
||||
let pendingDeletePath = null;
|
||||
let pendingDeleteName = null;
|
||||
let pendingExcludePath = null;
|
||||
let pendingDeleteArmTimer = null;
|
||||
|
||||
// Delay-activates every delete button inside a delete-confirmation modal so a
|
||||
// misclick in the first moments after opening cannot confirm the deletion.
|
||||
// Returns the pending timeout id so callers can cancel it when the modal closes early.
|
||||
export function armDeleteButton(modalElement, delayMs = DELETE_BUTTON_ARM_DELAY_MS) {
|
||||
if (!modalElement) return null;
|
||||
|
||||
const deleteButtons = modalElement.querySelectorAll('.delete-btn');
|
||||
if (!deleteButtons.length) return null;
|
||||
|
||||
deleteButtons.forEach((button) => { button.disabled = true; });
|
||||
|
||||
return setTimeout(() => {
|
||||
deleteButtons.forEach((button) => { button.disabled = false; });
|
||||
}, delayMs);
|
||||
}
|
||||
|
||||
export function showDeleteModal(filePath) {
|
||||
pendingDeletePath = filePath;
|
||||
@@ -41,10 +21,6 @@ export function showDeleteModal(filePath) {
|
||||
const modal = modalManager.getModal('deleteModal').element;
|
||||
const modelInfo = modal.querySelector('.delete-model-info');
|
||||
|
||||
const undoEnabled = state.global?.settings?.delete_undo_enabled;
|
||||
const warningKey = undoEnabled
|
||||
? 'modals.deleteModel.recoverableWarning'
|
||||
: 'modals.deleteModel.permanentWarning';
|
||||
const fileSize = card?.dataset.file_size;
|
||||
const sizeLine = fileSize
|
||||
? `<br>${translate('modals.deleteModel.freesSpace', { size: formatFileSize(parseInt(fileSize, 10)) })}`
|
||||
@@ -55,11 +31,10 @@ export function showDeleteModal(filePath) {
|
||||
<br>
|
||||
<strong>File:</strong> ${filePath}
|
||||
<br>
|
||||
${translate(warningKey)}${sizeLine}
|
||||
${translate('modals.deleteModel.recoverableWarning')}${sizeLine}
|
||||
`;
|
||||
|
||||
modalManager.showModal('deleteModal');
|
||||
pendingDeleteArmTimer = armDeleteButton(modal);
|
||||
}
|
||||
|
||||
export async function confirmDelete() {
|
||||
@@ -90,10 +65,6 @@ export async function confirmDelete() {
|
||||
|
||||
export function closeDeleteModal() {
|
||||
modalManager.closeModal('deleteModal');
|
||||
if (pendingDeleteArmTimer) {
|
||||
clearTimeout(pendingDeleteArmTimer);
|
||||
pendingDeleteArmTimer = null;
|
||||
}
|
||||
pendingDeletePath = null;
|
||||
pendingDeleteName = null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user