Compare commits

...

2 Commits

Author SHA1 Message Date
Will Miao
3c83e78d9f feat(ui): auto-newline after pasting URL in download and batch-import textareas
Extract auto-newline-on-paste logic into shared setupAutoNewlineOnPaste() utility in uiHelpers.js.
Apply it to both the Download modal (modelUrl) and Batch Import modal (batchUrlInput)
textarea, so users can paste multiple URLs in succession without manually pressing Enter.
2026-07-02 10:53:33 +08:00
Will Miao
d7291f73c9 fix(download): recognize civitai.red and civitai.green URLs in batch download (#1003) 2026-07-02 10:28:03 +08:00
4 changed files with 60 additions and 5 deletions

View File

@@ -1,5 +1,5 @@
import { modalManager } from './ModalManager.js';
import { showToast } from '../utils/uiHelpers.js';
import { showToast, setupAutoNewlineOnPaste } from '../utils/uiHelpers.js';
import { translate } from '../utils/i18nHelpers.js';
import { WS_ENDPOINTS } from '../api/apiConfig.js';
import { getStorageItem, setStorageItem } from '../utils/storageHelpers.js';
@@ -43,6 +43,9 @@ export class BatchImportManager {
setStorageItem('batch_import_skip_no_metadata', e.target.checked);
});
}
// Auto-append newline after pasting a URL in the batch URL input
setupAutoNewlineOnPaste('batchUrlInput');
}
/**

View File

@@ -1,5 +1,5 @@
import { modalManager } from './ModalManager.js';
import { showToast } from '../utils/uiHelpers.js';
import { showToast, setupAutoNewlineOnPaste } from '../utils/uiHelpers.js';
import { state } from '../state/index.js';
import { LoadingManager } from './LoadingManager.js';
import { getModelApiClient, resetAndReload } from '../api/modelApiFactory.js';
@@ -107,7 +107,8 @@ export class DownloadManager {
// Default path toggle handler
document.getElementById('useDefaultPath').addEventListener('change', this.handleToggleDefaultPath);
// Auto-append newline after pasting a URL so users can paste multiple URLs in succession
setupAutoNewlineOnPaste('modelUrl');
}
updateModalLabels() {
@@ -463,8 +464,8 @@ export class DownloadManager {
const trimmed = url.trim();
if (!trimmed) return null;
// CivitAI
if (/civitai\.com\/models\//i.test(trimmed) || /civitaiarchive|civarchive/i.test(trimmed)) {
// CivitAI — matches civitai.com, civitai.red, civitai.green, etc.
if (/civitai\.(?:com|red|green)\/models\//i.test(trimmed) || /civitaiarchive|civarchive/i.test(trimmed)) {
// Will be parsed by existing CivitAI logic
return { type: 'civitai' };
}

View File

@@ -1482,3 +1482,40 @@ export async function openExampleImagesFolder(modelHash) {
return false;
}
}
/**
* Set up a paste handler on a textarea that automatically appends a newline
* after pasted content that looks like a URL (http/https). This lets users
* paste multiple URLs one after another without manually pressing Enter.
* @param {string} textareaId - The id of the textarea element
*/
export function setupAutoNewlineOnPaste(textareaId) {
const el = document.getElementById(textareaId);
if (!el || el.tagName !== 'TEXTAREA') return;
el.addEventListener('paste', (e) => {
const pastedText = (e.clipboardData || window.clipboardData).getData('text');
// Only apply to text that starts with http:// or https://
if (/^https?:\/\//.test(pastedText) && !pastedText.endsWith('\n')) {
e.preventDefault();
const start = el.selectionStart;
const end = el.selectionEnd;
const text = el.value;
const before = text.substring(0, start);
const after = text.substring(end);
// Append newline after the pasted URL
const modifiedText = pastedText + '\n';
el.value = before + modifiedText + after;
// Move cursor to just after the inserted text
const newCursorPos = start + modifiedText.length;
el.selectionStart = el.selectionEnd = newCursorPos;
// Trigger input event so any listeners stay in sync
el.dispatchEvent(new Event('input', { bubbles: true }));
}
// Non-URL text or text already ending with \n — let default paste happen
});
}

View File

@@ -62,6 +62,20 @@ describe('DownloadManager.detectUrlType — HF URL detection', () => {
expect(result).toEqual({ type: 'civitai' });
});
it('detects CivitAI URL on civitai.red domain', () => {
const result = DownloadManager.detectUrlType(
'https://civitai.red/models/12345/my-model'
);
expect(result).toEqual({ type: 'civitai' });
});
it('detects CivitAI URL on civitai.green domain', () => {
const result = DownloadManager.detectUrlType(
'https://civitai.green/models/67890/another-model'
);
expect(result).toEqual({ type: 'civitai' });
});
it('detects CivArchive URL', () => {
const result = DownloadManager.detectUrlType(
'https://civarchive.com/models/456'