feat(claude-do): merge feat(ui): "Worktree öffnen" im Kontextmenü der Task-Zeile

ClaudeDo-Task: 9be17e29e0b54f42ba9385b0cebe89d5
This commit is contained in:
mika kuns
2026-08-21 18:14:45 +02:00
6 changed files with 92 additions and 2 deletions
@@ -20,6 +20,7 @@ public sealed partial class TaskRowViewModel : ViewModelBase
[ObservableProperty] private string? _branch;
[ObservableProperty] private string? _diffStat;
[ObservableProperty] private ClaudeDo.Data.Models.WorktreeState? _worktreeState;
[ObservableProperty] private string? _worktreePath;
[ObservableProperty] private DateTime? _scheduledFor;
[ObservableProperty] private int _diffAdditions;
[ObservableProperty] private int _diffDeletions;
@@ -179,6 +180,9 @@ public sealed partial class TaskRowViewModel : ViewModelBase
// placeholder so the menu wiring is uniform; always null until a real gate exists.
public string? QuickSessionDisabledReason => null;
public bool CanOpenWorktree => !string.IsNullOrWhiteSpace(WorktreePath);
public string? OpenWorktreeDisabledReason => CanOpenWorktree ? null : Loc.T("tasks.reasonNoWorktree");
public string? RefineDisabledReason
{
get
@@ -425,6 +429,11 @@ public sealed partial class TaskRowViewModel : ViewModelBase
partial void OnNumberChanged(int value) => OnPropertyChanged(nameof(ShowNumberBadge));
partial void OnBranchChanged(string? value) => OnPropertyChanged(nameof(HasBranch));
partial void OnWorktreePathChanged(string? value)
{
OnPropertyChanged(nameof(CanOpenWorktree));
OnPropertyChanged(nameof(OpenWorktreeDisabledReason));
}
partial void OnWorktreeStateChanged(ClaudeDo.Data.Models.WorktreeState? value)
{
OnPropertyChanged(nameof(IsParked));
@@ -485,6 +494,7 @@ public sealed partial class TaskRowViewModel : ViewModelBase
Branch = t.Worktree?.BranchName;
DiffStat = t.Worktree?.DiffStat;
WorktreeState = t.Worktree?.State;
WorktreePath = t.Worktree?.Path;
ScheduledFor = t.ScheduledFor;
DiffAdditions = add;
DiffDeletions = del;
@@ -1429,6 +1429,21 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
OpenConPtySessionRequested?.Invoke(row.Id);
}
[RelayCommand]
private void OpenTaskWorktree(TaskRowViewModel? row)
{
if (row?.WorktreePath is not { } path || string.IsNullOrWhiteSpace(path)) return;
try
{
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName = path,
UseShellExecute = true,
});
}
catch (Exception ex) { ErrorReported?.Invoke(Loc.T("vm.tasksIsland.openWorktreeFailed", ex.Message)); }
}
[RelayCommand]
private async Task ResumePlanningSessionAsync(TaskRowViewModel? row)
{