Add command files and enhance session management features

This commit is contained in:
ImBenji
2026-04-28 19:00:27 +01:00
parent 3588783001
commit 728c0ffe81
146 changed files with 6854 additions and 7783 deletions
@@ -0,0 +1,52 @@
import 'package:clawd_code/ui/widgets/common/button.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart';
class AccountButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return AgcGhostButton(
onPressed: () {
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Avatar(
initials: "BW",
),
Gap(12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Benjamin Watt"
).small,
Text(
"Pro plan"
).xSmall.muted
],
),
Spacer(),
Icon(
LucideIcons.ellipsisVertical
),
Gap(10),
],
),
),
);
}
}
+90 -18
View File
@@ -1,3 +1,5 @@
import "package:clawd_code/ui/widgets/sidebar/account_button.dart";
import "package:flutter/services.dart" show Clipboard, ClipboardData;
import "package:provider/provider.dart";
import "package:shadcn_flutter/shadcn_flutter.dart";
@@ -11,29 +13,69 @@ import "app_logo.dart";
import "../common/button.dart";
class SidebarV2 extends StatelessWidget {
const SidebarV2({super.key});
final VoidCallback? onClose;
const SidebarV2({super.key, this.onClose});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container(
width: 300,
width: 320,
color: theme.colorScheme.input.scaleAlpha(0.3),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (onClose != null) ...[
Container(
alignment: Alignment.topLeft,
padding: EdgeInsets.all(8),
child: IconButton.ghost(
onPressed: onClose,
icon: Icon(
LucideIcons.panelLeftClose,
size: 16,
color: theme.colorScheme.mutedForeground,
),
),
),
],
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 28),
child: AppLogo(),
padding: const EdgeInsets.only(
left: 16, bottom: 22
),
child: Row(
children: [
Expanded(child: AppLogo()),
],
),
),
// Divider(color: theme.colorScheme.border, height: 1),
_ActionsSection(),
Divider(color: theme.colorScheme.border, height: 1),
// Divider(color: theme.colorScheme.border, height: 1),
Expanded(child: _ProjectsSection()),
Divider(),
Expanded(
child: Padding(
padding: const EdgeInsets.all(4),
child: OutlinedContainer(
borderRadius: BorderRadius.zero,
child: _ProjectsSection()
),
)
),
Divider(),
AccountButton(),
],
),
);
@@ -68,7 +110,7 @@ class _ActionsSection extends StatelessWidget {
onTap: coordinator.pickProjectDirectory,
),
Divider(color: theme.colorScheme.border, height: 1),
// Divider(color: theme.colorScheme.border, height: 1),
],
);
}
@@ -132,6 +174,11 @@ class _ProjectsSection extends StatelessWidget {
physics: const ClampingScrollPhysics(),
padding: EdgeInsets.zero,
children: [
// _SectionHeader(title: "PROJECTS", large: true),
//
// Divider(color: theme.colorScheme.background, height: 1),
for (final project in projects) ...[
_CollapsibleProjectSection(
projectName: project.name,
@@ -224,7 +271,9 @@ class _CollapsibleProjectSectionState
),
),
Divider(color: theme.colorScheme.border, height: 1),
if (_expanded) ...[
Divider(color: theme.colorScheme.background, height: 1),
],
if (_expanded) ...[
if (widget.sessions.isEmpty)
@@ -258,25 +307,38 @@ class _CollapsibleProjectSectionState
class _SectionHeader extends StatelessWidget {
final String title;
final bool large;
const _SectionHeader({required this.title});
const _SectionHeader({required this.title, this.large = false});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
TextStyle style;
if (large) {
style = TextStyle(
fontSize: 22,
fontWeight: FontWeight.w600,
color: theme.colorScheme.foreground,
letterSpacing: 0.4,
);
} else {
style = TextStyle(
fontSize: 11,
fontWeight: FontWeight.w600,
color: theme.colorScheme.foreground,
letterSpacing: 0.4,
);
}
return ColoredBox(
color: theme.colorScheme.secondary,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
child: Text(
title,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w600,
color: theme.colorScheme.foreground,
letterSpacing: 0.4,
),
style: style
),
),
);
@@ -296,12 +358,12 @@ class _PanelItem extends StatelessWidget {
final muted = onTap == null;
return Padding(
padding: const EdgeInsets.all(1),
padding: const EdgeInsets.all(0),
child: AgcGhostButton(
onPressed: onTap,
borderRadius: BorderRadius.zero,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 9),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
child: Row(
children: [
Icon(
@@ -384,6 +446,16 @@ class _ThreadItem extends StatelessWidget {
return ContextMenu(
items: [
MenuButton(
leading: const Icon(LucideIcons.copy).iconSmall,
onPressed: (_) {
final dir = session.workingDirectory ?? "";
final path = "$dir/.the_agency/sessions/${session.id}.json";
Clipboard.setData(ClipboardData(text: path));
},
child: const Text("Copy session path"),
),
MenuButton(
leading: const Icon(LucideIcons.trash2).iconSmall,
onPressed: (_) => onDelete(),
@@ -391,7 +463,7 @@ class _ThreadItem extends StatelessWidget {
),
],
child: Container(
margin: EdgeInsets.all(1),
// margin: EdgeInsets.all(1),
decoration: BoxDecoration(
color: glowColor != null
? glowColor.withAlpha(selected ? 55 : 30)