fix(ui): wire delete confirm, close-details, uppercase eyebrow, explorer button

- A1: list-name eyebrow runs through UpperCase converter.
- D2: + Open-in-explorer icon button in AgentStrip (Process.Start on worktree path).
- D4: DeleteTaskCommand prompts inline confirm Window before deleting; shell
  wires Details.CloseDetail to clear Tasks.SelectedTask and Details.DeleteFromList
  to reload the current list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-04-20 11:47:10 +02:00
parent 9b1178ca2f
commit 5acc896d5c
5 changed files with 85 additions and 1 deletions

View File

@@ -78,6 +78,9 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
// Set by the view so OpenWorktreeCommand can show the modal as a dialog
public Func<WorktreeModalViewModel, System.Threading.Tasks.Task>? ShowWorktreeModal { get; set; }
// Set by the view so DeleteTaskCommand can prompt yes/no before deleting
public Func<string, System.Threading.Tasks.Task<bool>>? ConfirmAsync { get; set; }
public DetailsIslandViewModel(IDbContextFactory<ClaudeDoDbContext> dbFactory, WorkerClient worker, IServiceProvider services)
{
_dbFactory = dbFactory;
@@ -186,10 +189,26 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
private bool CanOpenWorktree() => WorktreePath != null;
[RelayCommand(CanExecute = nameof(CanOpenWorktree))]
private void OpenInExplorer()
{
if (WorktreePath == null) return;
try
{
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName = WorktreePath,
UseShellExecute = true,
});
}
catch { /* explorer open is best-effort */ }
}
partial void OnWorktreePathChanged(string? value)
{
OpenDiffCommand.NotifyCanExecuteChanged();
OpenWorktreeCommand.NotifyCanExecuteChanged();
OpenInExplorerCommand.NotifyCanExecuteChanged();
}
[RelayCommand]
@@ -212,6 +231,11 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase
{
if (Task == null) return;
var row = Task;
if (ConfirmAsync != null)
{
var ok = await ConfirmAsync($"Delete \"{row.Title}\"? This cannot be undone.");
if (!ok) return;
}
await using var ctx = _dbFactory.CreateDbContext();
var repo = new TaskRepository(ctx);
await repo.DeleteAsync(row.Id);