using System.Diagnostics; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using ClaudeDo.Ui.Localization; using ClaudeDo.Ui.Services; namespace ClaudeDo.Ui.ViewModels.Planning; public sealed partial class ConflictResolutionViewModel : ObservableObject { private readonly IWorkerClient _worker; private readonly string _planningTaskId; private readonly string _worktreePath; public string SubtaskTitle { get; } public string TargetBranch { get; } public IReadOnlyList ConflictedFiles { get; } public string SubtaskLabel => Loc.T("vm.conflictResolution.subtaskPrefix", SubtaskTitle); public string TargetLabel => Loc.T("vm.conflictResolution.targetPrefix", TargetBranch); [ObservableProperty] private string? _vsCodeError; [ObservableProperty] private string? _actionError; public Action? CloseRequested { get; set; } public ConflictResolutionViewModel( IWorkerClient worker, string planningTaskId, string subtaskTitle, string targetBranch, IReadOnlyList conflictedFiles, string worktreePath) { _worker = worker; _planningTaskId = planningTaskId; _worktreePath = worktreePath; SubtaskTitle = subtaskTitle; TargetBranch = targetBranch; ConflictedFiles = conflictedFiles; } [RelayCommand] private void OpenInVsCode() { try { var args = string.Join(" ", ConflictedFiles.Select(f => $"\"{f}\"")); Process.Start(new ProcessStartInfo { FileName = "code", Arguments = args, WorkingDirectory = _worktreePath, UseShellExecute = true, }); VsCodeError = null; } catch (Exception ex) { VsCodeError = Loc.T("vm.conflictResolution.vsCodeError", ex.Message); } } [RelayCommand] private async Task ContinueAsync() { ActionError = null; try { await _worker.ContinuePlanningMergeAsync(_planningTaskId); CloseRequested?.Invoke(); } catch (Exception ex) { ActionError = ex.Message; } } [RelayCommand] private async Task AbortAsync() { ActionError = null; try { await _worker.AbortPlanningMergeAsync(_planningTaskId); CloseRequested?.Invoke(); } catch (Exception ex) { ActionError = ex.Message; } } }