Commit Graph
128 Commits
Author SHA1 Message Date
diodiogod e840c6df4d Version 4.19.2
Add configurable VC engine for <restore> tags

Technical implementation:
- Add ComfyUI settings menu option for VC engine selection
- Support three VC engines: ChatterBox 23-Lang, ChatterBox, CosyVoice
- Fix module import to use shared sys.modules instance
- Implement file-based settings cache for persistence across restarts
- Add beforeQueuing hook to ensure settings sync before workflows
2026-01-28 12:18:54 -03:00
diodiogod 88feb3a99a Add Qwen3-TTS engine with Phase 1 implementation
Implements complete Qwen3-TTS integration following NEW_ENGINE_IMPLEMENTATION_GUIDE
with unified architecture, character switching, language support, and Voice Designer.

## Core Engine Implementation

**Engine Wrapper** (`engines/qwen3_tts/qwen3_tts.py`):
- Wraps official Qwen3-TTS implementation with .to() method for VRAM management
- Device checking before generation with automatic model reload
- Support for 3 model types: CustomVoice (presets), VoiceDesign (text-to-voice), Base (voice cloning)
- Progress bar integration via transformers streamer interface
- 24kHz mono audio output in ComfyUI-compatible format

**Bundled Implementation** (`engines/qwen3_tts/impl/`):
- Official Qwen3-TTS library bundled for stability
- Patched modeling_qwen3_tts.py (line 2069) for progress callback support
- Sox dependency stubbed out (25Hz models only, we use 12Hz)
- Supports 6 models: 0.6B/1.7B × CustomVoice/VoiceDesign/Base

**Adapter** (`engines/adapters/qwen3_tts_adapter.py`):
- Intelligent model selection based on context (voice_preset/node_type)
- Automatic switching: preset→CustomVoice, None→Base, Designer→VoiceDesign
- Full caching integration with audio_cache.generate_cache_key()
- Voice reference processing for Base model (audio + transcript)
- Character-to-speaker mapping for CustomVoice presets (deterministic MD5 hashing)

## Node Implementation

**Engine Configuration Node** (`nodes/engines/qwen3_tts_engine_node.py`):
- Unified interface with voice_preset dropdown (9 preset speakers + None for zero-shot)
- Model size selection: 0.6B (low VRAM) / 1.7B (high quality)
- Language dropdown: Auto + 10 languages (Chinese, English, Japanese, Korean, German, French, Russian, Portuguese, Spanish, Italian)
- Conditional instruction field (locked when unsupported: Base model or 0.6B CustomVoice)
- Generation parameters: top_k, top_p, temperature, repetition_penalty, max_new_tokens
- Advanced: dtype, attn_implementation, x_vector_only_mode

**Voice Designer Node** (`nodes/qwen3_tts/qwen3_tts_voice_designer_node.py`):
- UNIQUE FEATURE: Create voices from natural language descriptions
- Smart disk check: loads existing characters without model loading/generation
- Runtime caching for same-session regeneration optimization
- Saves to models/voices/ with standard format (.wav + .reference.txt + .txt metadata)
- Outputs unified NARRATOR_VOICE format matching Character Voices node
- Duplicate detection prevents regenerating identical voices

**TTS Processor** (`nodes/qwen3_tts/qwen3_tts_processor.py`):
- Full character switching support via character parser
- CustomVoice: deterministic character→preset mapping (preserves narrator's chosen preset)
- Base: uses models/voices/ audio references (standard voice cloning)
- VoiceDesign: uses saved voice descriptions from Designer node
- Pause tag processing with silence generation
- Language switching support via [language:Character] tags
- Segment parameter support ([seed:X], [temperature:0.8])
- Interrupt handling for cancellation
- Chunk combining with ChunkCombiner + ChunkTimingHelper

## JavaScript Widget

**Widget Locking** (`web/qwen3_tts_widgets.js`):
- Conditional UI: locks instruction field when unsupported
- Locked when: voice_preset="None" OR (model_size="0.6B" + preset selected)
- Console warnings explain limitations
- Preserves field value when locked (doesn't clear)

## System Integration

**Language Support** (`utils/models/language_mapper.py`):
- Added QWEN3_TTS_LANGUAGE_MAP: maps ISO codes to full names (e.g., "po"→"Portuguese")
- Added map_language_code_to_qwen3_tts() helper function
- Added "po" to global LANGUAGE_ALIASES (maps to pt-pt)
- Qwen3-TTS expects FULL language names, not ISO codes

**Unified Model Interface** (`utils/models/unified_model_interface.py`):
- Registered qwen3_tts factory in initialize_all_factories()
- Consolidated loading messages (single-line model loading output)
- Context-based model selection (VoiceDesign/CustomVoice/Base)

**Segment Parameters** (`utils/text/segment_parameters.py`):
- Added "qwen3_tts" to PARAMETER_ENGINES for inline tag support

**Voice Discovery** (`utils/voice/discovery.py`):
- Enhanced get_character_mapping() to detect VoiceDesign saved voices
- Checks for voice metadata format (description vs audio reference)
- Returns voice type for processor to handle correctly

**TTS Text Node** (`nodes/unified/tts_text_node.py`):
- Added qwen3_tts processor routing
- CustomVoice console messages (shows preset speaker instead of narrator warning)
- Recognizes unified NARRATOR_VOICE format from Voice Designer
- Language code mapping display (shows "po" → "Portuguese" conversion)

**Node Registration** (`nodes.py`):
- Registered Qwen3TTSEngineNode and Qwen3TTSVoiceDesignerNode
- Added error handling with fallback messages

## Features Implemented (Phase 1 Complete)

✅ Basic engine integration with unified architecture
✅ Character switching (CustomVoice presets + Base model cloning)
✅ Language switching (10 languages + Auto detection)
✅ Pause tags ([pause:1.5])
✅ Segment parameters ([seed:42], [temperature:0.8])
✅ Audio caching (prevents duplicate generation)
✅ VRAM management (.to() method + device checking)
✅ Interrupt handling (user cancellation)
✅ Progress bars (console + ComfyUI)
✅ Voice Designer (text-to-voice creation)
✅ Smart disk caching (skips regeneration for saved voices)
✅ Unified NARRATOR_VOICE output format

## Technical Details

- **Sample Rate**: 24kHz mono
- **Models**: 6 variants (0.6B/1.7B × CustomVoice/VoiceDesign/Base)
- **Tokenizer**: Qwen3-TTS-Tokenizer-12Hz (12.5 fps, 16 quantizers)
- **Languages**: 10 (Chinese, English, Japanese, Korean, German, French, Russian, Portuguese, Spanish, Italian)
- **CustomVoice Presets**: 9 (Vivian, Serena, Uncle_Fu, Dylan, Eric, Ryan, Aiden, Ono_Anna, Sohee)
- **Audio Format**: torch.Tensor [1, 1, samples] at 24kHz
- **Cache Integration**: Uses audio_cache with stable key generation
- **Character Mapping**: MD5-based deterministic assignment (cache-friendly)

## Testing Completed

- Engine node loads and configures correctly
- Preset voice generation (CustomVoice with 9 speakers)
- Zero-shot cloning (Base model with voice references)
- Voice Designer text-to-voice generation
- Character switching with automatic preset mapping
- Pause tags create correct silence durations
- Language selection and switching
- Caching prevents duplicate generation
- VRAM management (Clear VRAM + reload)
- Generation info reports with timing
- Interrupt cancellation
- Widget locking behavior
- Disk check optimization (skips model loading for existing voices)

## Phase 2+ (Future)

- SRT processor integration (Phase 4)
- Streaming generation (requires special deployment)
- Fine-tuning nodes (advanced feature)
2026-01-28 00:02:02 -03:00
diodiogod 80e321e86f Fix copy/paste in Multiline TTS Tag Editor for ComfyUI v0.3.75+
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.
2025-12-12 11:55:15 -03:00
diodiogod 887050726d Fix paste behavior in Multiline TTS Tag Editor
Use bubble phase stopPropagation (not capture phase) to allow paste to complete in contentEditable div before preventing event from reaching ComfyUI canvas handlers.
2025-12-12 11:22:36 -03:00
diodiogod cbf02a44d8 Fix Multiline TTS Tag Editor paste event propagation
Prevent paste events from bubbling to ComfyUI canvas, which was causing previously copied nodes to be pasted when pasting text into the editor.
2025-12-12 09:45:33 -03:00
diodiogod d9d9164382 Add tabbed Inline Edit interface to Multiline TTS Tag Editor
Implements comprehensive inline edit tag UI for Step Audio EditX post-processing with trapezoid tab design and full persistence.

New Features:
- Tabbed interface: "Character/Parameters" and "Inline Edit" tabs
- Trapezoid tab design with cyan active indicator
- Tab text never wraps (nowrap + ellipsis overflow)
- Inline edit tag sections for all tag types:
  * Paralinguistic (Laughter, Breathing, Sigh, etc.) - 10 types
  * Emotion (happy, sad, angry, etc.) - 14 emotions
  * Style (whisper, serious, child, etc.) - 32 styles
  * Speed (faster, slower, more_faster, more_slower)
  * Voice Restoration (with VC passes and reference iteration)

Intelligent Tag Insertion:
- Pipe-separator support for combining multiple tags (e.g., <Laughter:2|emotion:happy>)
- Smart tag detection: cursor inside/after existing tag adds with pipe separator
- Tag type replacement: adding same type replaces existing (e.g., emotion:sad replaces emotion:happy)
- Iteration control via sliders (1-5 iterations)
- Toast notifications for insertion feedback

Full Persistence:
- All dropdown selections saved to localStorage
- All iteration slider positions saved to localStorage
- Values restored on ComfyUI restart/browser reload
- Fixed parameter section to restore saved values (was only saving, not restoring)

Syntax Highlighting:
- Inline edit tags highlighted in magenta (#ff66ff)
- Distinguishes from character tags (cyan)

Files Added:
- web/widget-inline-edit-section.js - Inline edit UI builder
- web/widget-tabs.js - Tabbed interface system

Files Modified:
- web/string_multiline_tag_editor.js - Integrated tabs and inline edit section
- web/widget-event-handlers.js - Tag insertion logic with pipe-separator support
- web/widget-parameter-section.js - Fixed parameter value restoration
2025-12-09 15:38:42 -03:00
diodiogod 9907e8964c Add ComfyUI settings menu for inline edit tag precision/device control
Features:
- New settings menu under "TTS Audio Suite > Step Audio EditX (Inline Tags)"
- Precision options: auto, fp32, fp16, bf16, int8, int4
- Device options: auto, cuda, cpu, xpu
- Settings persist across ComfyUI restarts
- API endpoint for JavaScript-Python communication
- Automatic dead engine detection and reload

Implementation:
- web/tts_audio_suite_settings.js: Frontend settings UI
- __init__.py: API endpoint /api/tts-audio-suite/settings
- edit_post_processor.py: Global settings storage and retrieval
- step_audio_editx_audio_editor_node.py: Settings detection and engine reload logic

Notes:
- Settings require browser refresh (F5) to take effect (documented in tooltips)
- Only affects inline edit tags, not Step Audio EditX node direct usage
- Fixes dead engine detection after memory management unloads quantized models
2025-12-09 09:56:57 -03:00
diodiogod c8f7a4759f Fix Step Audio EditX non-quantized model CPU offloading
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)"
2025-12-09 01:14:11 -03:00
diodiogod 55cf8842d8 Improve Step Audio EditX edit node UI with conditional widget disabling
• 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
2025-12-05 14:45:04 -03:00
diodiogod 985bf68248 Fix Silent Speech Analyzer video preview: generate and annotate preview video on first analysis 2025-11-08 11:54:51 -03:00
diodiogod 24e3f4c41d Fix history preservation and workflow data persistence
- 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
2025-11-03 22:03:25 -03:00
diodiogod 7a97c8b056 Fix workflow data persistence and history preservation
- 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
2025-11-03 18:43:47 -03:00
diodiogod 6062ff0cdd Fix localStorage priority in workflow data loading
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.
2025-11-03 14:56:59 -03:00
diodiogod ea5f7f1a27 Fix workflow data loading vs localStorage persistence
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
2025-11-03 13:59:25 -03:00
diodiogod 297bfcf0ef Version 4.14.1
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
2025-11-01 01:11:52 -03:00
diodiogod 1927911d47 Add default example text to tag editor with SRT format showcase
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.
2025-10-31 23:42:54 -03:00
diodiogod ab5262ee97 Add selected text support for tag insertion
- 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
2025-10-31 19:26:30 -03:00
diodiogod 9d43723421 Fix format button and Enter key handling
- 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
2025-10-31 19:13:21 -03:00
diodiogod c6173080d6 Add keyboard shortcuts for tag and preset insertion
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.
2025-10-31 18:44:35 -03:00
diodiogod da223f49f7 Fix language code detection: load supported languages on module init
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.
2025-10-31 18:38:58 -03:00
diodiogod 4e75e5ffe0 Prevent duplicate language code insertion
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.
2025-10-31 18:17:27 -03:00
diodiogod 8e880592d3 Fix language dropdown persistence and character replacement with language prefix
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
2025-10-31 18:11:12 -03:00
diodiogod 012852c27d Fix language tag insertion for parameter-only tags
[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.
2025-10-31 18:02:33 -03:00
diodiogod 293229aaf7 Load language list dynamically from API endpoint
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.
2025-10-31 17:52:50 -03:00
diodiogod 855ca30007 Fix language tag insertion to use pipe separator for parameters
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.
2025-10-31 17:51:23 -03:00
diodiogod 368ccd0dd4 Create language constants source of truth and fix language tag logic
- 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
2025-10-31 17:48:06 -03:00
diodiogod 0f5cd0ad7b Make tag modification tolerant of single space after closing bracket
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.
2025-10-31 17:41:51 -03:00
diodiogod b5da78f754 Fix language tag insertion to preserve pipe-separated parameters
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.
2025-10-31 17:39:25 -03:00
diodiogod fc79682b5f Add functional language tag button to TTS editor
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
2025-10-31 17:28:45 -03:00
diodiogod c8c0f5a95a Integrate event handlers module into TTS tag editor
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.
2025-10-31 17:23:15 -03:00
diodiogod b78cdbe2fc Refactor monolithic widget into modular architecture
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.
2025-10-31 16:54:22 -03:00
diodiogod 2dad024160 Fix format button removing space before tags at end of sentence 2025-10-31 16:03:16 -03:00
diodiogod c9403923d7 Apply 2-120px font size limits to Ctrl+scroll handler 2025-10-31 16:00:03 -03:00
diodiogod 767d28e87d Set font size range to 2-120px for more flexibility 2025-10-31 15:17:22 -03:00
diodiogod 37e88c40c8 Sync font size input field when using Ctrl+scroll 2025-10-31 15:10:40 -03:00
diodiogod 1ca22b4306 Add comprehensive font options (16 web-safe fonts) including programming-friendly monospace 2025-10-31 15:05:24 -03:00
diodiogod 2fab935c04 Adjust floating font box to better position above node with responsive shrinking 2025-10-31 14:53:09 -03:00
diodiogod 29ca82eace Make floating font box shrink responsively instead of overflowing 2025-10-31 14:49:34 -03:00
diodiogod 55a41d6af9 Adjust floating font box offset and add overflow clipping 2025-10-31 14:46:21 -03:00
diodiogod 3ffc079292 Refactor to use wrapper container for floating font box above node 2025-10-31 14:45:08 -03:00
diodiogod a84c332d11 Fix font dropdown to use canonical system fonts 2025-10-31 14:39:14 -03:00
diodiogod d25d38a446 Fix resize divider position after sidebar width changes
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.
2025-10-31 14:20:19 -03:00
diodiogod 44748cf5ac Make preset name truncation dynamic based on sidebar width
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.
2025-10-31 14:17:51 -03:00
diodiogod b074217d55 Auto-update preset names to show saved content
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.
2025-10-31 14:11:15 -03:00
diodiogod 9e9adf17a4 Replace undo/redo shortcut with Alt+Z to avoid ComfyUI conflict
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.
2025-10-31 14:08:52 -03:00
diodiogod 746fad8b52 Add stopPropagation to undo/redo to prevent ComfyUI conflicts
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.
2025-10-31 11:40:52 -03:00
diodiogod ab0dafc93f Fix preset save button - use actual selection instead of stale caretPos
- 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
2025-10-31 11:35:06 -03:00
diodiogod 5c087dc793 Fix tag detection when caret is right before closing bracket
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.
2025-10-31 03:03:53 -03:00
diodiogod 1b0578775d Fix parameter duplicate tags - position caret right after ] on new tag creation
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.
2025-10-31 03:01:34 -03:00
diodiogod 646f2fc10b Fine-tune resize divider to 6px (3px on each side)
Perfect balance: easy enough to grab, thin enough to not interfere with text.
2025-10-31 02:55:03 -03:00