Skip to content

Fix: IME input handling to prevent unintended message submission - #439

Open
seijikohara wants to merge 1 commit into
winfunc:mainfrom
seijikohara:fix/ime-enter-handling
Open

Fix: IME input handling to prevent unintended message submission#439
seijikohara wants to merge 1 commit into
winfunc:mainfrom
seijikohara:fix/ime-enter-handling

Conversation

@seijikohara

@seijikoharaseijikohara commented Jan 28, 2026

Copy link
Copy Markdown

Summary

This PR fixes a bug where pressing Enter to confirm IME (Input Method Editor) conversion unintentionally triggers message submission in chat interfaces.

Closes#19
Supersedes #278 (more comprehensive fix applied across all input components)

Problem

When users type with IME for East Asian languages, they press Enter to confirm character conversion (e.g., hiragana → kanji). The application incorrectly interpreted this Enter keypress as a submit action.

Root Cause

The justEndedRef flag reset logic was flawed:

// Before (incorrect)if(hasCompositionJustEndedRef.current&&keyCode!==229){hasCompositionJustEndedRef.current=false;}

Since Enter has keyCode === 13 (not 229), the condition keyCode !== 229 evaluated to true, resetting the flag before the Enter key check could use it.

Event Sequence Diagram

sequenceDiagram
participant User
participant IME
participant Browser
participant App
User->>IME: Type "nihon"
IME->>Browser: compositionstart
Browser->>App: Set isComposingRef = true
User->>IME: Press Enter (confirm)
IME->>Browser: compositionend
Browser->>App: Set isComposingRef = false
Browser->>App: Set justEndedRef = true
Browser->>App: keydown (Enter)
Note over App: Check justEndedRef → true
App->>App: Skip submission ✓
App->>App: Reset justEndedRef = false
User->>IME: Press Enter (submit)
Browser->>App: keydown (Enter)
Note over App: Check justEndedRef → false
App->>App: Submit message ✓
Loading

Solution

1. Fix Flag Reset Condition

Changed the reset condition to only reset on non-Enter keys:

// After (correct)if(justEndedRef.current&&e.key!=="Enter"){justEndedRef.current=false;}

2. Multi-Layered IME Detection

Implemented a detection strategy for cross-browser compatibility:

flowchart TD
A[keydown event] --> B{e.isComposing?}
B -->|true| Z[Skip: IME active]
B -->|false| C{native.isComposing?}
C -->|true| Z
C -->|false| D{isComposingRef?}
D -->|true| Z
D -->|false| E{keyCode === 229?}
E -->|true| Z
E -->|false| F{justEndedRef?}
F -->|true| Y[Skip: Just confirmed]
F -->|false| G[Process Enter]
Loading
LayerMethodPurpose
PrimaryisComposing propertyStandard API (React/Native)
SecondaryComposition event trackingManual fallback
TertiarykeyCode === 229Safari/WKWebView edge cases

3. Shared Utilities (DRY/SSOT)

Created centralized utilities to eliminate code duplication:

src/
├── utils/
│ └── ime.ts # Single source of truth
└── hooks/
└── useIMESafeEnterSubmit.ts # Reusable hook

Comparison with #278

Aspect#278This PR
Components fixedFloatingPromptInput onlyAll 5 input components
Flag reset bug fixNoYes (e.key !== "Enter")
Shared utilitiesNoYes (DRY/SSOT)
Custom hookNoYes (useIMESafeEnterSubmit)
onBlur cleanupNoYes

Changes

FileChange
src/utils/ime.tsNew: Shared IME detection utilities
src/hooks/useIMESafeEnterSubmit.tsNew: Custom hook for IME-safe Enter
src/components/FloatingPromptInput.tsxModified: Use shared utilities
src/components/ClaudeCodeSession.tsxModified: Use shared utilities
src/components/TimelineNavigator.tsxModified: Use shared utilities
src/components/WebviewPreview.tsxModified: Use shared utilities
src/components/AgentExecution.tsxModified: Use shared utilities

Supported Languages

This implementation is language-agnostic and supports any IME using composition events:

  • Japanese (Hiragana/Katakana/Kanji)
  • Chinese (Pinyin, Wubi, Zhuyin, Cangjie)
  • Korean (Hangul)
  • Vietnamese (Telex, VNI)
  • Other composition-based input methods

Testing

  • TypeScript type check (tsc --noEmit)
  • Rust tests (9/9 passed)
  • Manual testing with Japanese IME on macOS
  • Verified: IME confirmation Enter does not submit
  • Verified: Subsequent Enter correctly submits

References

…bmission
- Add shared IME utilities (src/utils/ime.ts) as single source of truth
- Add useIMESafeEnterSubmit custom hook for reusable IME handling
- Fix justEndedRef reset condition from keyCode !== 229 to e.key !== "Enter"
- Implement multi-layered IME detection: isComposing, composition events, keyCode 229
Supports all IME languages: Japanese, Chinese, Korean, Vietnamese, etc.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Japanese strings sent before confirming

1 participant

@seijikohara