feat(ui): add Refine button, icon, and command to task card

This commit is contained in:
mika kuns
2026-06-04 23:21:30 +02:00
parent 4098f7f341
commit 2a6781f80f
6 changed files with 50 additions and 4 deletions

View File

@@ -111,7 +111,8 @@
"reviewTitle": "Review", "reviewTitle": "Review",
"feedbackLabel": "FEEDBACK FÜR DEN AGENTEN", "feedbackLabel": "FEEDBACK FÜR DEN AGENTEN",
"feedbackPlaceholder": "Was soll der Agent korrigieren?", "feedbackPlaceholder": "Was soll der Agent korrigieren?",
"rerun": "Erneut ausführen" "rerun": "Erneut ausführen",
"refineTip": "Aufgabe mit Claude verfeinern"
}, },
"lists": { "lists": {
"heading": "Listen", "heading": "Listen",

View File

@@ -111,7 +111,8 @@
"reviewTitle": "Review", "reviewTitle": "Review",
"feedbackLabel": "FEEDBACK FOR THE AGENT", "feedbackLabel": "FEEDBACK FOR THE AGENT",
"feedbackPlaceholder": "What should the agent fix?", "feedbackPlaceholder": "What should the agent fix?",
"rerun": "Re-run" "rerun": "Re-run",
"refineTip": "Refine this task with Claude"
}, },
"lists": { "lists": {
"heading": "Lists", "heading": "Lists",

View File

@@ -76,6 +76,9 @@
<!-- Icon.PlanDay (stroke-rendered via Path.plan-icon — sun over horizon) --> <!-- Icon.PlanDay (stroke-rendered via Path.plan-icon — sun over horizon) -->
<StreamGeometry x:Key="Icon.PlanDay">M3,20 L21,20 M8.4,11 a3.6,3.6 0 1,0 7.2,0 a3.6,3.6 0 1,0 -7.2,0 M12,4.5 L12,3 M6,11 L4.5,11 M18,11 L19.5,11 M7.5,6.5 L6.4,5.4 M16.5,6.5 L17.6,5.4</StreamGeometry> <StreamGeometry x:Key="Icon.PlanDay">M3,20 L21,20 M8.4,11 a3.6,3.6 0 1,0 7.2,0 a3.6,3.6 0 1,0 -7.2,0 M12,4.5 L12,3 M6,11 L4.5,11 M18,11 L19.5,11 M7.5,6.5 L6.4,5.4 M16.5,6.5 L17.6,5.4</StreamGeometry>
<!-- Icon.Refine (stroke-rendered via Path.plan-icon — list lines + sparkle + edit tail) -->
<StreamGeometry x:Key="Icon.Refine">M3,5 L11,5 M3,9 L9,9 M3,13 L7,13 M19,1.8 L19.7,3.9 L21.7,4.6 L19.7,5.3 L19,7.4 L18.3,5.3 L16.3,4.6 L18.3,3.9 Z M18,10.5 L12.2,16.3 M16.6,9.1 L19.4,11.9 M12.2,16.3 L11,18.5 L13.2,17.5 Z</StreamGeometry>
<!-- Icon.X --> <!-- Icon.X -->
<StreamGeometry x:Key="Icon.X">M6 6l12 12M18 6L6 18</StreamGeometry> <StreamGeometry x:Key="Icon.X">M6 6l12 12M18 6L6 18</StreamGeometry>

View File

@@ -32,6 +32,9 @@ public sealed partial class TaskRowViewModel : ViewModelBase
[ObservableProperty] private bool _showListChip = true; [ObservableProperty] private bool _showListChip = true;
[ObservableProperty] private bool _parentFinalized; [ObservableProperty] private bool _parentFinalized;
[ObservableProperty] private int _roadblockCount; [ObservableProperty] private int _roadblockCount;
[ObservableProperty] private bool _isRefining;
public bool CanRefine => Status == TaskStatus.Idle && PlanningPhase == PlanningPhase.None && !IsRefining;
public DateTime CreatedAt { get; init; } public DateTime CreatedAt { get; init; }
public string CreatedAtFormatted => CreatedAt == default ? "—" : Loc.T("vm.taskRow.createdPrefix", CreatedAt.ToString("MMM d")); public string CreatedAtFormatted => CreatedAt == default ? "—" : Loc.T("vm.taskRow.createdPrefix", CreatedAt.ToString("MMM d"));
@@ -125,6 +128,7 @@ public sealed partial class TaskRowViewModel : ViewModelBase
OnPropertyChanged(nameof(CanOpenPlanningSession)); OnPropertyChanged(nameof(CanOpenPlanningSession));
OnPropertyChanged(nameof(CanRemoveFromQueue)); OnPropertyChanged(nameof(CanRemoveFromQueue));
OnPropertyChanged(nameof(CanSendToQueue)); OnPropertyChanged(nameof(CanSendToQueue));
OnPropertyChanged(nameof(CanRefine));
} }
partial void OnParentTaskIdChanged(string? value) partial void OnParentTaskIdChanged(string? value)
@@ -155,8 +159,11 @@ public sealed partial class TaskRowViewModel : ViewModelBase
OnPropertyChanged(nameof(CanOpenPlanningSession)); OnPropertyChanged(nameof(CanOpenPlanningSession));
OnPropertyChanged(nameof(CanResumeOrDiscardPlanning)); OnPropertyChanged(nameof(CanResumeOrDiscardPlanning));
OnPropertyChanged(nameof(CanQueuePlan)); OnPropertyChanged(nameof(CanQueuePlan));
OnPropertyChanged(nameof(CanRefine));
} }
partial void OnIsRefiningChanged(bool value) => OnPropertyChanged(nameof(CanRefine));
partial void OnHasQueuedSubtasksChanged(bool value) partial void OnHasQueuedSubtasksChanged(bool value)
{ {
OnPropertyChanged(nameof(CanRemoveFromQueue)); OnPropertyChanged(nameof(CanRemoveFromQueue));

View File

@@ -82,6 +82,8 @@ public sealed partial class TasksIslandViewModel : ViewModelBase
_worker.WorktreeUpdatedEvent += OnWorkerTaskUpdated; _worker.WorktreeUpdatedEvent += OnWorkerTaskUpdated;
_worker.ListUpdatedEvent += OnWorkerListUpdated; _worker.ListUpdatedEvent += OnWorkerListUpdated;
_worker.ConnectionRestoredEvent += () => LoadForList(_currentList); _worker.ConnectionRestoredEvent += () => LoadForList(_currentList);
_worker.RefineStartedEvent += OnRefineStarted;
_worker.RefineFinishedEvent += OnRefineFinished;
} }
Loc.LanguageChanged += (_, _) => RefreshLocalizedText(); Loc.LanguageChanged += (_, _) => RefreshLocalizedText();
} }
@@ -830,6 +832,27 @@ public sealed partial class TasksIslandViewModel : ViewModelBase
Regroup(); Regroup();
} }
[RelayCommand]
private async Task RefineTask(TaskRowViewModel row)
{
if (row is null || !row.CanRefine) return;
row.IsRefining = true;
try { await _worker!.RefineTaskAsync(row.Id); }
catch { row.IsRefining = false; }
}
private void OnRefineStarted(string taskId)
{
var row = Items.FirstOrDefault(r => r.Id == taskId);
if (row is not null) row.IsRefining = true;
}
private void OnRefineFinished(string taskId, bool ok, string? error)
{
var row = Items.FirstOrDefault(r => r.Id == taskId);
if (row is not null) row.IsRefining = false;
}
partial void OnSelectedTaskChanged(TaskRowViewModel? value) partial void OnSelectedTaskChanged(TaskRowViewModel? value)
{ {
foreach (var i in Items) i.IsSelected = ReferenceEquals(i, value); foreach (var i in Items) i.IsSelected = ReferenceEquals(i, value);

View File

@@ -69,7 +69,7 @@
Click="OnClearScheduleClick"/> Click="OnClearScheduleClick"/>
</ContextMenu> </ContextMenu>
</Border.ContextMenu> </Border.ContextMenu>
<Grid ColumnDefinitions="0,18,32,*,Auto,32" Margin="6,8,10,8"> <Grid ColumnDefinitions="0,18,32,*,Auto,Auto,32" Margin="6,8,10,8">
<!-- Chevron toggle (only for planning parent tasks) --> <!-- Chevron toggle (only for planning parent tasks) -->
<Button Grid.Column="1" <Button Grid.Column="1"
@@ -194,8 +194,19 @@
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
<!-- Refine button -->
<Button Grid.Column="5" Classes="icon-btn refine-btn"
IsVisible="{Binding CanRefine}"
Command="{Binding $parent[ItemsControl].((vm:TasksIslandViewModel)DataContext).RefineTaskCommand}"
CommandParameter="{Binding}"
ToolTip.Tip="{loc:Tr tasks.refineTip}">
<Viewbox Width="16" Height="16">
<Path Classes="plan-icon" Data="{StaticResource Icon.Refine}"/>
</Viewbox>
</Button>
<!-- Star toggle --> <!-- Star toggle -->
<Button Grid.Column="5" Classes="icon-btn star-btn" <Button Grid.Column="6" Classes="icon-btn star-btn"
Classes.on="{Binding IsStarred}" Classes.on="{Binding IsStarred}"
VerticalAlignment="Top" Margin="0,2,0,0" VerticalAlignment="Top" Margin="0,2,0,0"
Command="{Binding $parent[ItemsControl].((vm:TasksIslandViewModel)DataContext).ToggleStarCommand}" Command="{Binding $parent[ItemsControl].((vm:TasksIslandViewModel)DataContext).ToggleStarCommand}"