chore(ui): remove obsolete pre-rewrite views and viewmodels
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:ClaudeDo.Ui.ViewModels"
|
||||
xmlns:svc="using:ClaudeDo.Data.Models"
|
||||
x:Class="ClaudeDo.Ui.Views.ListEditorView"
|
||||
x:DataType="vm:ListEditorViewModel"
|
||||
Title="{Binding WindowTitle}"
|
||||
Width="450" Height="480"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False"
|
||||
Background="{StaticResource WindowBgBrush}">
|
||||
<StackPanel Margin="16" Spacing="10">
|
||||
<TextBlock Text="Name" FontWeight="SemiBold" Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<TextBox Text="{Binding Name}" PlaceholderText="List name..."/>
|
||||
|
||||
<TextBlock Text="Working Directory" FontWeight="SemiBold" Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<DockPanel>
|
||||
<Button DockPanel.Dock="Right" Content="Browse..." Click="OnBrowseFolder" Margin="8,0,0,0" VerticalAlignment="Center"/>
|
||||
<TextBox Text="{Binding WorkingDir}" PlaceholderText="(optional) Absolute path to git repo"/>
|
||||
</DockPanel>
|
||||
|
||||
<TextBlock Text="Default Commit Type" FontWeight="SemiBold" Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<ComboBox ItemsSource="{Binding CommitTypes}"
|
||||
SelectedItem="{Binding DefaultCommitType}"
|
||||
MinWidth="150"/>
|
||||
|
||||
<Border Height="1" Background="{StaticResource BorderSubtleBrush}" Margin="0,6,0,2"/>
|
||||
|
||||
<TextBlock Text="Agent Config" FontWeight="Bold" FontSize="13"
|
||||
Foreground="{StaticResource TextPrimaryBrush}"/>
|
||||
|
||||
<TextBlock Text="Model" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<ComboBox ItemsSource="{Binding ModelDisplayNames}"
|
||||
SelectedItem="{Binding Model}"
|
||||
MinWidth="150"/>
|
||||
|
||||
<TextBlock Text="System Prompt" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<TextBox Text="{Binding SystemPrompt}"
|
||||
PlaceholderText="(optional) Additional system instructions..."
|
||||
AcceptsReturn="True" TextWrapping="Wrap" MinHeight="50"/>
|
||||
|
||||
<TextBlock Text="Agent File" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<ComboBox ItemsSource="{Binding AvailableAgents}"
|
||||
SelectedItem="{Binding SelectedAgent}"
|
||||
MinWidth="150">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="svc:AgentInfo">
|
||||
<TextBlock Text="{Binding Name}"/>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right" Margin="0,10,0,0">
|
||||
<Button Content="Save" Command="{Binding SaveCommand}" IsDefault="True" MinWidth="80"
|
||||
Background="{StaticResource AccentBrush}" Foreground="{StaticResource TextPrimaryBrush}"/>
|
||||
<Button Content="Cancel" Command="{Binding CancelCommand}" IsCancel="True" MinWidth="80"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Window>
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using ClaudeDo.Ui.ViewModels;
|
||||
|
||||
namespace ClaudeDo.Ui.Views;
|
||||
|
||||
public partial class ListEditorView : Window
|
||||
{
|
||||
public ListEditorView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void OnBrowseFolder(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var vm = DataContext as ListEditorViewModel;
|
||||
var startPath = !string.IsNullOrWhiteSpace(vm?.WorkingDir) && Directory.Exists(vm.WorkingDir)
|
||||
? vm.WorkingDir
|
||||
: Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
|
||||
var startLocation = await StorageProvider.TryGetFolderFromPathAsync(new Uri(startPath));
|
||||
|
||||
var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
|
||||
{
|
||||
Title = "Select Working Directory",
|
||||
SuggestedStartLocation = startLocation,
|
||||
AllowMultiple = false,
|
||||
});
|
||||
|
||||
if (result.Count > 0)
|
||||
{
|
||||
var path = result[0].TryGetLocalPath();
|
||||
if (path is not null && vm is not null)
|
||||
vm.WorkingDir = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:ClaudeDo.Ui.ViewModels"
|
||||
xmlns:conv="using:ClaudeDo.Ui.Converters"
|
||||
x:Class="ClaudeDo.Ui.Views.StatusBarView"
|
||||
x:DataType="vm:StatusBarViewModel">
|
||||
<Border Background="#222" Padding="6,3">
|
||||
<Grid ColumnDefinitions="Auto,Auto,*,Auto">
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="6">
|
||||
<Ellipse Width="10" Height="10" VerticalAlignment="Center"
|
||||
Fill="{Binding ConnectionStatus, Converter={x:Static conv:ConnectionColorConverter.Instance}}"/>
|
||||
<TextBlock Text="{Binding ConnectionStatus}" Foreground="White" VerticalAlignment="Center" FontSize="12"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Column="1" Text="{Binding ActiveTasksSummary}" Foreground="LightGray"
|
||||
VerticalAlignment="Center" Margin="20,0,0,0" FontSize="12"/>
|
||||
|
||||
<TextBlock Grid.Column="3" Text="{Binding StatusMessage}" Foreground="Yellow"
|
||||
VerticalAlignment="Center" FontSize="12" Margin="0,0,8,0"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
@@ -1,11 +0,0 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace ClaudeDo.Ui.Views;
|
||||
|
||||
public partial class StatusBarView : UserControl
|
||||
{
|
||||
public StatusBarView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:ClaudeDo.Ui.ViewModels"
|
||||
xmlns:conv="using:ClaudeDo.Ui.Converters"
|
||||
xmlns:m="using:ClaudeDo.Data.Models"
|
||||
x:Class="ClaudeDo.Ui.Views.TaskDetailView"
|
||||
x:DataType="vm:TaskDetailViewModel">
|
||||
<ScrollViewer>
|
||||
<StackPanel Margin="12" Spacing="8"
|
||||
IsVisible="{Binding Title, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
||||
|
||||
<!-- Title (large, editable) -->
|
||||
<TextBox x:Name="TitleBox"
|
||||
Text="{Binding Title}"
|
||||
FontWeight="Bold" FontSize="16"
|
||||
Foreground="{StaticResource TextPrimaryBrush}"
|
||||
BorderThickness="0" Background="Transparent"
|
||||
Padding="0,4"
|
||||
LostFocus="OnFieldLostFocus"/>
|
||||
|
||||
<!-- Status + Commit Type row -->
|
||||
<Grid ColumnDefinitions="*,16,*" Margin="0,4,0,0">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Status" FontSize="12" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<ComboBox ItemsSource="{Binding StatusChoices}"
|
||||
SelectedItem="{Binding StatusChoice}"
|
||||
MinWidth="100"
|
||||
LostFocus="OnFieldLostFocus"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Commit Type" FontSize="12" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<ComboBox ItemsSource="{Binding CommitTypes}"
|
||||
SelectedItem="{Binding CommitType}"
|
||||
MinWidth="100"
|
||||
LostFocus="OnFieldLostFocus"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Tags -->
|
||||
<StackPanel Spacing="4" Margin="0,8,0,0">
|
||||
<TextBlock Text="Tags" FontSize="12" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<WrapPanel Orientation="Horizontal">
|
||||
<ItemsControl ItemsSource="{Binding Tags}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="m:TagEntity">
|
||||
<Border CornerRadius="10" Padding="8,3" Margin="0,0,4,4"
|
||||
Background="{StaticResource AccentSubtleBrush}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<TextBlock Text="{Binding Name}" FontSize="12"
|
||||
Foreground="{StaticResource AccentLightBrush}"
|
||||
VerticalAlignment="Center"/>
|
||||
<Button Content="x" FontSize="10" Padding="2,0"
|
||||
Background="Transparent" BorderThickness="0"
|
||||
Foreground="{StaticResource TextMutedBrush}"
|
||||
Cursor="Hand"
|
||||
Command="{Binding $parent[UserControl].((vm:TaskDetailViewModel)DataContext).RemoveTagCommand}"
|
||||
CommandParameter="{Binding}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBox Text="{Binding NewTagInput}"
|
||||
PlaceholderText="Add tag..."
|
||||
Width="100" FontSize="12"
|
||||
BorderThickness="0" Background="Transparent"
|
||||
Padding="4,3"
|
||||
KeyDown="OnTagInputKeyDown"/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Description (editable) -->
|
||||
<TextBlock Text="Description" FontSize="12" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,8,0,2"/>
|
||||
<TextBox Text="{Binding Description}"
|
||||
AcceptsReturn="True" TextWrapping="Wrap" MinHeight="60"
|
||||
Foreground="{StaticResource TextPrimaryBrush}"
|
||||
PlaceholderText="Add a description..."
|
||||
LostFocus="OnFieldLostFocus"/>
|
||||
|
||||
<!-- Sub-Tasks -->
|
||||
<Border Height="1" Background="{StaticResource BorderSubtleBrush}" Margin="0,8,0,4"/>
|
||||
<TextBlock Text="Sub-Tasks" FontWeight="Bold" FontSize="13"
|
||||
Foreground="{StaticResource TextPrimaryBrush}"/>
|
||||
<ItemsControl ItemsSource="{Binding Subtasks}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SubtaskItemViewModel">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6" Margin="0,2,0,2">
|
||||
<CheckBox IsChecked="{Binding Completed}" VerticalAlignment="Center"/>
|
||||
<TextBox Text="{Binding Title}" PlaceholderText="Subtask title..." Width="220"
|
||||
VerticalAlignment="Center"
|
||||
LostFocus="OnSubtaskTitleLostFocus"/>
|
||||
<Button Content="✕" Padding="6,2"
|
||||
Background="Transparent" BorderThickness="0"
|
||||
Foreground="{StaticResource TextMutedBrush}"
|
||||
Command="{Binding $parent[UserControl].((vm:TaskDetailViewModel)DataContext).RemoveSubtaskCommand}"
|
||||
CommandParameter="{Binding}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<Button Content="+ Add Sub-Task" Command="{Binding AddSubtaskCommand}"
|
||||
Background="Transparent" BorderThickness="0"
|
||||
Foreground="{StaticResource AccentLightBrush}" HorizontalAlignment="Left"/>
|
||||
|
||||
<!-- Agent Config (overrides) -->
|
||||
<Border Height="1" Background="{StaticResource BorderSubtleBrush}" Margin="0,8,0,4"/>
|
||||
<TextBlock Text="Agent Config (overrides)" FontWeight="Bold" FontSize="13"
|
||||
Foreground="{StaticResource TextPrimaryBrush}"/>
|
||||
|
||||
<Grid ColumnDefinitions="*,12,*" Margin="0,4,0,0">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Model" FontSize="12" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<ComboBox ItemsSource="{Binding ModelChoices}"
|
||||
SelectedItem="{Binding ModelChoice}"
|
||||
MinWidth="100"
|
||||
LostFocus="OnFieldLostFocus"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Agent File" FontSize="12" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<ComboBox ItemsSource="{Binding AvailableAgents}"
|
||||
SelectedItem="{Binding SelectedAgent}"
|
||||
MinWidth="100"
|
||||
LostFocus="OnFieldLostFocus">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="m:AgentInfo">
|
||||
<TextBlock Text="{Binding Name}"/>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<Button Content="…" Click="OnBrowseAgent" ToolTip.Tip="Browse for agent .md file"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Text="System Prompt" FontSize="12" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,4,0,2"/>
|
||||
<TextBox Text="{Binding SystemPromptOverride}"
|
||||
PlaceholderText="(inherits from list)"
|
||||
AcceptsReturn="True" TextWrapping="Wrap" MinHeight="50"
|
||||
LostFocus="OnFieldLostFocus"/>
|
||||
|
||||
<!-- === READ-ONLY ZONE === -->
|
||||
|
||||
<TextBlock Text="Result" FontWeight="SemiBold" FontSize="12"
|
||||
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,12,0,2"/>
|
||||
<TextBox Text="{Binding Result, Mode=OneWay}" IsReadOnly="True"
|
||||
AcceptsReturn="True" TextWrapping="Wrap" MinHeight="60"
|
||||
IsVisible="{Binding Result, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
<TextBlock Text="(no result yet)" Foreground="{StaticResource TextMutedBrush}" FontStyle="Italic"
|
||||
IsVisible="{Binding Result, Converter={x:Static StringConverters.IsNullOrEmpty}}"/>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="4"
|
||||
IsVisible="{Binding LogPath, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
||||
<TextBlock Text="Log:" FontWeight="SemiBold" FontSize="12"
|
||||
Foreground="{StaticResource TextSecondaryBrush}" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding LogPath}" FontSize="11"
|
||||
Foreground="{StaticResource TextDimBrush}" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Text="Live Output" FontWeight="SemiBold" FontSize="12"
|
||||
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,8,0,2"/>
|
||||
<TextBox x:Name="LiveOutputBox"
|
||||
Text="{Binding LiveText, Mode=OneWay}"
|
||||
IsReadOnly="True"
|
||||
AcceptsReturn="True"
|
||||
TextWrapping="NoWrap"
|
||||
FontFamily="Consolas,Courier New,monospace"
|
||||
FontSize="11"
|
||||
MaxHeight="300"
|
||||
Foreground="{StaticResource TextPrimaryBrush}"
|
||||
BorderBrush="{StaticResource BorderSubtleBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="6"
|
||||
Padding="6"/>
|
||||
|
||||
<Border IsVisible="{Binding HasWorktree}" BorderBrush="{StaticResource AccentBrush}"
|
||||
BorderThickness="1" CornerRadius="8" Padding="10" Margin="0,8,0,0">
|
||||
<StackPanel Spacing="6">
|
||||
<TextBlock Text="Worktree" FontWeight="Bold" FontSize="14"
|
||||
Foreground="{StaticResource TextPrimaryBrush}"/>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<TextBlock Text="Branch:" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<TextBlock Text="{Binding BranchName}" FontFamily="Consolas,Courier New,monospace"
|
||||
Foreground="{StaticResource TextPrimaryBrush}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<TextBlock Text="State:" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<TextBlock Text="{Binding WorktreeState}"
|
||||
Foreground="{StaticResource TextPrimaryBrush}"/>
|
||||
</StackPanel>
|
||||
<TextBlock Text="Diff Stat:" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"
|
||||
IsVisible="{Binding DiffStat, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
<TextBox Text="{Binding DiffStat, Mode=OneWay}" IsReadOnly="True"
|
||||
AcceptsReturn="True" FontFamily="Consolas,Courier New,monospace" FontSize="11"
|
||||
IsVisible="{Binding DiffStat, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
<WrapPanel Orientation="Horizontal" Margin="0,4,0,0">
|
||||
<Button Content="Open Worktree" Command="{Binding OpenWorktreeCommand}" Margin="0,0,4,4"/>
|
||||
<Button Content="Show Diff" Command="{Binding ShowDiffCommand}" Margin="0,0,4,4"/>
|
||||
<Button Content="Merge into main" Command="{Binding MergeIntoMainCommand}"
|
||||
IsEnabled="{Binding CanWorktreeAction}" Margin="0,0,4,4"/>
|
||||
<Button Content="Keep as branch" Command="{Binding KeepAsBranchCommand}"
|
||||
IsEnabled="{Binding CanWorktreeAction}" Margin="0,0,4,4"/>
|
||||
<Button Content="Discard" Command="{Binding DiscardCommand}"
|
||||
IsEnabled="{Binding CanWorktreeAction}" Margin="0,0,4,4"/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
@@ -1,85 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using ClaudeDo.Ui.ViewModels;
|
||||
|
||||
namespace ClaudeDo.Ui.Views;
|
||||
|
||||
public partial class TaskDetailView : UserControl
|
||||
{
|
||||
public TaskDetailView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void OnFieldLostFocus(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is TaskDetailViewModel vm)
|
||||
await vm.SaveAsync();
|
||||
}
|
||||
|
||||
private void OnSubtaskTitleLostFocus(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
// Title change is handled by SubtaskItemViewModel.PropertyChanged → OnSubtaskPropertyChanged in the VM
|
||||
}
|
||||
|
||||
private async void OnBrowseAgent(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel is null) return;
|
||||
var files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
{
|
||||
Title = "Select Agent File",
|
||||
AllowMultiple = false,
|
||||
FileTypeFilter = new[] { new FilePickerFileType("Agent Files") { Patterns = ["*.md"] } },
|
||||
});
|
||||
if (files.Count == 0) return;
|
||||
var path = files[0].TryGetLocalPath();
|
||||
if (path is null) return;
|
||||
if (DataContext is TaskDetailViewModel vm)
|
||||
{
|
||||
vm.SetAgentFromPath(path);
|
||||
await vm.SaveAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTagInputKeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter && DataContext is TaskDetailViewModel vm)
|
||||
{
|
||||
vm.AddTagCommand.Execute(null);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void FocusTitle()
|
||||
{
|
||||
this.FindControl<TextBox>("TitleBox")?.Focus();
|
||||
}
|
||||
|
||||
private TaskDetailViewModel? _previousVm;
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (_previousVm is not null)
|
||||
_previousVm.PropertyChanged -= OnViewModelPropertyChanged;
|
||||
_previousVm = DataContext as TaskDetailViewModel;
|
||||
if (_previousVm is not null)
|
||||
_previousVm.PropertyChanged += OnViewModelPropertyChanged;
|
||||
}
|
||||
|
||||
private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(TaskDetailViewModel.LiveText))
|
||||
{
|
||||
var box = this.FindControl<TextBox>("LiveOutputBox");
|
||||
if (box is not null)
|
||||
{
|
||||
box.CaretIndex = box.Text?.Length ?? 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:ClaudeDo.Ui.ViewModels"
|
||||
xmlns:models="using:ClaudeDo.Data.Models"
|
||||
x:Class="ClaudeDo.Ui.Views.TaskEditorView"
|
||||
x:DataType="vm:TaskEditorViewModel"
|
||||
Title="{Binding WindowTitle}"
|
||||
Width="500" Height="600"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False"
|
||||
Background="{StaticResource WindowBgBrush}">
|
||||
<StackPanel Margin="16" Spacing="10">
|
||||
<TextBlock Text="Title" FontWeight="SemiBold" Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<TextBox Text="{Binding Title}" PlaceholderText="Task title..."/>
|
||||
|
||||
<TextBlock Text="Description" FontWeight="SemiBold" Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<TextBox Text="{Binding Description}" PlaceholderText="(optional)" AcceptsReturn="True"
|
||||
TextWrapping="Wrap" MinHeight="80"/>
|
||||
|
||||
<Grid ColumnDefinitions="*,16,*">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Status" FontWeight="SemiBold" Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<ComboBox ItemsSource="{Binding StatusChoices}"
|
||||
SelectedItem="{Binding StatusChoice}"
|
||||
MinWidth="120"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Commit Type" FontWeight="SemiBold" Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<ComboBox ItemsSource="{Binding CommitTypes}"
|
||||
SelectedItem="{Binding CommitType}"
|
||||
MinWidth="120"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Text="Tags (comma-separated)" FontWeight="SemiBold" Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<TextBox Text="{Binding TagsInput}" PlaceholderText="agent, manual, code, ..."/>
|
||||
|
||||
<!-- Sub-Tasks -->
|
||||
<Border Height="1" Background="{StaticResource BorderSubtleBrush}" Margin="0,6,0,2"/>
|
||||
<TextBlock Text="Sub-Tasks" FontWeight="Bold" FontSize="13"
|
||||
Foreground="{StaticResource TextPrimaryBrush}"/>
|
||||
<ItemsControl ItemsSource="{Binding Subtasks}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SubtaskItemViewModel">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6" Margin="0,2,0,2">
|
||||
<CheckBox IsChecked="{Binding Completed}" VerticalAlignment="Center"/>
|
||||
<TextBox Text="{Binding Title}" PlaceholderText="Subtask title..." Width="320"
|
||||
VerticalAlignment="Center"/>
|
||||
<Button Content="✕" Padding="6,2"
|
||||
Background="Transparent" BorderThickness="0"
|
||||
Foreground="{StaticResource TextMutedBrush}"
|
||||
Command="{Binding $parent[Window].((vm:TaskEditorViewModel)DataContext).RemoveSubtaskCommand}"
|
||||
CommandParameter="{Binding}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<Button Content="+ Add Sub-Task" Command="{Binding AddSubtaskCommand}"
|
||||
Background="Transparent" BorderThickness="0"
|
||||
Foreground="{StaticResource AccentLightBrush}" HorizontalAlignment="Left"/>
|
||||
|
||||
<!-- Divider -->
|
||||
<Border Height="1" Background="{StaticResource BorderSubtleBrush}" Margin="0,6,0,2"/>
|
||||
|
||||
<TextBlock Text="Agent Config (overrides)" FontWeight="Bold" FontSize="13"
|
||||
Foreground="{StaticResource TextPrimaryBrush}"/>
|
||||
|
||||
<TextBlock Text="Model" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<ComboBox ItemsSource="{Binding ModelChoices}"
|
||||
SelectedItem="{Binding ModelChoice}"
|
||||
MinWidth="150"/>
|
||||
|
||||
<TextBlock Text="System Prompt" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<TextBox Text="{Binding SystemPromptOverride}"
|
||||
PlaceholderText="(inherits from list)"
|
||||
AcceptsReturn="True" TextWrapping="Wrap" MinHeight="50"/>
|
||||
|
||||
<TextBlock Text="Agent File" FontWeight="SemiBold"
|
||||
Foreground="{StaticResource TextSecondaryBrush}"/>
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<ComboBox ItemsSource="{Binding AvailableAgents}"
|
||||
SelectedItem="{Binding SelectedAgent}"
|
||||
MinWidth="150">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:AgentInfo">
|
||||
<TextBlock Text="{Binding Name}"/>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<Button Content="…" Click="OnBrowseAgent" ToolTip.Tip="Browse for agent .md file"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right" Margin="0,10,0,0">
|
||||
<Button Content="Save" Command="{Binding SaveCommand}" IsDefault="True" MinWidth="80"
|
||||
Background="{StaticResource AccentBrush}" Foreground="{StaticResource TextPrimaryBrush}"/>
|
||||
<Button Content="Cancel" Command="{Binding CancelCommand}" IsCancel="True" MinWidth="80"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Window>
|
||||
@@ -1,29 +0,0 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using ClaudeDo.Ui.ViewModels;
|
||||
|
||||
namespace ClaudeDo.Ui.Views;
|
||||
|
||||
public partial class TaskEditorView : Window
|
||||
{
|
||||
public TaskEditorView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void OnBrowseAgent(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var files = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
{
|
||||
Title = "Select Agent File",
|
||||
AllowMultiple = false,
|
||||
FileTypeFilter = new[] { new FilePickerFileType("Agent Files") { Patterns = ["*.md"] } },
|
||||
});
|
||||
if (files.Count == 0) return;
|
||||
var path = files[0].TryGetLocalPath();
|
||||
if (path is null) return;
|
||||
if (DataContext is TaskEditorViewModel vm)
|
||||
vm.SetAgentFromPath(path);
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:ClaudeDo.Ui.ViewModels"
|
||||
xmlns:conv="using:ClaudeDo.Ui.Converters"
|
||||
x:Class="ClaudeDo.Ui.Views.TaskListView"
|
||||
x:DataType="vm:TaskListViewModel"
|
||||
x:Name="Root">
|
||||
<DockPanel>
|
||||
<!-- Inline add field at bottom -->
|
||||
<Border DockPanel.Dock="Bottom" Padding="8,8"
|
||||
BorderThickness="0,1,0,0" BorderBrush="{StaticResource BorderSubtleBrush}">
|
||||
<TextBox x:Name="InlineAddBox"
|
||||
Text="{Binding InlineAddTitle, Mode=TwoWay}"
|
||||
PlaceholderText="+ Add a task..."
|
||||
BorderThickness="1"
|
||||
BorderBrush="{StaticResource BorderSubtleBrush}"
|
||||
CornerRadius="8"
|
||||
Padding="10,8"
|
||||
FontSize="13"
|
||||
KeyDown="OnInlineAddKeyDown"
|
||||
GotFocus="OnInlineAddGotFocus"
|
||||
LostFocus="OnInlineAddLostFocus"/>
|
||||
</Border>
|
||||
|
||||
<!-- Task list -->
|
||||
<ListBox x:Name="TaskListBox"
|
||||
ItemsSource="{Binding Tasks}"
|
||||
SelectedItem="{Binding SelectedTask}"
|
||||
Background="Transparent"
|
||||
Margin="4,0"
|
||||
KeyDown="OnTaskListKeyDown">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:TaskItemViewModel">
|
||||
<Grid RowDefinitions="Auto,Auto"
|
||||
Background="Transparent"
|
||||
Opacity="{Binding RowOpacity}">
|
||||
<!-- Row 0: Task row -->
|
||||
<Grid Grid.Row="0" ColumnDefinitions="20,Auto,*" Margin="4,4"
|
||||
DoubleTapped="OnTaskItemDoubleTapped"
|
||||
PointerPressed="OnTaskItemPointerPressed">
|
||||
<Grid.ContextFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuItem Header="Edit"
|
||||
Command="{Binding #Root.((vm:TaskListViewModel)DataContext).EditTaskCommand}"/>
|
||||
<MenuItem Header="Delete"
|
||||
Command="{Binding #Root.((vm:TaskListViewModel)DataContext).DeleteTaskCommand}"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="Run Now"
|
||||
Command="{Binding RunNowCommand}"/>
|
||||
</MenuFlyout>
|
||||
</Grid.ContextFlyout>
|
||||
|
||||
<!-- Expand/collapse chevron -->
|
||||
<Button Grid.Column="0"
|
||||
Command="{Binding ToggleExpandedCommand}"
|
||||
IsVisible="{Binding HasSubtasks}"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Padding="0"
|
||||
Width="16" Height="16"
|
||||
VerticalAlignment="Center"
|
||||
Cursor="Hand">
|
||||
<Panel>
|
||||
<Canvas Width="10" Height="10"
|
||||
IsVisible="{Binding !IsExpanded}">
|
||||
<Path Stroke="{StaticResource TextDimBrush}" StrokeThickness="1.5"
|
||||
Data="M 2,0 L 8,5 L 2,10"/>
|
||||
</Canvas>
|
||||
<Canvas Width="10" Height="10"
|
||||
IsVisible="{Binding IsExpanded}">
|
||||
<Path Stroke="{StaticResource TextDimBrush}" StrokeThickness="1.5"
|
||||
Data="M 0,2 L 5,8 L 10,2"/>
|
||||
</Canvas>
|
||||
</Panel>
|
||||
</Button>
|
||||
|
||||
<!-- Circular checkbox -->
|
||||
<Border Grid.Column="1" Width="22" Height="22"
|
||||
CornerRadius="11"
|
||||
BorderThickness="2"
|
||||
BorderBrush="{Binding StatusText, Converter={x:Static conv:CheckboxBorderConverter.Instance}}"
|
||||
Background="Transparent"
|
||||
VerticalAlignment="Center" Margin="0,0,10,0"
|
||||
Cursor="Hand"
|
||||
PointerPressed="OnCheckboxPressed">
|
||||
<Panel>
|
||||
<Canvas Width="12" Height="12"
|
||||
IsVisible="{Binding IsDone}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Path Stroke="{StaticResource StatusGreenBrush}" StrokeThickness="2"
|
||||
Data="M 1,6 L 4.5,9.5 L 11,3"/>
|
||||
</Canvas>
|
||||
<Ellipse Width="8" Height="8"
|
||||
Fill="{StaticResource StatusOrangeBrush}"
|
||||
IsVisible="{Binding IsRunning}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
<Ellipse Width="8" Height="8" Fill="#FFD700"
|
||||
IsVisible="{Binding IsStarting}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Panel>
|
||||
</Border>
|
||||
|
||||
<!-- Task content -->
|
||||
<StackPanel Grid.Column="2" VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding Title}" FontWeight="Medium"
|
||||
Foreground="{Binding TitleForeground}"
|
||||
TextDecorations="{Binding TitleDecorations}"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
<TextBlock FontSize="11"
|
||||
Foreground="{StaticResource TextDimBrush}"
|
||||
IsVisible="{Binding TagsText, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0} · {1}">
|
||||
<Binding Path="TagsText"/>
|
||||
<Binding Path="StatusText"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
<TextBlock Text="{Binding StatusText}" FontSize="11"
|
||||
Foreground="{StaticResource TextDimBrush}"
|
||||
IsVisible="{Binding TagsText, Converter={x:Static StringConverters.IsNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Row 1: Subtask list (visible when expanded) -->
|
||||
<ItemsControl Grid.Row="1"
|
||||
ItemsSource="{Binding Subtasks}"
|
||||
IsVisible="{Binding IsExpanded}"
|
||||
Margin="40,0,0,4">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SubtaskItemViewModel">
|
||||
<Grid ColumnDefinitions="Auto,*" Margin="0,2"
|
||||
PointerPressed="OnSubtaskPointerPressed">
|
||||
<Grid.ContextFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuItem Header="Edit Task"
|
||||
Command="{Binding #Root.((vm:TaskListViewModel)DataContext).EditTaskCommand}"/>
|
||||
</MenuFlyout>
|
||||
</Grid.ContextFlyout>
|
||||
<CheckBox Grid.Column="0"
|
||||
IsChecked="{Binding Completed, Mode=OneWay}"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,6,0"
|
||||
MinWidth="0"
|
||||
Click="OnSubtaskCheckboxClick"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding Title}"
|
||||
FontSize="12"
|
||||
Foreground="{StaticResource TextDimBrush}"
|
||||
VerticalAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
@@ -1,128 +0,0 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.VisualTree;
|
||||
using ClaudeDo.Ui.ViewModels;
|
||||
|
||||
namespace ClaudeDo.Ui.Views;
|
||||
|
||||
public partial class TaskListView : UserControl
|
||||
{
|
||||
public TaskListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnInlineAddKeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (DataContext is not TaskListViewModel vm) return;
|
||||
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
vm.InlineAddCommand.Execute(null);
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.Escape)
|
||||
{
|
||||
vm.InlineAddTitle = "";
|
||||
this.FindControl<ListBox>("TaskListBox")?.Focus();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInlineAddGotFocus(object? sender, FocusChangedEventArgs e)
|
||||
{
|
||||
if (sender is TextBox tb)
|
||||
tb.BorderBrush = Avalonia.Application.Current?.FindResource("AccentBrush") as Avalonia.Media.IBrush;
|
||||
}
|
||||
|
||||
private void OnInlineAddLostFocus(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is TextBox tb)
|
||||
tb.BorderBrush = Avalonia.Application.Current?.FindResource("BorderSubtleBrush") as Avalonia.Media.IBrush;
|
||||
}
|
||||
|
||||
private void OnTaskListKeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (DataContext is not TaskListViewModel vm || vm.SelectedTask is null) return;
|
||||
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Delete:
|
||||
vm.DeleteTaskCommand.Execute(null);
|
||||
e.Handled = true;
|
||||
break;
|
||||
case Key.Space:
|
||||
if (vm.SelectedTask.CanToggleDone)
|
||||
{
|
||||
vm.SelectedTask.ToggleDoneCommand.Execute(null);
|
||||
e.Handled = true;
|
||||
}
|
||||
break;
|
||||
case Key.Enter:
|
||||
case Key.F2:
|
||||
var detailView = this.GetVisualAncestors().OfType<Window>().FirstOrDefault()
|
||||
?.GetVisualDescendants().OfType<TaskDetailView>().FirstOrDefault();
|
||||
detailView?.FocusTitle();
|
||||
e.Handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCheckboxPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender is not Border { DataContext: TaskItemViewModel task }) return;
|
||||
if (task.CanToggleDone)
|
||||
{
|
||||
task.ToggleDoneCommand.Execute(null);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTaskItemDoubleTapped(object? sender, TappedEventArgs e)
|
||||
{
|
||||
if (DataContext is TaskListViewModel vm)
|
||||
vm.EditTaskCommand.Execute(null);
|
||||
}
|
||||
|
||||
private void OnTaskItemPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
var props = e.GetCurrentPoint(this).Properties;
|
||||
if (!props.IsRightButtonPressed) return;
|
||||
|
||||
if (sender is Grid { DataContext: TaskItemViewModel item }
|
||||
&& DataContext is TaskListViewModel vm)
|
||||
{
|
||||
vm.SelectedTask = item;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSubtaskPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (e.GetCurrentPoint(null).Properties.IsRightButtonPressed
|
||||
&& sender is Control { DataContext: SubtaskItemViewModel subtask }
|
||||
&& DataContext is TaskListViewModel vm)
|
||||
{
|
||||
var parent = vm.Tasks.FirstOrDefault(t => t.Subtasks.Contains(subtask));
|
||||
if (parent is not null)
|
||||
vm.SelectedTask = parent;
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnSubtaskCheckboxClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is CheckBox { DataContext: SubtaskItemViewModel subtask }
|
||||
&& DataContext is TaskListViewModel vm)
|
||||
{
|
||||
var parent = vm.Tasks.FirstOrDefault(t => t.Subtasks.Contains(subtask));
|
||||
if (parent is not null)
|
||||
await parent.ToggleSubtaskDoneCommand.ExecuteAsync(subtask.Id);
|
||||
}
|
||||
}
|
||||
|
||||
public void FocusInlineAdd()
|
||||
{
|
||||
this.FindControl<TextBox>("InlineAddBox")?.Focus();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user