feat(ui): details island with agent strip, terminal, subtasks, notes
Adds AgentStripView (status/model/turns/tokens row, worktree path, branch line, action buttons), SessionTerminalView (scrollable log with auto-scroll on CollectionChanged, prompt TextBox with Enter binding), and replaces DetailsIslandView placeholder with full ScrollViewer layout containing editable title, agent strip, terminal, subtasks, notes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
39
src/ClaudeDo.Ui/Views/Islands/AgentStripView.axaml
Normal file
39
src/ClaudeDo.Ui/Views/Islands/AgentStripView.axaml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Islands"
|
||||||
|
x:Class="ClaudeDo.Ui.Views.Islands.AgentStripView"
|
||||||
|
x:DataType="vm:DetailsIslandViewModel">
|
||||||
|
<Border Classes="agent-strip">
|
||||||
|
<StackPanel Margin="14,12" Spacing="6">
|
||||||
|
<!-- Row 1: status dot · status label · model · turns · tokens -->
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||||
|
<Ellipse Width="8" Height="8" Fill="{DynamicResource MossBrush}" VerticalAlignment="Center"/>
|
||||||
|
<TextBlock Text="{Binding AgentStatusLabel}" FontSize="12"
|
||||||
|
Foreground="{DynamicResource TextBrush}" VerticalAlignment="Center"/>
|
||||||
|
<TextBlock Text="{Binding Model}" FontFamily="{DynamicResource MonoFamily}"
|
||||||
|
FontSize="11" Foreground="{DynamicResource TextDimBrush}" VerticalAlignment="Center"
|
||||||
|
IsVisible="{Binding Model, Converter={x:Static ObjectConverters.IsNotNull}}"/>
|
||||||
|
<TextBlock Text="{Binding Turns, StringFormat='turns: {0}'}" FontSize="11"
|
||||||
|
Foreground="{DynamicResource TextMuteBrush}" VerticalAlignment="Center"/>
|
||||||
|
<TextBlock Text="{Binding Tokens, StringFormat='tok: {0}'}" FontSize="11"
|
||||||
|
Foreground="{DynamicResource TextMuteBrush}" VerticalAlignment="Center"/>
|
||||||
|
</StackPanel>
|
||||||
|
<!-- Row 2: worktree path -->
|
||||||
|
<TextBlock Text="{Binding WorktreePath}" FontFamily="{DynamicResource MonoFamily}"
|
||||||
|
FontSize="11" Foreground="{DynamicResource TextDimBrush}"
|
||||||
|
TextTrimming="CharacterEllipsis"
|
||||||
|
IsVisible="{Binding WorktreePath, Converter={x:Static ObjectConverters.IsNotNull}}"/>
|
||||||
|
<!-- Row 3: branch line -->
|
||||||
|
<TextBlock Text="{Binding BranchLine}" FontFamily="{DynamicResource MonoFamily}"
|
||||||
|
FontSize="11" Foreground="{DynamicResource TextDimBrush}"
|
||||||
|
IsVisible="{Binding BranchLine, Converter={x:Static ObjectConverters.IsNotNull}}"/>
|
||||||
|
<!-- Button row -->
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,6,0,0">
|
||||||
|
<Button Classes="icon-btn" Content="Open diff"/>
|
||||||
|
<Button Classes="icon-btn" Content="Worktree"/>
|
||||||
|
<Button Classes="icon-btn" Content="Stop" Command="{Binding StopCommand}"/>
|
||||||
|
<Button Classes="icon-btn" Content="Approve & merge" Command="{Binding ApproveMergeCommand}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</UserControl>
|
||||||
8
src/ClaudeDo.Ui/Views/Islands/AgentStripView.axaml.cs
Normal file
8
src/ClaudeDo.Ui/Views/Islands/AgentStripView.axaml.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace ClaudeDo.Ui.Views.Islands;
|
||||||
|
|
||||||
|
public partial class AgentStripView : UserControl
|
||||||
|
{
|
||||||
|
public AgentStripView() { InitializeComponent(); }
|
||||||
|
}
|
||||||
@@ -1,8 +1,34 @@
|
|||||||
<UserControl xmlns="https://github.com/avaloniaui"
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Islands"
|
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Islands"
|
||||||
|
xmlns:islands="using:ClaudeDo.Ui.Views.Islands"
|
||||||
x:Class="ClaudeDo.Ui.Views.Islands.DetailsIslandView"
|
x:Class="ClaudeDo.Ui.Views.Islands.DetailsIslandView"
|
||||||
x:DataType="vm:DetailsIslandViewModel">
|
x:DataType="vm:DetailsIslandViewModel">
|
||||||
<TextBlock Margin="14" Text="Details (placeholder)"
|
<ScrollViewer>
|
||||||
Foreground="{DynamicResource TextDimBrush}"/>
|
<StackPanel Margin="18,14" Spacing="14">
|
||||||
|
<!-- Editable title -->
|
||||||
|
<TextBox Text="{Binding EditableTitle, Mode=TwoWay}" FontSize="18"
|
||||||
|
BorderThickness="0" Background="Transparent"
|
||||||
|
Foreground="{DynamicResource TextBrush}"/>
|
||||||
|
<!-- Agent strip (only when a worktree exists or task is active) -->
|
||||||
|
<islands:AgentStripView/>
|
||||||
|
<!-- Session terminal: log + prompt -->
|
||||||
|
<islands:SessionTerminalView Height="260"/>
|
||||||
|
<!-- Subtasks -->
|
||||||
|
<ItemsControl ItemsSource="{Binding Subtasks}">
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate DataType="vm:SubtaskRowViewModel">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8" Margin="0,2">
|
||||||
|
<CheckBox IsChecked="{Binding Done, Mode=TwoWay}"/>
|
||||||
|
<TextBlock Text="{Binding Title}" VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource TextBrush}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
<!-- Notes -->
|
||||||
|
<TextBox Text="{Binding Notes, Mode=TwoWay}" AcceptsReturn="True"
|
||||||
|
TextWrapping="Wrap" MinHeight="80" PlaceholderText="Notes…"/>
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -21,9 +21,10 @@
|
|||||||
<ScrollViewer Name="LogScroll" VerticalScrollBarVisibility="Auto">
|
<ScrollViewer Name="LogScroll" VerticalScrollBarVisibility="Auto">
|
||||||
<ItemsControl ItemsSource="{Binding Log}">
|
<ItemsControl ItemsSource="{Binding Log}">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate x:CompileBindings="False" DataType="vm:LogLineViewModel">
|
<DataTemplate DataType="vm:LogLineViewModel">
|
||||||
<TextBlock Text="{Binding Text}" Classes="{Binding ClassName}"
|
<TextBlock Text="{Binding Text}" Tag="{Binding ClassName}"
|
||||||
FontFamily="{DynamicResource MonoFamily}" FontSize="11"
|
FontFamily="{DynamicResource MonoFamily}" FontSize="11"
|
||||||
|
Foreground="{DynamicResource TextDimBrush}"
|
||||||
TextWrapping="Wrap"/>
|
TextWrapping="Wrap"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
|
|||||||
23
src/ClaudeDo.Ui/Views/Islands/SessionTerminalView.axaml.cs
Normal file
23
src/ClaudeDo.Ui/Views/Islands/SessionTerminalView.axaml.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System.Collections.Specialized;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using ClaudeDo.Ui.ViewModels.Islands;
|
||||||
|
|
||||||
|
namespace ClaudeDo.Ui.Views.Islands;
|
||||||
|
|
||||||
|
public partial class SessionTerminalView : UserControl
|
||||||
|
{
|
||||||
|
public SessionTerminalView() { InitializeComponent(); }
|
||||||
|
|
||||||
|
protected override void OnDataContextChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnDataContextChanged(e);
|
||||||
|
if (DataContext is DetailsIslandViewModel vm)
|
||||||
|
vm.Log.CollectionChanged += OnLogChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLogChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||||
|
LogScroll.ScrollToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user