Skip to content

Commit 40cdd03

Browse files
committed
fix: use Input.insertText for contenteditable elements
dispatchKeyEvent drops special characters (., (), %, etc.) in contenteditable editors (X/Twitter, Medium, Reddit New UI). Detect contenteditable/role=textbox and use CDP Input.insertText which handles all characters reliably.
1 parent 37e144d commit 40cdd03

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

lib/src/bridge/cdp_driver.dart

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,18 +1505,27 @@ class CdpDriver implements AppDriver {
15051505

15061506
/// Type text character by character (more realistic than enterText).
15071507
Future<void> typeText(String text) async {
1508-
// Snapshot focused element's value before typing
1509-
final beforeResult = await _evalJs('''
1508+
// Check if focused element is contenteditable — use Input.insertText directly
1509+
// (dispatchKeyEvent drops special chars like '.', '(', '%' in contenteditable)
1510+
final focusInfo = await _evalJs('''
15101511
(() => {
15111512
const el = document.activeElement;
1512-
if (!el) return JSON.stringify({tag: null});
1513-
return JSON.stringify({tag: el.tagName, val: el.value || '', len: (el.value || '').length});
1513+
if (!el) return JSON.stringify({tag: null, ce: false});
1514+
const ce = el.isContentEditable || el.getAttribute('contenteditable') === 'true' || el.getAttribute('role') === 'textbox';
1515+
return JSON.stringify({tag: el.tagName, ce: ce, val: el.value || '', len: (el.value || el.textContent || '').length});
15141516
})()
15151517
''');
1516-
final beforeParsed = _parseJsonEval(beforeResult);
1517-
final beforeLen = (beforeParsed?['len'] as num?)?.toInt() ?? 0;
1518+
final info = _parseJsonEval(focusInfo);
1519+
final isContentEditable = info?['ce'] == true;
1520+
final beforeLen = (info?['len'] as num?)?.toInt() ?? 0;
15181521

1519-
// Primary: keyDown(text) + keyUp per character
1522+
if (isContentEditable) {
1523+
// Use Input.insertText for contenteditable — reliable for all characters
1524+
await _call('Input.insertText', {'text': text});
1525+
return;
1526+
}
1527+
1528+
// For regular inputs/textareas: keyDown(text) + keyUp per character
15201529
for (final char in text.split('')) {
15211530
final code = char.codeUnitAt(0);
15221531
final keyCode = code >= 97 && code <= 122 ? code - 32 : code;

0 commit comments

Comments
 (0)