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
+84 -62
View File
@@ -10,6 +10,7 @@ import "../../widgets/chat/chat_box.dart";
import "../../widgets/chat/chat_view.dart";
import "../../widgets/common/footer_bar.dart";
import "../../widgets/common/app_header.dart";
import "../../widgets/common/button.dart";
import "../../widgets/sidebar/sidebar.dart";
import "../../widgets/sidebar/sidebar_v2.dart";
@@ -137,19 +138,38 @@ class _ChatArea extends StatelessWidget {
return Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(16),
// padding: const EdgeInsets.all(16),
padding: EdgeInsets.only(
left: 16,
right: 16
),
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 600),
constraints: const BoxConstraints(maxWidth: 700),
child: Column(
children: [
Expanded(
child: chatProvider.messages.isEmpty
? _EmptyChatState()
: ChatView(scrollController: scrollController),
),
if (chatProvider.messages.isEmpty)...[
Expanded(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_EmptyChatState(),
ChatBox(),
],
),
)
),
] else ...[
Expanded(child: ChatView(scrollController: scrollController)),
ChatBox(),
Gap(12),
],
ChatBox(),
],
),
@@ -177,58 +197,15 @@ class _EmptyChatState extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(LucideIcons.messagesSquare, size: 28),
const Gap(16),
Text(
"Ask the agency anything",
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.w700),
"Lets burn some braincells",
textAlign: TextAlign.center,
),
const Gap(8),
).x4Large.extraBold,
Text(
"Select a project and thread from the sidebar, or start a new chat.",
textAlign: TextAlign.center,
).textSmall.muted,
const Gap(24),
Select<ProjectRecord>(
itemBuilder: (context, item) => Text(item.name),
popup: SelectPopup.builder(
searchPlaceholder: const Text("Search projects"),
builder: (context, searchQuery) {
final filtered = searchQuery == null || searchQuery.isEmpty
? projects
: projects.where((p) =>
p.name.toLowerCase().contains(searchQuery.toLowerCase()) ||
p.workingDirectory.toLowerCase().contains(searchQuery.toLowerCase())
).toList();
return SelectItemList(
children: [
for (final project in filtered)
SelectItemButton(
value: project,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(project.name),
Text(project.workingDirectory).textSmall.muted,
],
),
),
],
);
},
),
onChanged: (project) {
if (project != null) coordinator.selectProject(project);
},
constraints: const BoxConstraints(minWidth: 240),
value: selected,
placeholder: const Text("Select a project"),
),
],
),
),
@@ -272,24 +249,69 @@ class _InsetShadowPainter extends CustomPainter {
}
class _SidebarPane extends StatelessWidget {
class _SidebarPane extends StatefulWidget {
const _SidebarPane();
@override
State<_SidebarPane> createState() => _SidebarPaneState();
}
class _SidebarPaneState extends State<_SidebarPane> {
bool _open = true;
static const _dur = Duration(milliseconds: 220);
static const _curve = Curves.easeInOut;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return OutlinedContainer(
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.15),
blurRadius: 16,
spreadRadius: 2,
return Stack(
clipBehavior: Clip.none,
children: [
AnimatedSlide(
offset: _open ? Offset.zero : const Offset(-1.1, 0),
duration: _dur,
curve: _curve,
child: AnimatedOpacity(
opacity: _open ? 1.0 : 0.0,
duration: _dur,
curve: _curve,
child: OutlinedContainer(
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.15),
blurRadius: 16,
spreadRadius: 2,
),
],
child: SidebarV2(onClose: () => setState(() => _open = false)),
),
),
),
AnimatedOpacity(
opacity: _open ? 0.0 : 1.0,
duration: _dur,
curve: _curve,
child: IgnorePointer(
ignoring: _open,
child: IconButton.ghost(
onPressed: () => setState(() => _open = true),
icon: Icon(
LucideIcons.panelLeftOpen,
size: 16,
color: theme.colorScheme.mutedForeground,
),
),
),
),
],
child: SidebarV2(),
);
}
}