Migrate ClideTheme.of(context) reads across the widget, feature, and shell layers to the unified ClideSettings.theme.of(context) facade (D-101), so theme/i18n/fonts/settings share one widget-facing entry. The facade delegates straight to ClideTheme, so behaviour is unchanged — goldens are unmoved. The low-level theme provider keeps its direct ClideTheme.of: the facade is built on it, and the two kernel sites (ClideTheme's own definition + the panels drag-resize widget) stay direct to avoid a widgets→kernel import cycle. Dead controller.dart/kernel.dart imports left by the sweep removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
99 lines
3.6 KiB
Dart
99 lines
3.6 KiB
Dart
/// The Team tab: the roster cockpit (T-171) — per-member rows with
|
|
/// controls, the TASKS section, and the MESSAGES chat feed (T-180).
|
|
/// Stateless and props-driven; the parent owns the member list, inject
|
|
/// state, and orchestrator wiring. Split out of claude_meta_sidebar.dart
|
|
/// (T-395).
|
|
library;
|
|
|
|
import 'package:clide/builtin/claude/src/meta_sidebar/models.dart';
|
|
import 'package:clide/builtin/claude/src/meta_sidebar/roster_row.dart';
|
|
import 'package:clide/builtin/claude/src/meta_sidebar/task_row.dart';
|
|
import 'package:clide/builtin/claude/src/session_orchestrator.dart';
|
|
import 'package:clide/builtin/claude/src/team_broker.dart' show TeamTask;
|
|
import 'package:clide/builtin/claude/src/team_chat_sidebar.dart' show TeamChatSidebar;
|
|
import 'package:clide/builtin/claude/src/transcript_reader.dart' show SessionStatus;
|
|
import 'package:clide/kernel/kernel.dart';
|
|
import 'package:clide/widgets/widgets.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
class TeamTabView extends StatelessWidget {
|
|
const TeamTabView({
|
|
super.key,
|
|
required this.members,
|
|
required this.memberStatus,
|
|
required this.orchestrator,
|
|
required this.tasks,
|
|
required this.injectingAgentId,
|
|
required this.injectController,
|
|
required this.onToggleInject,
|
|
required this.onInjectSubmit,
|
|
required this.onClose,
|
|
required this.onSetPermissionMode,
|
|
required this.onFork,
|
|
required this.onOpenChatPane,
|
|
});
|
|
|
|
final List<TeamMemberJoined> members;
|
|
final Map<String, SessionStatus> memberStatus;
|
|
final ClaudeSessionOrchestrator? orchestrator;
|
|
final List<TeamTask> tasks;
|
|
final String? injectingAgentId;
|
|
final TextEditingController injectController;
|
|
final void Function(String memberName) onToggleInject;
|
|
final void Function(String memberName, String text) onInjectSubmit;
|
|
final void Function(String memberName) onClose;
|
|
final void Function(String memberName, String mode) onSetPermissionMode;
|
|
final void Function(String memberName) onFork;
|
|
final VoidCallback onOpenChatPane;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final tokens = ClideSettings.theme.of(context).surface;
|
|
if (members.isEmpty) {
|
|
return metaPlaceholder('No team active.');
|
|
}
|
|
final children = <Widget>[
|
|
for (final m in members)
|
|
AgentRosterRow(
|
|
key: ValueKey(m.agentId),
|
|
member: m,
|
|
status: memberStatus[m.agentId],
|
|
orchestrator: orchestrator,
|
|
injectingAgentId: injectingAgentId,
|
|
injectController: injectController,
|
|
onToggleInject: onToggleInject,
|
|
onInjectSubmit: onInjectSubmit,
|
|
onClose: onClose,
|
|
onSetPermissionMode: onSetPermissionMode,
|
|
onFork: onFork,
|
|
),
|
|
];
|
|
|
|
if (tasks.isNotEmpty) {
|
|
children.add(const SizedBox(height: 12));
|
|
children.add(_taskSection(tokens));
|
|
}
|
|
|
|
// MESSAGES section (T-180): live broker chat feed + quick-post composer.
|
|
final chatModel = orchestrator?.chatModel;
|
|
final broker = orchestrator?.broker;
|
|
if (chatModel != null && broker != null) {
|
|
children.add(const SizedBox(height: 12));
|
|
children.add(TeamChatSidebar(model: chatModel, broker: broker, onPopOut: onOpenChatPane));
|
|
}
|
|
|
|
return ListView(padding: const EdgeInsets.all(12), children: children);
|
|
}
|
|
|
|
Widget _taskSection(SurfaceTokens tokens) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
ClideText('TASKS', fontSize: clideFontSmall, color: tokens.globalTextMuted),
|
|
const SizedBox(height: 4),
|
|
for (final t in tasks) TaskRow(task: t, members: members, broker: orchestrator?.broker),
|
|
],
|
|
);
|
|
}
|
|
}
|