refactor(merge): single IMergeCoordinator replaces the 5 conflict seams
The RequestConflictResolution Func was declared on 5 VMs and hand-threaded shell->details->merge-section->diff->merge-modal. Replaced with a DI-singleton IMergeCoordinator (MergeCoordinator holder; shell wires its Handler at composition, breaking the shell<->island cycle). Invokers (MergeModal, DetailsIsland, WorktreesOverview) depend on the interface; the two pass-through VMs (DiffModal, MergeSection) drop the seam entirely. No behavior change; conflict-seam + batch tests rewired to assert via the coordinator.
This commit is contained in:
@@ -52,6 +52,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
private readonly IWorkerClient _worker;
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly INotesApi _notesApi;
|
||||
private readonly IMergeCoordinator _merge;
|
||||
|
||||
// ── Section view models ───────────────────────────────────────────────────
|
||||
public AgentSettingsSectionViewModel AgentSettings { get; }
|
||||
@@ -343,13 +344,6 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
|
||||
public bool HasReviewFeedback => !string.IsNullOrWhiteSpace(ReviewFeedback);
|
||||
|
||||
// Kept for backwards-compat surface — delegates to Merge.RequestConflictResolution
|
||||
public Func<string, string, System.Threading.Tasks.Task>? RequestConflictResolution
|
||||
{
|
||||
get => Merge.RequestConflictResolution;
|
||||
set => Merge.RequestConflictResolution = value;
|
||||
}
|
||||
|
||||
private static string StatusToStateKey(ClaudeDo.Data.Models.TaskStatus status) => status switch
|
||||
{
|
||||
ClaudeDo.Data.Models.TaskStatus.Queued => "queued",
|
||||
@@ -404,12 +398,14 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
IDbContextFactory<ClaudeDoDbContext> dbFactory,
|
||||
IWorkerClient worker,
|
||||
IServiceProvider services,
|
||||
INotesApi notesApi)
|
||||
INotesApi notesApi,
|
||||
IMergeCoordinator merge)
|
||||
{
|
||||
_dbFactory = dbFactory;
|
||||
_worker = worker;
|
||||
_services = services;
|
||||
_notesApi = notesApi;
|
||||
_merge = merge;
|
||||
|
||||
AgentSettings = new AgentSettingsSectionViewModel(worker);
|
||||
Merge = new MergeSectionViewModel(worker, services);
|
||||
@@ -1151,20 +1147,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
|
||||
var hasChildren = Subtasks.Count > 0 || ChildOutcomes.Count > 0;
|
||||
var result = await _worker.ApproveReviewAsync(Task.Id, Merge.SelectedMergeTarget ?? "");
|
||||
if (!hasChildren && result?.Status == "conflict")
|
||||
{
|
||||
if (Merge.RequestConflictResolution is not null)
|
||||
{
|
||||
await Merge.RequestConflictResolution(Task.Id, Merge.SelectedMergeTarget ?? "");
|
||||
}
|
||||
else
|
||||
{
|
||||
var (text, _, _) = MergePreviewPresenter.Describe(
|
||||
new MergePreviewDto("conflict", result.ConflictFiles, 0));
|
||||
Merge.MergePreviewText = text;
|
||||
Merge.MergeIsClean = false;
|
||||
Merge.MergeIsConflict = true;
|
||||
}
|
||||
}
|
||||
await _merge.ResolveConflictAsync(Task.Id, Merge.SelectedMergeTarget ?? "");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user