render the Claude pane natively from the transcript (T-137)
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

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>
This commit is contained in:
2026-05-22 20:12:30 +02:00
co-authored by Claude
parent 3f2e5ad9a9
commit 76c1d24904
9 changed files with 524 additions and 76 deletions
+43
View File
@@ -0,0 +1,43 @@
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,
),
);
}
}