focus the Claude composer on a background tap
T-227. A tap on empty conversation area now lands the cursor in the composer. The conversation area is wrapped in a translucent GestureDetector whose onTap focuses a pane-owned composer FocusNode, so message links, copy buttons, and the SelectableRegion's selection drags keep winning their own gestures — only an unclaimed tap reaches us. It's a no-op while a prompt holds the interaction zone (D-78), so a tap never pulls focus over an open prompt. The composer learned to accept an external focus node (the pane owns it, so it survives composer remounts) and attaches its key handling to whichever node it's given. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -336,6 +336,39 @@ void main() {
|
||||
});
|
||||
});
|
||||
|
||||
group('ClaudeComposer external focus node (T-227)', () {
|
||||
late KernelFixture f;
|
||||
setUp(() async => f = await KernelFixture.create());
|
||||
tearDown(() => f.dispose());
|
||||
|
||||
testWidgets('uses a supplied focus node and focuses the input on request', (tester) async {
|
||||
final node = FocusNode();
|
||||
addTearDown(node.dispose);
|
||||
await tester.pumpWidget(harness(f, ClaudeComposer(onSubmit: (_) {}, focusNode: node)));
|
||||
|
||||
expect(tester.widget<EditableText>(find.byType(EditableText)).focusNode, same(node));
|
||||
|
||||
node.requestFocus(); // what the pane does on a background tap
|
||||
await tester.pump();
|
||||
expect(node.hasFocus, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('key handling still works through the supplied node', (tester) async {
|
||||
final submitted = <String>[];
|
||||
final node = FocusNode();
|
||||
addTearDown(node.dispose);
|
||||
await tester.pumpWidget(harness(
|
||||
f,
|
||||
ClaudeComposer(onSubmit: submitted.add, focusNode: node),
|
||||
));
|
||||
await tester.enterText(find.byType(EditableText), 'via external node');
|
||||
await tester.pump();
|
||||
await tester.sendKeyEvent(LogicalKeyboardKey.enter);
|
||||
await tester.pump();
|
||||
expect(submitted, ['via external node']);
|
||||
});
|
||||
});
|
||||
|
||||
group('ClaudeComposer prompt history (T-163)', () {
|
||||
late KernelFixture f;
|
||||
setUp(() async => f = await KernelFixture.create());
|
||||
|
||||
Reference in New Issue
Block a user