Spaces:
Paused
Paused
Upload 5 files
Browse files
ui/components/generation_panel.py
CHANGED
|
@@ -8,10 +8,12 @@ import gradio as gr
|
|
| 8 |
from utils.constants import (
|
| 9 |
MODEL_CHOICES,
|
| 10 |
SAMPLER_CHOICES,
|
|
|
|
| 11 |
DEFAULT_MODEL,
|
| 12 |
DEFAULT_STEPS,
|
| 13 |
DEFAULT_SCALE,
|
| 14 |
-
DEFAULT_SAMPLER
|
|
|
|
| 15 |
)
|
| 16 |
|
| 17 |
|
|
@@ -21,7 +23,7 @@ def create_generation_panel():
|
|
| 21 |
|
| 22 |
Returns:
|
| 23 |
Dict with control components:
|
| 24 |
-
- model, steps, scale, cfg_rescale, sampler, seed
|
| 25 |
Note: Resolution is now in the Prompt header, not here
|
| 26 |
"""
|
| 27 |
with gr.Group():
|
|
@@ -71,6 +73,21 @@ def create_generation_panel():
|
|
| 71 |
elem_id="naia-sampler"
|
| 72 |
)
|
| 73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
# Seed row
|
| 75 |
seed = gr.Number(
|
| 76 |
value=0,
|
|
@@ -87,5 +104,7 @@ def create_generation_panel():
|
|
| 87 |
"scale": scale,
|
| 88 |
"cfg_rescale": cfg_rescale,
|
| 89 |
"sampler": sampler,
|
|
|
|
|
|
|
| 90 |
"seed": seed
|
| 91 |
}
|
|
|
|
| 8 |
from utils.constants import (
|
| 9 |
MODEL_CHOICES,
|
| 10 |
SAMPLER_CHOICES,
|
| 11 |
+
NOISE_SCHEDULE_CHOICES,
|
| 12 |
DEFAULT_MODEL,
|
| 13 |
DEFAULT_STEPS,
|
| 14 |
DEFAULT_SCALE,
|
| 15 |
+
DEFAULT_SAMPLER,
|
| 16 |
+
DEFAULT_NOISE_SCHEDULE
|
| 17 |
)
|
| 18 |
|
| 19 |
|
|
|
|
| 23 |
|
| 24 |
Returns:
|
| 25 |
Dict with control components:
|
| 26 |
+
- model, steps, scale, cfg_rescale, sampler, noise_schedule, variety_plus, seed
|
| 27 |
Note: Resolution is now in the Prompt header, not here
|
| 28 |
"""
|
| 29 |
with gr.Group():
|
|
|
|
| 73 |
elem_id="naia-sampler"
|
| 74 |
)
|
| 75 |
|
| 76 |
+
# Noise Schedule and VAR+ row
|
| 77 |
+
with gr.Row():
|
| 78 |
+
noise_schedule = gr.Dropdown(
|
| 79 |
+
choices=NOISE_SCHEDULE_CHOICES,
|
| 80 |
+
value=DEFAULT_NOISE_SCHEDULE,
|
| 81 |
+
label="Noise Schedule",
|
| 82 |
+
elem_id="naia-noise-schedule"
|
| 83 |
+
)
|
| 84 |
+
|
| 85 |
+
variety_plus = gr.Checkbox(
|
| 86 |
+
value=False,
|
| 87 |
+
label="VAR+",
|
| 88 |
+
elem_id="naia-variety-plus"
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
# Seed row
|
| 92 |
seed = gr.Number(
|
| 93 |
value=0,
|
|
|
|
| 104 |
"scale": scale,
|
| 105 |
"cfg_rescale": cfg_rescale,
|
| 106 |
"sampler": sampler,
|
| 107 |
+
"noise_schedule": noise_schedule,
|
| 108 |
+
"variety_plus": variety_plus,
|
| 109 |
"seed": seed
|
| 110 |
}
|
ui/components/output_panel.py
CHANGED
|
@@ -71,6 +71,13 @@ def create_generation_info_panel():
|
|
| 71 |
elem_id="naia-processed-negative"
|
| 72 |
)
|
| 73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
return {
|
| 75 |
"info": output_info,
|
| 76 |
"processed_prompt": processed_prompt,
|
|
|
|
| 71 |
elem_id="naia-processed-negative"
|
| 72 |
)
|
| 73 |
|
| 74 |
+
# Useful external links
|
| 75 |
+
gr.Markdown("""
|
| 76 |
+
* If you need parameters inspection, visit: [novelai.net/inspect](https://novelai.net/inspect)
|
| 77 |
+
* If you need tags wiki, visit: [danbooru.donmai.us/wiki_pages/tag_groups](https://danbooru.donmai.us/wiki_pages/tag_groups)
|
| 78 |
+
* If you need image to danbooru tags, visit: [SmilingWolf/wd-tagger](https://huggingface.co/spaces/SmilingWolf/wd-tagger)
|
| 79 |
+
""", elem_id="naia-gen-info-links")
|
| 80 |
+
|
| 81 |
return {
|
| 82 |
"info": output_info,
|
| 83 |
"processed_prompt": processed_prompt,
|
ui/components/quick_search.py
CHANGED
|
@@ -87,7 +87,7 @@ def create_quick_search():
|
|
| 87 |
recommended_tags = gr.Dataframe(
|
| 88 |
headers=["Tag", "Count", "+", "-"],
|
| 89 |
datatype=["str", "number", "str", "str"],
|
| 90 |
-
|
| 91 |
row_count=(10, "dynamic"),
|
| 92 |
interactive=False,
|
| 93 |
wrap=True,
|
|
|
|
| 87 |
recommended_tags = gr.Dataframe(
|
| 88 |
headers=["Tag", "Count", "+", "-"],
|
| 89 |
datatype=["str", "number", "str", "str"],
|
| 90 |
+
column_count=(4, "fixed"),
|
| 91 |
row_count=(10, "dynamic"),
|
| 92 |
interactive=False,
|
| 93 |
wrap=True,
|
ui/components/settings_panel.py
CHANGED
|
@@ -178,7 +178,6 @@ LOCALSTORAGE_JS = """
|
|
| 178 |
if (generateStartTime) {
|
| 179 |
const elapsed = (Date.now() - generateStartTime) / 1000;
|
| 180 |
addResponseTime(elapsed);
|
| 181 |
-
console.log('NAIA-WEB: Response time:', elapsed.toFixed(2), 's, Average:', getAverageResponseTime().toFixed(2), 's');
|
| 182 |
}
|
| 183 |
|
| 184 |
if (timerInterval) {
|
|
@@ -203,11 +202,13 @@ LOCALSTORAGE_JS = """
|
|
| 203 |
const autoSaveContainer = document.querySelector('#naia-auto-save');
|
| 204 |
const autoSaveCheckbox = autoSaveContainer ? autoSaveContainer.querySelector('input[type="checkbox"]') : null;
|
| 205 |
if (autoSaveCheckbox && autoSaveCheckbox.checked) {
|
| 206 |
-
//
|
| 207 |
-
|
|
|
|
|
|
|
|
|
|
| 208 |
downloadBtn.click();
|
| 209 |
-
|
| 210 |
-
}, 500);
|
| 211 |
}
|
| 212 |
}
|
| 213 |
}
|
|
@@ -264,7 +265,6 @@ LOCALSTORAGE_JS = """
|
|
| 264 |
input.value = savedToken;
|
| 265 |
input.dispatchEvent(new Event('input', { bubbles: true }));
|
| 266 |
input.dispatchEvent(new Event('change', { bubbles: true }));
|
| 267 |
-
console.log('NAIA-WEB: Token loaded from localStorage');
|
| 268 |
}
|
| 269 |
} catch (e) {
|
| 270 |
console.error('NAIA-WEB: Error loading token:', e);
|
|
@@ -387,6 +387,8 @@ LOCALSTORAGE_JS = """
|
|
| 387 |
scale: toFloat(getInputValue('#naia-scale')),
|
| 388 |
cfg_rescale: toFloat(getInputValue('#naia-cfg-rescale')),
|
| 389 |
sampler: getInputValue('#naia-sampler'),
|
|
|
|
|
|
|
| 390 |
// Random resolution
|
| 391 |
random_resolution: getInputValue('#naia-random-resolution', 'checkbox'),
|
| 392 |
enabled_resolutions: getCheckboxGroupValues('#naia-res-checkboxes'),
|
|
@@ -417,10 +419,6 @@ LOCALSTORAGE_JS = """
|
|
| 417 |
|
| 418 |
try {
|
| 419 |
localStorage.setItem(SETTINGS_KEY, JSON.stringify(settings));
|
| 420 |
-
console.log('NAIA-WEB: Settings saved', settings.char_slots ? `(${settings.char_slots.length} char slots)` : '(no char slots)');
|
| 421 |
-
if (settings.char_slots && settings.char_slots.length > 0) {
|
| 422 |
-
console.log('NAIA-WEB: Saved char slots:', JSON.stringify(settings.char_slots));
|
| 423 |
-
}
|
| 424 |
} catch (e) {
|
| 425 |
console.error('NAIA-WEB: Error saving settings:', e);
|
| 426 |
}
|
|
@@ -481,7 +479,6 @@ LOCALSTORAGE_JS = """
|
|
| 481 |
renderFromCache() {
|
| 482 |
const grid = document.getElementById('naia-qs-tag-grid');
|
| 483 |
if (!grid) {
|
| 484 |
-
console.log('NAIA-WEB QuickSearch: Grid not ready, will render when accordion opens');
|
| 485 |
return;
|
| 486 |
}
|
| 487 |
|
|
@@ -510,7 +507,6 @@ LOCALSTORAGE_JS = """
|
|
| 510 |
}
|
| 511 |
|
| 512 |
this.updatePageInfo();
|
| 513 |
-
console.log(`NAIA-WEB QuickSearch: Rendered page ${this.currentPage}/${this.totalPages} (${this.currentTags.length} tags)`);
|
| 514 |
},
|
| 515 |
|
| 516 |
// Show popup to choose Include or Exclude (positioned above grid)
|
|
@@ -582,7 +578,6 @@ LOCALSTORAGE_JS = """
|
|
| 582 |
actionInput.value = `${action}:${tag}`;
|
| 583 |
actionInput.dispatchEvent(new Event('input', { bubbles: true }));
|
| 584 |
actionInput.dispatchEvent(new Event('change', { bubbles: true }));
|
| 585 |
-
console.log(`NAIA-WEB QuickSearch: Tag action ${action}:${tag}`);
|
| 586 |
}
|
| 587 |
},
|
| 588 |
|
|
@@ -610,16 +605,11 @@ LOCALSTORAGE_JS = """
|
|
| 610 |
}
|
| 611 |
|
| 612 |
// Add click listener - just try to render after click
|
| 613 |
-
// renderWithRetry will handle checking if grid exists
|
| 614 |
button.addEventListener('click', () => {
|
| 615 |
-
console.log('NAIA-WEB QuickSearch: Accordion clicked');
|
| 616 |
if (self.dataReady) {
|
| 617 |
-
// Try to render with retries (accordion might need time to expand)
|
| 618 |
self.renderWithRetry(5);
|
| 619 |
}
|
| 620 |
});
|
| 621 |
-
|
| 622 |
-
console.log('NAIA-WEB QuickSearch: Click listener set up on accordion');
|
| 623 |
};
|
| 624 |
|
| 625 |
checkAccordion();
|
|
@@ -688,16 +678,10 @@ LOCALSTORAGE_JS = """
|
|
| 688 |
|
| 689 |
// Initialize autocomplete on all target textareas
|
| 690 |
init() {
|
| 691 |
-
console.log('NAIA-WEB Autocomplete: Starting initialization...');
|
| 692 |
this.createDropdown();
|
| 693 |
-
console.log('NAIA-WEB Autocomplete: Dropdown created');
|
| 694 |
-
// Debug: show all textareas on page
|
| 695 |
-
this.debugListTextareas();
|
| 696 |
this.attachToTargets();
|
| 697 |
-
console.log('NAIA-WEB Autocomplete: Attached to targets');
|
| 698 |
// Re-attach when new elements appear (for dynamic char slots)
|
| 699 |
this.setupMutationObserver();
|
| 700 |
-
console.log('NAIA-WEB Autocomplete: Initialized successfully');
|
| 701 |
},
|
| 702 |
|
| 703 |
// Create the dropdown element
|
|
@@ -736,9 +720,6 @@ LOCALSTORAGE_JS = """
|
|
| 736 |
return container.querySelector('textarea');
|
| 737 |
},
|
| 738 |
|
| 739 |
-
// Track which IDs we've already reported as not found (to reduce log spam)
|
| 740 |
-
_notFoundReported: new Set(),
|
| 741 |
-
|
| 742 |
// Attach to all target textareas
|
| 743 |
attachToTargets() {
|
| 744 |
let attachedCount = 0;
|
|
@@ -748,11 +729,6 @@ LOCALSTORAGE_JS = """
|
|
| 748 |
if (textarea && !textarea.dataset.autocompleteAttached) {
|
| 749 |
this.attachToTextarea(textarea);
|
| 750 |
attachedCount++;
|
| 751 |
-
console.log('NAIA-WEB Autocomplete: Attached to #' + containerId);
|
| 752 |
-
this._notFoundReported.delete(containerId);
|
| 753 |
-
} else if (!textarea && !this._notFoundReported.has(containerId)) {
|
| 754 |
-
// Only log "not found" once per ID
|
| 755 |
-
this._notFoundReported.add(containerId);
|
| 756 |
}
|
| 757 |
}
|
| 758 |
|
|
@@ -763,12 +739,10 @@ LOCALSTORAGE_JS = """
|
|
| 763 |
if (promptTextarea && !promptTextarea.dataset.autocompleteAttached) {
|
| 764 |
this.attachToTextarea(promptTextarea);
|
| 765 |
attachedCount++;
|
| 766 |
-
console.log('NAIA-WEB Autocomplete: Attached to #naia-char-prompt-' + i);
|
| 767 |
}
|
| 768 |
if (negativeTextarea && !negativeTextarea.dataset.autocompleteAttached) {
|
| 769 |
this.attachToTextarea(negativeTextarea);
|
| 770 |
attachedCount++;
|
| 771 |
-
console.log('NAIA-WEB Autocomplete: Attached to #naia-char-negative-' + i);
|
| 772 |
}
|
| 773 |
}
|
| 774 |
|
|
@@ -777,11 +751,6 @@ LOCALSTORAGE_JS = """
|
|
| 777 |
if (charSearchTextarea && !charSearchTextarea.dataset.autocompleteAttached) {
|
| 778 |
this.attachToTextarea(charSearchTextarea);
|
| 779 |
attachedCount++;
|
| 780 |
-
console.log('NAIA-WEB Autocomplete: Attached to character search input');
|
| 781 |
-
}
|
| 782 |
-
|
| 783 |
-
if (attachedCount > 0) {
|
| 784 |
-
console.log('NAIA-WEB Autocomplete: Total attached:', attachedCount);
|
| 785 |
}
|
| 786 |
},
|
| 787 |
|
|
@@ -840,25 +809,12 @@ LOCALSTORAGE_JS = """
|
|
| 840 |
observer.observe(document.body, { childList: true, subtree: true });
|
| 841 |
},
|
| 842 |
|
| 843 |
-
// Debug: List all textareas on page
|
| 844 |
-
debugListTextareas() {
|
| 845 |
-
const textareas = document.querySelectorAll('textarea');
|
| 846 |
-
console.log('NAIA-WEB Autocomplete DEBUG: Found', textareas.length, 'textareas on page:');
|
| 847 |
-
textareas.forEach((ta, i) => {
|
| 848 |
-
const parent = ta.closest('[id]');
|
| 849 |
-
const parentId = parent ? parent.id : 'no-id-parent';
|
| 850 |
-
console.log(` [${i}] parent=#${parentId}, placeholder="${ta.placeholder || ''}"`.substring(0, 100));
|
| 851 |
-
});
|
| 852 |
-
},
|
| 853 |
-
|
| 854 |
// Handle input event
|
| 855 |
onInput(textarea) {
|
| 856 |
-
console.log('NAIA-WEB Autocomplete: Input event fired');
|
| 857 |
this.activeTextarea = textarea;
|
| 858 |
|
| 859 |
clearTimeout(this.debounceTimer);
|
| 860 |
this.debounceTimer = setTimeout(() => {
|
| 861 |
-
console.log('NAIA-WEB Autocomplete: Debounce triggered, calling search');
|
| 862 |
this.search(textarea);
|
| 863 |
}, this.DEBOUNCE_MS);
|
| 864 |
},
|
|
@@ -951,12 +907,10 @@ LOCALSTORAGE_JS = """
|
|
| 951 |
}
|
| 952 |
|
| 953 |
const tokenInfo = this.getCurrentToken(textarea);
|
| 954 |
-
const { token, isWeightValue
|
| 955 |
-
console.log('NAIA-WEB Autocomplete: Search called, token:', token, 'weightPrefix:', weightPrefix, 'weightSuffix:', weightSuffix);
|
| 956 |
|
| 957 |
// Skip autocomplete if editing a weight value (e.g., "0.5" in "0.5::tag")
|
| 958 |
if (isWeightValue) {
|
| 959 |
-
console.log('NAIA-WEB Autocomplete: Editing weight value, skipping');
|
| 960 |
this.close();
|
| 961 |
return;
|
| 962 |
}
|
|
@@ -965,42 +919,33 @@ LOCALSTORAGE_JS = """
|
|
| 965 |
this.currentTokenInfo = tokenInfo;
|
| 966 |
|
| 967 |
if (token.length < this.MIN_CHARS) {
|
| 968 |
-
console.log('NAIA-WEB Autocomplete: Token too short, closing');
|
| 969 |
this.close();
|
| 970 |
return;
|
| 971 |
}
|
| 972 |
|
| 973 |
// Determine search mode based on textarea context
|
| 974 |
this.currentSearchMode = this.getSearchMode(textarea);
|
| 975 |
-
console.log('NAIA-WEB Autocomplete: Search mode:', this.currentSearchMode);
|
| 976 |
|
| 977 |
// Trigger Gradio search via hidden input
|
| 978 |
// Format: "mode:query" (e.g., "no_character:blue" or "character_only:miku")
|
| 979 |
const searchContainer = document.getElementById('naia-autocomplete-query');
|
| 980 |
const searchInput = searchContainer ? searchContainer.querySelector('textarea, input') : null;
|
| 981 |
-
console.log('NAIA-WEB Autocomplete: Search input element:', searchInput);
|
| 982 |
if (searchInput) {
|
| 983 |
const queryWithMode = this.currentSearchMode + ':' + token;
|
| 984 |
searchInput.value = queryWithMode;
|
| 985 |
searchInput.dispatchEvent(new Event('input', { bubbles: true }));
|
| 986 |
-
console.log('NAIA-WEB Autocomplete: Dispatched search event for:', queryWithMode);
|
| 987 |
-
} else {
|
| 988 |
-
console.log('NAIA-WEB Autocomplete: ERROR - Search input not found! Container:', searchContainer);
|
| 989 |
}
|
| 990 |
},
|
| 991 |
|
| 992 |
// Receive results from Gradio (called from JS parameter)
|
| 993 |
setResults(results) {
|
| 994 |
-
console.log('NAIA-WEB Autocomplete: setResults called with:', results);
|
| 995 |
if (!results || results.length === 0) {
|
| 996 |
-
console.log('NAIA-WEB Autocomplete: No results, closing');
|
| 997 |
this.close();
|
| 998 |
return;
|
| 999 |
}
|
| 1000 |
|
| 1001 |
this.currentResults = results;
|
| 1002 |
this.selectedIndex = 0;
|
| 1003 |
-
console.log('NAIA-WEB Autocomplete: Rendering', results.length, 'results');
|
| 1004 |
this.renderDropdown();
|
| 1005 |
this.show();
|
| 1006 |
},
|
|
@@ -1116,7 +1061,6 @@ LOCALSTORAGE_JS = """
|
|
| 1116 |
const searchBtn = document.querySelector('#naia-char-search-btn');
|
| 1117 |
if (searchBtn) {
|
| 1118 |
searchBtn.click();
|
| 1119 |
-
console.log('NAIA-WEB Autocomplete: Clicked character search button');
|
| 1120 |
}
|
| 1121 |
}, 100);
|
| 1122 |
} else {
|
|
@@ -1259,7 +1203,6 @@ LOCALSTORAGE_JS = """
|
|
| 1259 |
|
| 1260 |
// Initialize after DOM ready with retry
|
| 1261 |
function initAutocompleteWithRetry(attempt = 1) {
|
| 1262 |
-
console.log('NAIA-WEB Autocomplete: Init attempt', attempt);
|
| 1263 |
Autocomplete.init();
|
| 1264 |
|
| 1265 |
// If no textareas attached and still have retries, try again
|
|
@@ -1290,7 +1233,6 @@ LOCALSTORAGE_JS = """
|
|
| 1290 |
// Move download button into image container
|
| 1291 |
if (!imageContainer.contains(downloadBtn)) {
|
| 1292 |
imageContainer.appendChild(downloadBtn);
|
| 1293 |
-
console.log('NAIA-WEB: Download button moved into image container');
|
| 1294 |
}
|
| 1295 |
}
|
| 1296 |
|
|
|
|
| 178 |
if (generateStartTime) {
|
| 179 |
const elapsed = (Date.now() - generateStartTime) / 1000;
|
| 180 |
addResponseTime(elapsed);
|
|
|
|
| 181 |
}
|
| 182 |
|
| 183 |
if (timerInterval) {
|
|
|
|
| 202 |
const autoSaveContainer = document.querySelector('#naia-auto-save');
|
| 203 |
const autoSaveCheckbox = autoSaveContainer ? autoSaveContainer.querySelector('input[type="checkbox"]') : null;
|
| 204 |
if (autoSaveCheckbox && autoSaveCheckbox.checked) {
|
| 205 |
+
// Mobile-friendly auto-save: click immediately to maintain user interaction context
|
| 206 |
+
const link = downloadBtn.querySelector('a[download]');
|
| 207 |
+
if (link) {
|
| 208 |
+
link.click();
|
| 209 |
+
} else {
|
| 210 |
downloadBtn.click();
|
| 211 |
+
}
|
|
|
|
| 212 |
}
|
| 213 |
}
|
| 214 |
}
|
|
|
|
| 265 |
input.value = savedToken;
|
| 266 |
input.dispatchEvent(new Event('input', { bubbles: true }));
|
| 267 |
input.dispatchEvent(new Event('change', { bubbles: true }));
|
|
|
|
| 268 |
}
|
| 269 |
} catch (e) {
|
| 270 |
console.error('NAIA-WEB: Error loading token:', e);
|
|
|
|
| 387 |
scale: toFloat(getInputValue('#naia-scale')),
|
| 388 |
cfg_rescale: toFloat(getInputValue('#naia-cfg-rescale')),
|
| 389 |
sampler: getInputValue('#naia-sampler'),
|
| 390 |
+
noise_schedule: getInputValue('#naia-noise-schedule'),
|
| 391 |
+
variety_plus: getInputValue('#naia-variety-plus', 'checkbox'),
|
| 392 |
// Random resolution
|
| 393 |
random_resolution: getInputValue('#naia-random-resolution', 'checkbox'),
|
| 394 |
enabled_resolutions: getCheckboxGroupValues('#naia-res-checkboxes'),
|
|
|
|
| 419 |
|
| 420 |
try {
|
| 421 |
localStorage.setItem(SETTINGS_KEY, JSON.stringify(settings));
|
|
|
|
|
|
|
|
|
|
|
|
|
| 422 |
} catch (e) {
|
| 423 |
console.error('NAIA-WEB: Error saving settings:', e);
|
| 424 |
}
|
|
|
|
| 479 |
renderFromCache() {
|
| 480 |
const grid = document.getElementById('naia-qs-tag-grid');
|
| 481 |
if (!grid) {
|
|
|
|
| 482 |
return;
|
| 483 |
}
|
| 484 |
|
|
|
|
| 507 |
}
|
| 508 |
|
| 509 |
this.updatePageInfo();
|
|
|
|
| 510 |
},
|
| 511 |
|
| 512 |
// Show popup to choose Include or Exclude (positioned above grid)
|
|
|
|
| 578 |
actionInput.value = `${action}:${tag}`;
|
| 579 |
actionInput.dispatchEvent(new Event('input', { bubbles: true }));
|
| 580 |
actionInput.dispatchEvent(new Event('change', { bubbles: true }));
|
|
|
|
| 581 |
}
|
| 582 |
},
|
| 583 |
|
|
|
|
| 605 |
}
|
| 606 |
|
| 607 |
// Add click listener - just try to render after click
|
|
|
|
| 608 |
button.addEventListener('click', () => {
|
|
|
|
| 609 |
if (self.dataReady) {
|
|
|
|
| 610 |
self.renderWithRetry(5);
|
| 611 |
}
|
| 612 |
});
|
|
|
|
|
|
|
| 613 |
};
|
| 614 |
|
| 615 |
checkAccordion();
|
|
|
|
| 678 |
|
| 679 |
// Initialize autocomplete on all target textareas
|
| 680 |
init() {
|
|
|
|
| 681 |
this.createDropdown();
|
|
|
|
|
|
|
|
|
|
| 682 |
this.attachToTargets();
|
|
|
|
| 683 |
// Re-attach when new elements appear (for dynamic char slots)
|
| 684 |
this.setupMutationObserver();
|
|
|
|
| 685 |
},
|
| 686 |
|
| 687 |
// Create the dropdown element
|
|
|
|
| 720 |
return container.querySelector('textarea');
|
| 721 |
},
|
| 722 |
|
|
|
|
|
|
|
|
|
|
| 723 |
// Attach to all target textareas
|
| 724 |
attachToTargets() {
|
| 725 |
let attachedCount = 0;
|
|
|
|
| 729 |
if (textarea && !textarea.dataset.autocompleteAttached) {
|
| 730 |
this.attachToTextarea(textarea);
|
| 731 |
attachedCount++;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 732 |
}
|
| 733 |
}
|
| 734 |
|
|
|
|
| 739 |
if (promptTextarea && !promptTextarea.dataset.autocompleteAttached) {
|
| 740 |
this.attachToTextarea(promptTextarea);
|
| 741 |
attachedCount++;
|
|
|
|
| 742 |
}
|
| 743 |
if (negativeTextarea && !negativeTextarea.dataset.autocompleteAttached) {
|
| 744 |
this.attachToTextarea(negativeTextarea);
|
| 745 |
attachedCount++;
|
|
|
|
| 746 |
}
|
| 747 |
}
|
| 748 |
|
|
|
|
| 751 |
if (charSearchTextarea && !charSearchTextarea.dataset.autocompleteAttached) {
|
| 752 |
this.attachToTextarea(charSearchTextarea);
|
| 753 |
attachedCount++;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 754 |
}
|
| 755 |
},
|
| 756 |
|
|
|
|
| 809 |
observer.observe(document.body, { childList: true, subtree: true });
|
| 810 |
},
|
| 811 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 812 |
// Handle input event
|
| 813 |
onInput(textarea) {
|
|
|
|
| 814 |
this.activeTextarea = textarea;
|
| 815 |
|
| 816 |
clearTimeout(this.debounceTimer);
|
| 817 |
this.debounceTimer = setTimeout(() => {
|
|
|
|
| 818 |
this.search(textarea);
|
| 819 |
}, this.DEBOUNCE_MS);
|
| 820 |
},
|
|
|
|
| 907 |
}
|
| 908 |
|
| 909 |
const tokenInfo = this.getCurrentToken(textarea);
|
| 910 |
+
const { token, isWeightValue } = tokenInfo;
|
|
|
|
| 911 |
|
| 912 |
// Skip autocomplete if editing a weight value (e.g., "0.5" in "0.5::tag")
|
| 913 |
if (isWeightValue) {
|
|
|
|
| 914 |
this.close();
|
| 915 |
return;
|
| 916 |
}
|
|
|
|
| 919 |
this.currentTokenInfo = tokenInfo;
|
| 920 |
|
| 921 |
if (token.length < this.MIN_CHARS) {
|
|
|
|
| 922 |
this.close();
|
| 923 |
return;
|
| 924 |
}
|
| 925 |
|
| 926 |
// Determine search mode based on textarea context
|
| 927 |
this.currentSearchMode = this.getSearchMode(textarea);
|
|
|
|
| 928 |
|
| 929 |
// Trigger Gradio search via hidden input
|
| 930 |
// Format: "mode:query" (e.g., "no_character:blue" or "character_only:miku")
|
| 931 |
const searchContainer = document.getElementById('naia-autocomplete-query');
|
| 932 |
const searchInput = searchContainer ? searchContainer.querySelector('textarea, input') : null;
|
|
|
|
| 933 |
if (searchInput) {
|
| 934 |
const queryWithMode = this.currentSearchMode + ':' + token;
|
| 935 |
searchInput.value = queryWithMode;
|
| 936 |
searchInput.dispatchEvent(new Event('input', { bubbles: true }));
|
|
|
|
|
|
|
|
|
|
| 937 |
}
|
| 938 |
},
|
| 939 |
|
| 940 |
// Receive results from Gradio (called from JS parameter)
|
| 941 |
setResults(results) {
|
|
|
|
| 942 |
if (!results || results.length === 0) {
|
|
|
|
| 943 |
this.close();
|
| 944 |
return;
|
| 945 |
}
|
| 946 |
|
| 947 |
this.currentResults = results;
|
| 948 |
this.selectedIndex = 0;
|
|
|
|
| 949 |
this.renderDropdown();
|
| 950 |
this.show();
|
| 951 |
},
|
|
|
|
| 1061 |
const searchBtn = document.querySelector('#naia-char-search-btn');
|
| 1062 |
if (searchBtn) {
|
| 1063 |
searchBtn.click();
|
|
|
|
| 1064 |
}
|
| 1065 |
}, 100);
|
| 1066 |
} else {
|
|
|
|
| 1203 |
|
| 1204 |
// Initialize after DOM ready with retry
|
| 1205 |
function initAutocompleteWithRetry(attempt = 1) {
|
|
|
|
| 1206 |
Autocomplete.init();
|
| 1207 |
|
| 1208 |
// If no textareas attached and still have retries, try again
|
|
|
|
| 1233 |
// Move download button into image container
|
| 1234 |
if (!imageContainer.contains(downloadBtn)) {
|
| 1235 |
imageContainer.appendChild(downloadBtn);
|
|
|
|
| 1236 |
}
|
| 1237 |
}
|
| 1238 |
|