feat(ui): agent config inline in detail panel, file picker, subtask UI

TaskDetailView now edits Model / SystemPrompt / Agent inline (LostFocus
save), matching the modal editor. Both TaskEditorView and TaskDetailView
gain a Browse button that opens a .md file picker — external agent
paths are preserved on reload via a synthetic AgentInfo entry. Both
views also render the per-task subtask checklist (CheckBox + TextBox +
remove), with diff-on-save in the editor and inline-save in the detail
panel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mika Kuns
2026-04-15 11:20:17 +02:00
parent 8c051d8f62
commit 9a407bde83
8 changed files with 410 additions and 16 deletions

View File

@@ -2,6 +2,7 @@ using System.ComponentModel;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using ClaudeDo.Ui.ViewModels;
namespace ClaudeDo.Ui.Views;
@@ -19,6 +20,31 @@ public partial class TaskDetailView : UserControl
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)