Files
clide/lib/builtin/claude/src/claude_session_host.dart
T
jpmschweitzerandClaude 5ee759d0fd clear dart doc validate-links warnings
Eight unresolved doc references and broken README-rewritten links
that surfaced under `dart doc --validate-links`:

- Library-scope refs `[spawn]`, `[openProject]` qualified to
  `[Backend.spawn]` / `[Backend.openProject]`; same treatment for
  `[resolvePaths]` / `[applyResolved]` on Toolchain.
- `[D-41]` was a decision ID, not a Dart symbol — drop the brackets.
- `[from]` from I18n.interpolated qualified to `[I18nReplacer.from]`.
- `[DefaultSurfaceMap]` was a stale name (private `_defaultSurfaceMap`
  in resolver.dart); switch to backticked path reference since
  dartdoc can't link private members.
- `[icons/]` was a directory, not a symbol; backticked path.
- README links to `legacy/`, `docs/initial-plan.md`, `decisions/`,
  `LICENSE` rewritten as absolute github.com/postmeridiem/clide URLs
  so dartdoc stops re-rooting them into the doc tree.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-06 17:58:18 +02:00

83 lines
2.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:clide/widgets/widgets.dart';
import 'package:flutter/widgets.dart';
import 'claude_pane.dart';
/// Hosts the primary Claude pane plus N user-spawned secondary
/// sessions per D-41. Uses [MultitabPane] for the tab strip
/// (drag-reorder, close ×, + button) and [IndexedStack]-mode
/// keep-alive so switching tabs doesn't tear down the underlying
/// PTY-backed terminal.
class ClaudeSessionHost extends StatefulWidget {
const ClaudeSessionHost({super.key});
@override
State<ClaudeSessionHost> createState() => ClaudeSessionHostState();
}
class ClaudeSessionHostState extends State<ClaudeSessionHost> {
static const _primaryId = 'primary';
late final MultitabController<_Session> _controller;
int _nextSecondary = 1;
@override
void initState() {
super.initState();
_controller = MultitabController<_Session>(
initial: [
MultitabEntry<_Session>(
id: _primaryId,
title: 'primary',
payload: const _Session(isPrimary: true),
// Primary persists across clide restarts and never gets a
// close affordance (D-41).
closeable: false,
reorderable: false,
),
],
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
/// Public entry point used by the `claude.new-secondary` command.
void addSecondary() {
final index = _nextSecondary++;
_controller.add(MultitabEntry<_Session>(
id: 'secondary-$index',
title: 'session $index',
payload: _Session(isPrimary: false, secondaryIndex: index),
));
}
@override
Widget build(BuildContext context) {
return MultitabPane<_Session>(
controller: _controller,
keepAlive: true,
onAddRequested: addSecondary,
bodyBuilder: (ctx, entry) {
final s = entry.payload;
return ClaudePane(
isPrimary: s.isPrimary,
secondaryIndex: s.secondaryIndex,
// The MultitabPane already provides the tab strip header;
// suppressing the ClaudePane's own chrome avoids a double row.
showChrome: false,
);
},
);
}
}
class _Session {
const _Session({required this.isPrimary, this.secondaryIndex});
final bool isPrimary;
final int? secondaryIndex;
}