finish T-235 (persisted activity fold level); close T-132 via Q-34
T-235: app-scoped kActivityFoldLevelKey + a claude.activity.fold-level command that cycles none→tools→thinking→everything; ClaudePane + team_panel_host read it and re-fold live via the settings notifier. Unit tests for the helpers. T-132 cleanup: the one blocked item (account/team token budget) is detached (T-158), reframed as Q-34 'how + when to surface the budget given upstream doesn't expose it', with T-158 as its backlog resolver. T-132 closed — all doable work delivered. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,18 @@ enum FoldLevel {
|
||||
everything,
|
||||
}
|
||||
|
||||
/// Settings key for the persisted activity-card fold level (T-235). App-scoped:
|
||||
/// a personal viewing preference, not per-repo.
|
||||
const String kActivityFoldLevelKey = 'app.claude.activityFoldLevel';
|
||||
|
||||
/// Parse a stored fold-level name back to a [FoldLevel], defaulting to L1
|
||||
/// ([FoldLevel.tools]) for null/unknown values.
|
||||
FoldLevel foldLevelFromName(String? name) => FoldLevel.values.firstWhere((l) => l.name == name, orElse: () => FoldLevel.tools);
|
||||
|
||||
/// The next fold level in the cycle none → tools → thinking → everything → none
|
||||
/// (T-235), for the toggle command.
|
||||
FoldLevel nextFoldLevel(FoldLevel level) => FoldLevel.values[(level.index + 1) % FoldLevel.values.length];
|
||||
|
||||
/// A unit the conversation view renders: either a single first-class item or
|
||||
/// a folded run of meta items.
|
||||
sealed class RenderGroup {
|
||||
|
||||
@@ -10,6 +10,7 @@ import 'claude_composer.dart';
|
||||
import 'claude_config.dart';
|
||||
import 'claude_status.dart';
|
||||
import 'clipboard_paste.dart';
|
||||
import 'activity_cluster.dart' show foldLevelFromName, kActivityFoldLevelKey;
|
||||
import 'conversation_controller.dart';
|
||||
import 'conversation_view.dart';
|
||||
import 'permission_mode_control.dart';
|
||||
@@ -152,12 +153,20 @@ class _ClaudePaneState extends State<ClaudePane> {
|
||||
// GlobalKey and spawns once, so without this it would keep the previous
|
||||
// repo's session after a switch (T-269).
|
||||
_projectSub = ClideKernel.of(context).events.on<ProjectOpened>().listen(_onProjectChanged);
|
||||
// Re-fold the conversation when the activity fold-level setting changes
|
||||
// (claude.activity.fold-level command, T-235).
|
||||
ClideKernel.of(context).settings.addListener(_onSettingsChanged);
|
||||
}
|
||||
}
|
||||
|
||||
void _onSettingsChanged() {
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
activeClaudeConfig?.removeListener(_onConfigChanged);
|
||||
_kernel()?.settings.removeListener(_onSettingsChanged);
|
||||
_projectSub?.cancel();
|
||||
_projectSub = null;
|
||||
_statusSub?.cancel();
|
||||
@@ -493,6 +502,7 @@ class _ClaudePaneState extends State<ClaudePane> {
|
||||
onTap: _focusComposerOnTap,
|
||||
child: ConversationView(
|
||||
controller: _conversation!,
|
||||
foldLevel: foldLevelFromName(_kernel()?.settings.get<String>(kActivityFoldLevelKey)),
|
||||
hiddenToolUseIds: _session?.promptedToolUseIds ?? const <String>{},
|
||||
toolUseOutcomes: _session?.toolUseOutcomes ?? const <String, bool>{},
|
||||
emptyState: ClaudeBanner(
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:clide/clide.dart';
|
||||
import 'package:clide/builtin/claude/src/activity_cluster.dart' show foldLevelFromName, kActivityFoldLevelKey, nextFoldLevel;
|
||||
import 'package:clide/builtin/claude/src/claude_config.dart';
|
||||
import 'package:clide/builtin/claude/src/claude_status.dart' show nextSafePermissionMode;
|
||||
import 'package:clide/builtin/claude/src/claude_session_host.dart';
|
||||
@@ -76,6 +77,15 @@ class ClaudeExtension extends ClideExtension {
|
||||
title: 'Claude: session storage (disk usage + cleanup)',
|
||||
run: _manageStorage,
|
||||
),
|
||||
// T-235: cycle how aggressively the activity card folds meta steps
|
||||
// (none → tools → thinking → everything), persisted app-wide. The panes
|
||||
// read kActivityFoldLevelKey and rebuild via the settings notifier.
|
||||
CommandContribution(
|
||||
id: 'claude.activity.fold-level',
|
||||
command: 'claude.activity.fold-level',
|
||||
title: 'Claude: cycle activity fold level',
|
||||
run: _cycleFoldLevel,
|
||||
),
|
||||
// T-171: agent roster controls (D-6 CLI/UI parity).
|
||||
// Usage: clide claude.agent.show <sessionId>
|
||||
CommandContribution(
|
||||
@@ -403,6 +413,18 @@ class ClaudeExtension extends ClideExtension {
|
||||
/// this when they want a hard reset — after a Claude wedge or to start
|
||||
/// completely fresh. All sessions are torn down through the orchestrator
|
||||
/// (D-77); the primary will re-spawn and resume on the next pane build.
|
||||
/// Cycle the persisted activity fold level (T-235). Reads the current value
|
||||
/// from settings, advances none → tools → thinking → everything → none, and
|
||||
/// writes it back; the panes listen to settings and re-fold live.
|
||||
Future<IpcResponse> _cycleFoldLevel(List<String> args) async {
|
||||
final ctx = _ctx;
|
||||
if (ctx == null) return IpcResponse.ok(id: '', data: const {});
|
||||
final current = foldLevelFromName(ctx.settings.get<String>(kActivityFoldLevelKey));
|
||||
final next = nextFoldLevel(current);
|
||||
await ctx.settings.set<String>(kActivityFoldLevelKey, next.name);
|
||||
return IpcResponse.ok(id: '', data: {'foldLevel': next.name});
|
||||
}
|
||||
|
||||
Future<IpcResponse> _killAllSessions(List<String> args) async {
|
||||
final orch = _orchestrator;
|
||||
if (orch == null) return IpcResponse.ok(id: '', data: const {});
|
||||
|
||||
@@ -11,6 +11,7 @@ library;
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:clide/builtin/claude/src/conversation_controller.dart';
|
||||
import 'package:clide/builtin/claude/src/activity_cluster.dart' show foldLevelFromName, kActivityFoldLevelKey;
|
||||
import 'package:clide/builtin/claude/src/conversation_view.dart';
|
||||
import 'package:clide/builtin/claude/src/transcript_publisher.dart';
|
||||
import 'package:clide/kernel/kernel.dart';
|
||||
@@ -202,7 +203,17 @@ class _TeammateTile extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(child: ConversationView(controller: controller, wrapInSelectionArea: false)),
|
||||
Expanded(
|
||||
// Re-fold live with the activity fold-level setting (T-235).
|
||||
child: ListenableBuilder(
|
||||
listenable: ClideKernel.of(context).settings,
|
||||
builder: (ctx, _) => ConversationView(
|
||||
controller: controller,
|
||||
wrapInSelectionArea: false,
|
||||
foldLevel: foldLevelFromName(ClideKernel.of(ctx).settings.get<String>(kActivityFoldLevelKey)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user