Add explicit copy event handler with stopPropagation to prevent ComfyUI v0.3.75+ from intercepting clipboard operations. Newer ComfyUI versions intercept clipboard events which was blocking copy operations in contentEditable elements.
Use bubble phase stopPropagation (not capture phase) to allow paste to complete in contentEditable div before preventing event from reaching ComfyUI canvas handlers.
Fixed CPU offloading for non-quantized (bfloat16/float16/float32) models:
- StepAudioTTS components (llm, cosy_model) don't have .to() method directly
- Handler now moves model.llm and model.cosy_model.cosy_impl individually
- Updates CosyVoice.device tracker when moving cosy_impl to CPU
- Properly handles both raw StepAudioTTS and wrapped models
Fixes unload behavior for non-quantized models to actually free VRAM
instead of silently failing with "no memory freed (model may already be on CPU)"
• Add JavaScript showcontrol file to grey out irrelevant options based on edit_type selection
- emotion dropdown only enabled when edit_type='emotion'
- style dropdown only enabled when edit_type='style'
- speed dropdown only enabled when edit_type='speed'
- All dropdowns disabled for paralinguistic, denoise, vad modes
- n_edit_iterations remains enabled for all modes
- Follows same pattern as Inpaint Crop (Improved) node
• Fix paralinguistic tooltip to show ALL 10 available tags instead of first 5 + "..."
- Complete list: <Breathing>, <Laughter>, <Sigh>, <Uhm>, <Surprise-oh>, <Surprise-ah>, <Surprise-wa>, <Confirmation-en>, <Question-ei>, <Dissatisfaction-hnn>
- Users can now see all available tags in the tooltip
Improves UX by showing only relevant options and providing complete tag reference
- Add immediate state.text update on input to ensure full text is saved to localStorage
- Use onConfigureCallCount to properly distinguish page reloads from new workflow loads
- Track lastWorkflowValue to detect when a different workflow file is opened
- Preserve undo/redo history across page reloads within same session
- Reset history to 1/1 when opening a different workflow (as expected)
- Ensure multiple tag editor nodes in same workflow maintain separate data
- Remove debug console.log statements
- Removed forceInput:True to enable widget serialization for cross-installation sharing
- Hide default STRING widget while keeping it in widgets array for serialization
- Use onConfigure hook to properly load workflow values after node creation
- Add isConfigured flag to prevent setValue from overwriting onConfigure state
- Preserve full undo/redo history across reloads using Object.assign
- Text now persists in workflows AND history survives reloads within same installation
Prioritize localStorage over workflow value to preserve user edits across sessions.
New priority order:
1. localStorage with custom data (persistent edits) - highest priority
2. Workflow with custom data (first load of shared workflow)
3. Workflow value or default
Fixes issue where user edits were lost on reload.
Prioritize workflow value if it contains custom data (not default example text).
This allows shared workflows to load their data while keeping localStorage
for persistent sessions of the same workflow instance.
Logic:
- Workflow has custom data → use it (shared workflow)
- localStorage has custom data → keep it (same session reload)
- Both default or empty → use workflow value
Fix keyboard event handling in tag editor
- Block ComfyUI shortcuts while editor has focus to prevent interference
- Allow Alt key combinations (Alt+L/C/P/Z and Alt+1/2/3) to work properly
- Fix Alt+Z undo/redo shortcut by moving handler out of else-if chain
- Use document.execCommand insertLineBreak for proper Enter key handling
- Prevent typing regular characters from triggering ComfyUI node list
New tag editor nodes now display helpful examples including:
- Basic character and parameter tag syntax
- Pause tag usage
- SRT subtitle format with timing and tags
Allows users to immediately see syntax highlighting in action.
- Select text and click tag buttons to prepend tags to selection
- If selection starts with a tag, modify it instead of creating new one
- Detects leading whitespace and positions caret correctly inside bracket
- Works for character, language, and parameter buttons
- All existing tag logic (checks, updates, etc) still applies
- Format button now preserves newlines and doesn't create double spaces before tags
- Plain Enter key now creates newlines without freezing (handles contenteditable properly)
- Prevents ComfyUI global handlers from interfering with editor behavior
Alt+L: Add Language Tag
Alt+C: Add Character
Alt+P: Add Parameter
Alt+1/2/3: Load Preset 1/2/3
Shortcuts work by programmatically clicking the corresponding buttons.
Ensure SUPPORTED_LANGUAGES in language-constants.js is populated with all 55 codes
before event handlers run, so isLanguageCode() works correctly. Prevents duplicate
language codes like [hr:|hr:|...] by properly detecting language codes vs parameters.
Language button now checks if the same language code already exists
before adding another one. Clicking the button multiple times on the
same tag now doesn't create duplicates like [pt-br:|pt-br:|...].
Only updates language if a different one is selected.
1. Language dropdown selection now persistent - restore value AFTER options
are loaded from API, not before (fixes race condition)
2. Character button now recognizes language-prefixed characters like
[en:broom_salesman|seed:3] and replaces just the character part,
producing [en:new_char|seed:3] instead of adding duplicate character
[seed:5|steps:3] now correctly becomes [en:|seed:5|steps:3] instead of
[en:|steps:3]. The issue was only capturing the pipe and subsequent
parameters, not the entire tag content including the first parameter.
Changed from static getSupportedLanguages() to dynamic API fetch,
matching the character loading pattern. Now fetches from
/api/tts-audio-suite/available-languages with fallback to hardcoded list.
Adds console message when languages are loaded.
When cursor is inside [seed:5|steps:3], language button now correctly
creates [de:|seed:5|steps:3] instead of [de:seed:5|steps:3].
For parameter-only tags, language code is inserted with pipe separator
(empty character slot) rather than prepending to parameter name.
- Added language-constants.js with API-driven language list (fallback to hardcoded)
- Added /api/tts-audio-suite/available-languages endpoint in __init__.py
- Updated widget-ui-builder.js to use getSupportedLanguages()
- Updated widget-event-handlers.js to use isLanguageCode() for detection
- Fixes issue where [seed:5|steps:3] now correctly becomes [de:|seed:5|steps:3]
instead of [de:5|steps:3] by properly detecting language codes vs parameters
Now accepts both [seed:3]* and [seed:3] * cursor positions when adding
parameters/languages. Previously only worked immediately after ] without
space. Fixes the issue where users had to place cursor directly after tag
instead of allowing normal spacing conventions.
When cursor is inside [seed:3], clicking language button now correctly
creates [de:|seed:3] instead of incorrectly replacing seed with language.
The fix properly handles tags with pipe separators, preserving all
existing parameters while prepending the language code.
Implements language tag insertion matching character/parameter buttons:
- Inserts [lang:] or [lang:Character] tags at cursor
- Supports all 9 languages (en, de, fr, ja, es, it, pt, th, no)
- Modifies existing tags (replaces language in [lang:Char] format)
- Creates new tags when cursor not in tag
- Integrates with tag editor UI builder and event handlers
Refactored 900-line main widget file to 534 lines by extracting all event listener attachments into widget-event-handlers.js (359 lines). Preserves 100% of original functionality while maintaining LLM-friendly modular architecture.
Changes:
- Extracted editor input debouncing, undo/redo, keyboard shortcuts
- Moved font controls (Ctrl+scroll, font family/size selectors)
- Consolidated character selection and parameter insertion handlers
- Preserved complex preset save/load logic with selection support
- Integrated divider resize with double-click reset
- Maintained sidebar scaling and canvas interaction events
All modules now <400 lines for optimal LLM context usage.
Major refactoring to improve code maintainability:
- Reduced main widget file from 1677→900 lines (46% reduction)
- Extracted UI builders into separate modules:
* widget-ui-builder.js (237 lines) - History, Character, Language, Validation sections
* widget-parameter-section.js (237 lines) - Parameter controls with dynamic inputs
* widget-preset-system.js (102 lines) - Preset management
- All original functionality preserved with identical behavior
- Parameter tag insertion now working with full event handler
- Note: Language selector currently only displays, doesn't auto-add to tags (design limitation)
Modules are properly organized with clear separation of concerns while maintaining all original logic and event handling.
Divider was positioned once on init but never updated when sidebar width changed.
Now setSidebarWidth() also updates the divider position, so cursor feedback
and resize handler stay accessible after resizing or double-click reset.
Instead of fixed 15 char limit, calculate max characters based on current
sidebar width. Uses formula: (sidebarWidth - 30) / 6 to estimate char count.
Minimum of 8 chars guaranteed. Automatically adjusts when sidebar is resized.
Preset titles now display the saved tag/content instead of just 'P1', 'P2', 'P3'.
Content is limited to 15 characters with ellipsis if longer. When preset is deleted,
title reverts back to P1/P2/P3. Updates both on initial load and after each save.
Changed from Ctrl+Z/Ctrl+Shift+Z to Alt+Z/Alt+Shift+Z. This avoids any conflict
with ComfyUI's global undo system since ComfyUI only listens for Ctrl+Z.
Updated button tooltips to reflect the new shortcuts.
Ctrl+Z/Ctrl+Shift+Z now stops event from bubbling to parent listeners.
Prevents ComfyUI from also trying to undo its own state when widget undo is used.
- Changed from using undefined selectionStart/selectionEnd to window.getSelection()
- Now properly detects when user has selected text in editor
- Saves complex tags from selection or character+parameters from sidebar
- Both load and save buttons now properly updated
Changed condition from '>' to '>=' when checking if caret is inside tag.
This fixes the bug where [seed:5<caret>] wasn't detected as inside the tag,
causing character/parameter additions to create duplicate tags instead of
modifying the existing one.
When creating a new parameter tag, position caret right after ] instead of
after the space. This allows subsequent parameter additions to detect and
modify the existing tag instead of creating duplicates.