Files
ComfyUI-Lora-Manager/templates/components/modals/download_modal.html
hein 4e3ede23b7 feat: batch URL download for LoRA models
Add multi-URL batch download support to the download modal.
Users can paste multiple CivitAI URLs (one per line) in a textarea,
preview all parsed models in a compact list, optionally change versions
per model, select a unified download path, and batch download sequentially.

Single URL behavior is preserved unchanged.

Changes:
- Replace single-line input with textarea for multi-URL input
- Add batch preview step with compact list (thumbnail, version, size)
- Per-item version editing via existing version selector
- Batch download with WebSocket progress tracking (reuses existing infra)
- URL deduplication by model ID, preserving paste order
- Invalid URLs shown inline with remove option
- Fix: prevent click listener accumulation in showVersionStep

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-20 11:37:36 +08:00

108 lines
5.6 KiB
HTML

<!-- Unified Download Modal for all model types -->
<div id="downloadModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<button class="close" id="closeDownloadModal">&times;</button>
<h2 id="downloadModalTitle">{{ t('modals.download.title') }}</h2>
</div>
<!-- Step 1: URL Input -->
<div class="download-step" id="urlStep">
<div class="input-group">
<label for="modelUrl" id="modelUrlLabel">{{ t('modals.download.url') }}:</label>
<textarea id="modelUrl" rows="5" placeholder="{{ t('modals.download.placeholder') }}"></textarea>
<div class="error-message" id="urlError"></div>
</div>
<div class="modal-actions">
<button class="primary-btn" id="nextFromUrl">{{ t('common.actions.next') }}</button>
</div>
</div>
<!-- Step 2: Batch Preview (multi-URL mode) -->
<div class="download-step" id="batchPreviewStep" style="display: none;">
<div class="batch-preview-list" id="batchPreviewList">
<!-- Batch items will be inserted here dynamically -->
</div>
<div class="modal-actions">
<button class="secondary-btn" id="backToUrlFromBatchBtn">{{ t('common.actions.back') }}</button>
<button class="primary-btn" id="nextFromBatchBtn">{{ t('common.actions.next') }}</button>
</div>
</div>
<!-- Step 3: Version Selection (single-URL or per-item editing) -->
<div class="download-step" id="versionStep" style="display: none;">
<div class="version-list" id="versionList">
<!-- Versions will be inserted here dynamically -->
</div>
<div class="modal-actions">
<button class="secondary-btn" id="backToUrlBtn">{{ t('common.actions.back') }}</button>
<button class="primary-btn" id="nextFromVersion">{{ t('common.actions.next') }}</button>
</div>
</div>
<!-- Step 3: Location Selection -->
<div class="download-step" id="locationStep" style="display: none;">
<div class="location-selection">
<!-- Path preview with inline toggle -->
<div class="path-preview">
<div class="path-preview-header">
<label>{{ t('modals.download.locationPreview') }}:</label>
<div class="inline-toggle-container" title="{{ t('modals.download.useDefaultPathTooltip') }}">
<span class="inline-toggle-label">{{ t('modals.download.useDefaultPath') }}</span>
<div class="toggle-switch">
<input type="checkbox" id="useDefaultPath">
<label for="useDefaultPath" class="toggle-slider"></label>
</div>
</div>
</div>
<div class="path-display" id="targetPathDisplay">
<span class="path-text">{{ t('modals.download.selectRootDirectory') }}</span>
</div>
</div>
<!-- Model Root Selection (always visible) -->
<div class="input-group">
<label for="modelRoot" id="modelRootLabel">{{ t('modals.download.selectModelRoot') }}</label>
<select id="modelRoot"></select>
</div>
<!-- Manual Path Selection (hidden when using default path) -->
<div class="manual-path-selection" id="manualPathSelection">
<!-- Path input with autocomplete -->
<div class="input-group">
<label for="folderPath">{{ t('modals.download.targetFolderPath') }}</label>
<div class="path-input-container">
<input type="text" id="folderPath" placeholder="{{ t('modals.download.pathPlaceholder') }}" autocomplete="off" />
<button type="button" id="createFolderBtn" class="create-folder-btn" title="{{ t('modals.download.createNewFolder') }}">
<i class="fas fa-plus"></i>
</button>
</div>
<div class="path-suggestions" id="pathSuggestions" style="display: none;"></div>
</div>
<!-- Breadcrumb navigation -->
<div class="breadcrumb-nav" id="breadcrumbNav">
<span class="breadcrumb-item root" data-path="">
<i class="fas fa-home"></i> {{ t('modals.download.root') }}
</span>
</div>
<!-- Hierarchical folder tree -->
<div class="input-group">
<label>{{ t('modals.download.browseFolders') }}</label>
<div class="folder-tree-container">
<div class="folder-tree" id="folderTree">
<!-- Tree will be loaded dynamically -->
</div>
</div>
</div>
</div>
</div>
<div class="modal-actions">
<button class="secondary-btn" id="backToVersionsBtn">{{ t('common.actions.back') }}</button>
<button class="primary-btn" id="startDownloadBtn">{{ t('modals.download.download') }}</button>
</div>
</div>
</div>
</div>