mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
f9cbf70f70
- Implement RichChatInput component with visual pill rendering - Add ActionPill component with blue circle icons for actions - Add MentionPill component with blue diamond icons for files - Support for /action and @filename pill creation - Inline pill display in both input and message history - Proper text selection, highlighting, and cursor positioning - Backspace removal of entire pills - Theme-aware styling for light/dark modes - Consistent white pill backgrounds with blue accent icons - Fixed line-breaking issues for natural text flow Components added: - RichChatInput.tsx: Main rich text input with pill rendering - ActionPill.tsx: Blue circle pills for actions - MentionPill.tsx: Blue diamond pills for file mentions - MessageContent.tsx: Enhanced message display with pills Features: - Visual pills replace [Action] and @filename text - Click and drag text selection works normally - Double/triple click for word/all selection - Pills flow inline with text content - Proper cursor positioning and blinking - Backspace removes entire pills as units
98 lines
3.7 KiB
Python
98 lines
3.7 KiB
Python
import re
|
|
|
|
# Read the RichChatInput file
|
|
with open('ui/desktop/src/components/RichChatInput.tsx', 'r') as f:
|
|
content = f.read()
|
|
|
|
# Add debugging to the renderContent function
|
|
# Find the while loop that processes actions
|
|
old_while_section = ''' while ((match = actionRegex.exec(value)) !== null) {
|
|
const beforeAction = value.slice(lastIndex, match.index);
|
|
const actionLabel = match[1];
|
|
|
|
// Add text before action with potential cursor
|
|
if (beforeAction) {'''
|
|
|
|
new_while_section = ''' console.log('🎨 RichChatInput renderContent called with value:', value);
|
|
console.log('🔍 Looking for action patterns with regex:', actionRegex);
|
|
|
|
while ((match = actionRegex.exec(value)) !== null) {
|
|
console.log('✅ Found action match:', match);
|
|
const beforeAction = value.slice(lastIndex, match.index);
|
|
const actionLabel = match[1];
|
|
console.log('📝 Processing action:', { beforeAction, actionLabel, matchIndex: match.index });
|
|
|
|
// Add text before action with potential cursor
|
|
if (beforeAction) {'''
|
|
|
|
content = content.replace(old_while_section, new_while_section)
|
|
|
|
# Add debugging to the action pill creation
|
|
old_pill_creation = ''' // Add the action pill
|
|
addCursorIfNeeded(currentPos);
|
|
const actionInfo = ACTION_MAP[actionLabel.toLowerCase().replace(/\\s+/g, '-') as keyof typeof ACTION_MAP] ||
|
|
{ label: actionLabel, icon: <Zap size={12} /> };
|
|
|
|
parts.push(
|
|
<ActionPill
|
|
key={`action-${keyCounter++}`}
|
|
actionId={actionLabel.toLowerCase().replace(/\\s+/g, '-')}
|
|
label={actionLabel}
|
|
icon={actionInfo.icon}
|
|
variant="default"
|
|
size="sm"
|
|
onRemove={() => handleRemoveAction(actionLabel)}
|
|
/>
|
|
);'''
|
|
|
|
new_pill_creation = ''' // Add the action pill
|
|
addCursorIfNeeded(currentPos);
|
|
const actionInfo = ACTION_MAP[actionLabel.toLowerCase().replace(/\\s+/g, '-') as keyof typeof ACTION_MAP] ||
|
|
{ label: actionLabel, icon: <Zap size={12} /> };
|
|
|
|
console.log('🏷️ Creating action pill:', { actionLabel, actionInfo });
|
|
|
|
parts.push(
|
|
<ActionPill
|
|
key={`action-${keyCounter++}`}
|
|
actionId={actionLabel.toLowerCase().replace(/\\s+/g, '-')}
|
|
label={actionLabel}
|
|
icon={actionInfo.icon}
|
|
variant="default"
|
|
size="sm"
|
|
onRemove={() => handleRemoveAction(actionLabel)}
|
|
/>
|
|
);
|
|
|
|
console.log('✅ Action pill added to parts array');'''
|
|
|
|
content = content.replace(old_pill_creation, new_pill_creation)
|
|
|
|
# Add debugging to the onChange handler
|
|
old_onchange = ''' const handleTextareaChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
const newValue = e.target.value;
|
|
const newCursorPos = e.target.selectionStart;
|
|
|
|
console.log('RichChatInput: onChange', { newValue, newCursorPos });
|
|
onChange(newValue, newCursorPos);
|
|
setCursorPosition(newCursorPos);
|
|
}, [onChange]);'''
|
|
|
|
new_onchange = ''' const handleTextareaChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
const newValue = e.target.value;
|
|
const newCursorPos = e.target.selectionStart;
|
|
|
|
console.log('🔄 RichChatInput: onChange', { newValue, newCursorPos });
|
|
console.log('🎨 Will trigger re-render with new value:', newValue);
|
|
onChange(newValue, newCursorPos);
|
|
setCursorPosition(newCursorPos);
|
|
}, [onChange]);'''
|
|
|
|
content = content.replace(old_onchange, new_onchange)
|
|
|
|
# Write the modified content back
|
|
with open('ui/desktop/src/components/RichChatInput.tsx', 'w') as f:
|
|
f.write(content)
|
|
|
|
print("Added comprehensive debugging to RichChatInput")
|