Files
clide/lib/widgets/src/clide_selection_area.dart
T
jpmschweitzerandClaude 76c1d24904
test / unit + widget + golden + a11y (push) Failing after 27s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 27s
render the Claude pane natively from the transcript (T-137)
The Phase-1 wedge of epic T-132 (D-75): the Claude pane no longer
renders the PTY's TUI. It runs claude in tmux as before (so the
transcript is written) but displays the conversation as native cards
read from the transcript via TranscriptReader — user / assistant
markdown / thinking / tool-use / tool-result. The whole list sits under
a new no-Material ClideSelectionArea (SelectableRegion-based, since
Flutter's SelectionArea is Material and D-7 bans it), so text selects
and copies across cards — recovering the terminal's one real advantage.

ClaudePane drops its Terminal model and the resize-driven spawn trigger
(spawn now fires once on didChangeDependencies with a fixed tmux size,
since the TUI isn't shown); pane.output is no longer consumed. The
terminal builtin is untouched and still available as a general tool.
Input/composer is the next ticket (T-138).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-22 20:12:30 +02:00

44 lines
1.4 KiB
Dart

import 'package:flutter/widgets.dart';
/// No-Material text selection wrapper (D-7 — clide ships no Material).
///
/// Flutter's convenient `SelectionArea` lives in `package:flutter/material.dart`,
/// so clide can't use it. This wraps the widget-layer [SelectableRegion]
/// with the desktop-appropriate setup: a managed [FocusNode], no on-screen
/// selection handles (`emptyTextSelectionControls` — desktop selects by
/// mouse drag), and [DefaultTextEditingShortcuts] so Ctrl/Cmd+A and
/// Ctrl/Cmd+C work even outside a `WidgetsApp`.
///
/// Any descendant `Text` / `Text.rich` (e.g. [ClideMarkdown],
/// [ClideCodeBlock] after T-135) becomes selectable, and selection +
/// copy span across them.
class ClideSelectionArea extends StatefulWidget {
const ClideSelectionArea({super.key, required this.child});
final Widget child;
@override
State<ClideSelectionArea> createState() => _ClideSelectionAreaState();
}
class _ClideSelectionAreaState extends State<ClideSelectionArea> {
final FocusNode _focusNode = FocusNode(debugLabel: 'ClideSelectionArea');
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return DefaultTextEditingShortcuts(
child: SelectableRegion(
focusNode: _focusNode,
selectionControls: emptyTextSelectionControls,
child: widget.child,
),
);
}
}