move the per-session status to the bottom status bar (T-145)
Per feedback, the model · permission-mode · context line reads better in the status bar than as a strip above the conversation. Adds a generic, publisher-agnostic status-bar context slot: a pane publishes a short string to the `statusbar.context` MessageBus channel and the bar shows the latest. The active Claude sub-tab publishes (inactive panes stay quiet, so no race); switching tabs swaps the slot to the focused pane. Replaces the in-pane ClaudeStatusStrip with a formatStatusLine helper + PaneContextStatusItem (the status-bar widget) and a StatusItemContribution. ClaudeSessionHost passes `active` so only the visible sub-tab publishes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,58 +0,0 @@
|
||||
/// Tests for the per-session status strip (T-145): formatters and the
|
||||
/// widget's render of model · permission-mode · context.
|
||||
library;
|
||||
|
||||
import 'package:clide/builtin/claude/src/claude_status_strip.dart';
|
||||
import 'package:clide/builtin/claude/src/transcript_reader.dart';
|
||||
import 'package:clide/widgets/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../helpers/kernel_fixture.dart';
|
||||
import '../../helpers/widget_harness.dart';
|
||||
|
||||
void main() {
|
||||
group('status formatters', () {
|
||||
test('shortModelLabel strips the claude- prefix and dots the version', () {
|
||||
expect(shortModelLabel('claude-opus-4-7'), 'opus 4.7');
|
||||
expect(shortModelLabel('claude-sonnet-4-6'), 'sonnet 4.6');
|
||||
expect(shortModelLabel('weird'), 'weird');
|
||||
});
|
||||
|
||||
test('permissionModeLabel humanises CC modes', () {
|
||||
expect(permissionModeLabel('acceptEdits'), 'accept-edits');
|
||||
expect(permissionModeLabel('bypassPermissions'), 'bypass');
|
||||
expect(permissionModeLabel('plan'), 'plan');
|
||||
expect(permissionModeLabel('default'), 'default');
|
||||
expect(permissionModeLabel('something-new'), 'something-new');
|
||||
});
|
||||
|
||||
test('formatTokenCount uses k / M / raw', () {
|
||||
expect(formatTokenCount(500), '500');
|
||||
expect(formatTokenCount(765000), '765k');
|
||||
expect(formatTokenCount(1200000), '1.2M');
|
||||
});
|
||||
});
|
||||
|
||||
group('ClaudeStatusStrip', () {
|
||||
late KernelFixture f;
|
||||
setUp(() async => f = await KernelFixture.create());
|
||||
tearDown(() => f.dispose());
|
||||
|
||||
testWidgets('renders model, mode, and context', (tester) async {
|
||||
await tester.pumpWidget(harness(
|
||||
f,
|
||||
const ClaudeStatusStrip(
|
||||
status: SessionStatus(model: 'claude-opus-4-7', permissionMode: 'acceptEdits', contextTokens: 765000),
|
||||
),
|
||||
));
|
||||
expect(find.textContaining('opus 4.7'), findsOneWidget);
|
||||
expect(find.textContaining('accept-edits'), findsOneWidget);
|
||||
expect(find.textContaining('765k ctx'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('empty status renders nothing', (tester) async {
|
||||
await tester.pumpWidget(harness(f, const ClaudeStatusStrip(status: SessionStatus())));
|
||||
expect(find.byType(ClideText), findsNothing);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/// Tests for the per-session status line formatting (T-145).
|
||||
library;
|
||||
|
||||
import 'package:clide/builtin/claude/src/claude_status.dart';
|
||||
import 'package:clide/builtin/claude/src/transcript_reader.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('status formatters', () {
|
||||
test('shortModelLabel strips the claude- prefix and dots the version', () {
|
||||
expect(shortModelLabel('claude-opus-4-7'), 'opus 4.7');
|
||||
expect(shortModelLabel('claude-sonnet-4-6'), 'sonnet 4.6');
|
||||
expect(shortModelLabel('weird'), 'weird');
|
||||
});
|
||||
|
||||
test('permissionModeLabel humanises CC modes', () {
|
||||
expect(permissionModeLabel('acceptEdits'), 'accept-edits');
|
||||
expect(permissionModeLabel('bypassPermissions'), 'bypass');
|
||||
expect(permissionModeLabel('plan'), 'plan');
|
||||
expect(permissionModeLabel('default'), 'default');
|
||||
expect(permissionModeLabel('something-new'), 'something-new');
|
||||
});
|
||||
|
||||
test('formatTokenCount uses k / M / raw', () {
|
||||
expect(formatTokenCount(500), '500');
|
||||
expect(formatTokenCount(765000), '765k');
|
||||
expect(formatTokenCount(1200000), '1.2M');
|
||||
});
|
||||
});
|
||||
|
||||
group('formatStatusLine', () {
|
||||
test('joins the present fields', () {
|
||||
const s = SessionStatus(model: 'claude-opus-4-7', permissionMode: 'acceptEdits', contextTokens: 21000);
|
||||
expect(formatStatusLine(s), 'opus 4.7 · accept-edits · 21k ctx');
|
||||
});
|
||||
|
||||
test('omits absent fields', () {
|
||||
expect(formatStatusLine(const SessionStatus(model: 'claude-sonnet-4-6')), 'sonnet 4.6');
|
||||
expect(formatStatusLine(const SessionStatus()), '');
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/// Tests for the status-bar in-pane context slot (T-145): it shows the
|
||||
/// latest text published on the bus channel and clears on empty.
|
||||
library;
|
||||
|
||||
import 'package:clide/builtin/claude/src/pane_context_status.dart';
|
||||
import 'package:clide/widgets/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../../helpers/kernel_fixture.dart';
|
||||
import '../../helpers/widget_harness.dart';
|
||||
|
||||
void main() {
|
||||
late KernelFixture f;
|
||||
setUp(() async => f = await KernelFixture.create());
|
||||
tearDown(() => f.dispose());
|
||||
|
||||
testWidgets('renders the latest published context, clears on empty', (tester) async {
|
||||
await tester.pumpWidget(harness(f, const PaneContextStatusItem()));
|
||||
await tester.pump();
|
||||
expect(find.byType(ClideText), findsNothing); // nothing published yet
|
||||
|
||||
publishPaneContext(f.services.messages, 'builtin.claude', 'opus 4.7 · default · 21k ctx');
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
expect(find.textContaining('opus 4.7'), findsOneWidget);
|
||||
|
||||
// A newer publisher overwrites the slot.
|
||||
publishPaneContext(f.services.messages, 'builtin.editor', 'lib/app.dart · modified');
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
expect(find.textContaining('opus 4.7'), findsNothing);
|
||||
expect(find.textContaining('lib/app.dart'), findsOneWidget);
|
||||
|
||||
// Empty clears it.
|
||||
publishPaneContext(f.services.messages, 'builtin.editor', '');
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
expect(find.byType(ClideText), findsNothing);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user