Add command files and enhance session management features
This commit is contained in:
@@ -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),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user