refactor(ui): single IDialogService replaces scattered Show* dialog seams

Collapses the ~10 per-modal Show*Modal Func callbacks (wired separately on the shell and the lists island) into one IDialogService + WindowDialogService impl. Removes the RepoImport/WorktreesOverview dialog construction duplicated across MainWindow and ListsIslandView, plus the Confirm/Error dialogs duplicated in both code-behinds. Shell/lists Open* commands now route through an injected Dialogs handle (propagated shell->lists); the per-list worktrees overview also wires conflict resolution now, matching the global one. No VM ctor changes (Dialogs is a settable seam), so no test-fake impact.
This commit is contained in:
Mika Kuns
2026-06-26 16:11:47 +02:00
parent 1fb2e34f85
commit d598a539bc
6 changed files with 234 additions and 291 deletions
@@ -27,28 +27,25 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable
public event EventHandler? FocusSearchRequested;
public void RequestFocusSearch() => FocusSearchRequested?.Invoke(this, EventArgs.Empty);
public Func<SettingsModalViewModel, Task>? ShowSettingsModal { get; set; }
public Func<ListSettingsModalViewModel, System.Threading.Tasks.Task>? ShowListSettingsModal { get; set; }
public Func<WorktreesOverviewModalViewModel, Task>? ShowWorktreesOverviewModal { get; set; }
public Func<RepoImportModalViewModel, System.Threading.Tasks.Task>? ShowRepoImportModal { get; set; }
public IDialogService? Dialogs { get; set; }
[RelayCommand]
private async Task OpenSettings()
{
if (ShowSettingsModal is null || _services is null) return;
if (Dialogs is null || _services is null) return;
var settingsVm = _services.GetRequiredService<SettingsModalViewModel>();
await settingsVm.LoadAsync();
await ShowSettingsModal(settingsVm);
await Dialogs.ShowSettingsAsync(settingsVm);
}
[RelayCommand]
private async System.Threading.Tasks.Task OpenListSettingsAsync(ListNavItemViewModel? row)
{
if (row is null || ShowListSettingsModal is null || _services is null) return;
if (row is null || Dialogs is null || _services is null) return;
var rawId = row.Id.StartsWith("user:", StringComparison.Ordinal) ? row.Id["user:".Length..] : row.Id;
var vm = _services.GetRequiredService<ListSettingsModalViewModel>();
await vm.LoadAsync(rawId, row.Name, row.WorkingDir, row.DefaultCommitType);
await ShowListSettingsModal(vm);
await Dialogs.ShowListSettingsAsync(vm);
if (vm.Deleted) await LoadAsync();
else await RefreshRowAsync(row.Id);
}
@@ -56,10 +53,10 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable
[RelayCommand]
private async System.Threading.Tasks.Task OpenRepoImportAsync()
{
if (ShowRepoImportModal is null || _services is null) return;
if (Dialogs is null || _services is null) return;
var vm = _services.GetRequiredService<RepoImportModalViewModel>();
await vm.LoadAsync();
await ShowRepoImportModal(vm);
await Dialogs.ShowRepoImportAsync(vm);
await LoadAsync();
}
@@ -68,7 +65,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable
[RelayCommand]
private async Task OpenWorktreesOverviewAsync(ListNavItemViewModel? row)
{
if (row is null || ShowWorktreesOverviewModal is null || _services is null) return;
if (row is null || Dialogs is null || _services is null) return;
if (row.Kind != ListKind.User) return;
if (_worktreesOverviewOpen) return;
_worktreesOverviewOpen = true;
@@ -78,7 +75,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable
var vm = _services.GetRequiredService<WorktreesOverviewModalViewModel>();
vm.Configure(rawId, row.Name);
await vm.LoadAsync();
await ShowWorktreesOverviewModal(vm);
await Dialogs.ShowWorktreesOverviewAsync(vm);
}
finally { _worktreesOverviewOpen = false; }
}
@@ -297,11 +294,11 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable
UserLists.Add(item);
SelectedList = item;
if (ShowListSettingsModal is not null && _services is not null)
if (Dialogs is not null && _services is not null)
{
var vm = _services.GetRequiredService<ListSettingsModalViewModel>();
await vm.LoadAsync(entity.Id, entity.Name, entity.WorkingDir, entity.DefaultCommitType);
await ShowListSettingsModal(vm);
await Dialogs.ShowListSettingsAsync(vm);
if (vm.Deleted) await LoadAsync();
else await RefreshRowAsync(item.Id);
}