118 lines
3.9 KiB
C#
118 lines
3.9 KiB
C#
using System.Collections.ObjectModel;
|
|
using ClaudeDo.Ui.Services;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
|
|
namespace ClaudeDo.Ui.ViewModels.Modals;
|
|
|
|
public sealed partial class MergeModalViewModel : ViewModelBase
|
|
{
|
|
private readonly WorkerClient _worker;
|
|
|
|
public string TaskId { get; set; } = "";
|
|
public string TaskTitle { get; set; } = "";
|
|
|
|
public ObservableCollection<string> Branches { get; } = new();
|
|
|
|
[ObservableProperty] private string? _selectedBranch;
|
|
[ObservableProperty] private bool _removeWorktree = true;
|
|
[ObservableProperty] private string _commitMessage = "";
|
|
|
|
[ObservableProperty] private bool _isBusy;
|
|
[ObservableProperty] private string? _errorMessage;
|
|
[ObservableProperty] private string? _warningMessage;
|
|
[ObservableProperty] private string? _successMessage;
|
|
[ObservableProperty] private bool _hasConflict;
|
|
[ObservableProperty] private IReadOnlyList<string> _conflictFiles = Array.Empty<string>();
|
|
|
|
public Action? CloseAction { get; set; }
|
|
|
|
public MergeModalViewModel(WorkerClient worker)
|
|
{
|
|
_worker = worker;
|
|
}
|
|
|
|
public async Task InitializeAsync(string taskId, string taskTitle)
|
|
{
|
|
TaskId = taskId;
|
|
TaskTitle = taskTitle;
|
|
CommitMessage = $"Merge task: {taskTitle}";
|
|
|
|
IsBusy = true;
|
|
try
|
|
{
|
|
var targets = await _worker.GetMergeTargetsAsync(taskId);
|
|
Branches.Clear();
|
|
if (targets is null)
|
|
{
|
|
ErrorMessage = "Worker offline — cannot list branches.";
|
|
return;
|
|
}
|
|
foreach (var b in targets.LocalBranches) Branches.Add(b);
|
|
SelectedBranch = Branches.Contains(targets.DefaultBranch)
|
|
? targets.DefaultBranch
|
|
: Branches.FirstOrDefault();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ErrorMessage = $"Failed to load branches: {ex.Message}";
|
|
}
|
|
finally { IsBusy = false; }
|
|
}
|
|
|
|
private bool CanSubmit() =>
|
|
!IsBusy && !HasConflict && !string.IsNullOrWhiteSpace(SelectedBranch);
|
|
|
|
[RelayCommand(CanExecute = nameof(CanSubmit))]
|
|
private async Task SubmitAsync()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(SelectedBranch)) return;
|
|
IsBusy = true;
|
|
ErrorMessage = null;
|
|
WarningMessage = null;
|
|
SuccessMessage = null;
|
|
try
|
|
{
|
|
var result = await _worker.MergeTaskAsync(
|
|
TaskId, SelectedBranch!, RemoveWorktree, CommitMessage);
|
|
|
|
switch (result.Status)
|
|
{
|
|
case "merged":
|
|
SuccessMessage = result.ErrorMessage is not null
|
|
? $"Merged with warning: {result.ErrorMessage}"
|
|
: "Merged.";
|
|
// Auto-close after a short delay.
|
|
_ = Task.Run(async () =>
|
|
{
|
|
await Task.Delay(1200);
|
|
Avalonia.Threading.Dispatcher.UIThread.Post(() => CloseAction?.Invoke());
|
|
});
|
|
break;
|
|
case "conflict":
|
|
HasConflict = true;
|
|
ConflictFiles = result.ConflictFiles;
|
|
ErrorMessage = "Merge conflict — target branch restored. Resolve manually or via Continue, then retry.";
|
|
break;
|
|
case "blocked":
|
|
ErrorMessage = $"Blocked: {result.ErrorMessage}";
|
|
break;
|
|
default:
|
|
ErrorMessage = $"Unknown status: {result.Status}";
|
|
break;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ErrorMessage = $"Merge failed: {ex.Message}";
|
|
}
|
|
finally
|
|
{
|
|
IsBusy = false;
|
|
}
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void Cancel() => CloseAction?.Invoke();
|
|
}
|