feat(ui): wire worktree overview modal entry points
Add list context-menu command (per-list mode) and Help menu entry (global mode) for the WorktreesOverviewModal; register VM and factory in DI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -95,6 +95,8 @@ sealed class Program
|
||||
|
||||
// ViewModels
|
||||
sc.AddTransient<WorktreeModalViewModel>();
|
||||
sc.AddTransient<WorktreesOverviewModalViewModel>();
|
||||
sc.AddTransient<Func<WorktreesOverviewModalViewModel>>(sp => () => sp.GetRequiredService<WorktreesOverviewModalViewModel>());
|
||||
sc.AddSingleton<IPrimeScheduleApi, WorkerPrimeScheduleApi>();
|
||||
sc.AddTransient<PrimeClaudeTabViewModel>();
|
||||
sc.AddTransient<SettingsModalViewModel>();
|
||||
|
||||
@@ -28,6 +28,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase
|
||||
|
||||
public Func<SettingsModalViewModel, Task>? ShowSettingsModal { get; set; }
|
||||
public Func<ListSettingsModalViewModel, System.Threading.Tasks.Task>? ShowListSettingsModal { get; set; }
|
||||
public Func<WorktreesOverviewModalViewModel, Task>? ShowWorktreesOverviewModal { get; set; }
|
||||
|
||||
[RelayCommand]
|
||||
private async Task OpenSettings()
|
||||
@@ -49,6 +50,18 @@ public sealed partial class ListsIslandViewModel : ViewModelBase
|
||||
await RefreshRowAsync(row.Id);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task OpenWorktreesOverviewAsync(ListNavItemViewModel? row)
|
||||
{
|
||||
if (row is null || ShowWorktreesOverviewModal is null || _services is null) return;
|
||||
if (row.Kind != ListKind.User) return;
|
||||
var rawId = row.Id.StartsWith("user:", StringComparison.Ordinal) ? row.Id["user:".Length..] : row.Id;
|
||||
var vm = _services.GetRequiredService<WorktreesOverviewModalViewModel>();
|
||||
vm.Configure(rawId, row.Name);
|
||||
await vm.LoadAsync();
|
||||
await ShowWorktreesOverviewModal(vm);
|
||||
}
|
||||
|
||||
public ObservableCollection<ListNavItemViewModel> Items { get; } = new();
|
||||
public ObservableCollection<ListNavItemViewModel> SmartLists { get; } = new();
|
||||
public ObservableCollection<ListNavItemViewModel> UserLists { get; } = new();
|
||||
|
||||
@@ -32,6 +32,7 @@ public sealed partial class IslandsShellViewModel : ViewModelBase
|
||||
private readonly UpdateCheckService _updateCheck;
|
||||
private readonly InstallerLocator _installerLocator;
|
||||
private readonly IDbContextFactory<ClaudeDoDbContext>? _dbFactory;
|
||||
private readonly Func<WorktreesOverviewModalViewModel> _worktreesOverviewVmFactory = () => null!;
|
||||
|
||||
// Set by MainWindow to open the conflict resolution dialog.
|
||||
public Func<ConflictResolutionViewModel, Task>? ShowConflictDialog { get; set; }
|
||||
@@ -39,6 +40,9 @@ public sealed partial class IslandsShellViewModel : ViewModelBase
|
||||
// Set by MainWindow to open the About dialog.
|
||||
public Func<AboutModalViewModel, Task>? ShowAboutModal { get; set; }
|
||||
|
||||
// Set by MainWindow to open the global worktrees overview dialog.
|
||||
public Func<WorktreesOverviewModalViewModel, Task>? ShowWorktreesOverviewModal { get; set; }
|
||||
|
||||
[ObservableProperty] private bool _isUpdateBannerVisible;
|
||||
[ObservableProperty] private string? _updateBannerLatestVersion;
|
||||
[ObservableProperty] private string? _inlineUpdateStatus;
|
||||
@@ -159,12 +163,14 @@ public sealed partial class IslandsShellViewModel : ViewModelBase
|
||||
WorkerClient worker,
|
||||
UpdateCheckService updateCheck,
|
||||
InstallerLocator installerLocator,
|
||||
IDbContextFactory<ClaudeDoDbContext> dbFactory)
|
||||
IDbContextFactory<ClaudeDoDbContext> dbFactory,
|
||||
Func<WorktreesOverviewModalViewModel> worktreesOverviewVmFactory)
|
||||
{
|
||||
Lists = lists; Tasks = tasks; Details = details; Worker = worker;
|
||||
_updateCheck = updateCheck;
|
||||
_installerLocator = installerLocator;
|
||||
_dbFactory = dbFactory;
|
||||
_worktreesOverviewVmFactory = worktreesOverviewVmFactory;
|
||||
Lists.SelectionChanged += (_, _) => Tasks.LoadForList(Lists.SelectedList);
|
||||
Tasks.SelectionChanged += (_, _) => Details.Bind(Tasks.SelectedTask);
|
||||
Tasks.TasksChanged += (_, _) => _ = Lists.RefreshCountsAsync();
|
||||
@@ -249,6 +255,16 @@ public sealed partial class IslandsShellViewModel : ViewModelBase
|
||||
if (ShowAboutModal is not null) await ShowAboutModal(vm);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task OpenWorktreesOverviewGlobalAsync()
|
||||
{
|
||||
if (ShowWorktreesOverviewModal is null) return;
|
||||
var vm = _worktreesOverviewVmFactory();
|
||||
vm.Configure(null, null);
|
||||
await vm.LoadAsync();
|
||||
await ShowWorktreesOverviewModal(vm);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task CheckForUpdatesAsync()
|
||||
{
|
||||
|
||||
@@ -132,6 +132,9 @@
|
||||
<MenuItem Header="Settings..."
|
||||
Command="{Binding $parent[UserControl].((vm:ListsIslandViewModel)DataContext).OpenListSettingsCommand}"
|
||||
CommandParameter="{Binding}"/>
|
||||
<MenuItem Header="Worktrees anzeigen…"
|
||||
Command="{Binding $parent[UserControl].((vm:ListsIslandViewModel)DataContext).OpenWorktreesOverviewCommand}"
|
||||
CommandParameter="{Binding}"/>
|
||||
</ContextMenu>
|
||||
</Border.ContextMenu>
|
||||
<Grid ColumnDefinitions="20,*,Auto">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Linq;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using ClaudeDo.Ui.ViewModels.Islands;
|
||||
@@ -25,6 +26,23 @@ public partial class ListsIslandView : UserControl
|
||||
if (top is null) window.Show();
|
||||
else await window.ShowDialog(top);
|
||||
};
|
||||
vm.ShowWorktreesOverviewModal = async modal =>
|
||||
{
|
||||
var window = new WorktreesOverviewModalView { DataContext = modal };
|
||||
modal.CloseAction = () => window.Close();
|
||||
modal.JumpToTaskAction = (listId, _) =>
|
||||
{
|
||||
if (vm is { } v)
|
||||
{
|
||||
var item = v.UserLists.FirstOrDefault(l => l.Id == $"user:{listId}");
|
||||
if (item is not null) v.SelectedList = item;
|
||||
}
|
||||
};
|
||||
// TODO: ShowDiffAction and ConfirmAction not wired in v1
|
||||
var top = TopLevel.GetTopLevel(this) as Window;
|
||||
if (top is null) window.Show();
|
||||
else await window.ShowDialog(top);
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@
|
||||
Command="{Binding CheckForUpdatesCommand}"/>
|
||||
<MenuItem Header="Restart worker"
|
||||
Command="{Binding RestartWorkerCommand}"/>
|
||||
<MenuItem Header="Worktrees…"
|
||||
Command="{Binding OpenWorktreesOverviewGlobalCommand}"/>
|
||||
<MenuItem Header="About…" Command="{Binding OpenAboutCommand}"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System.Linq;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using ClaudeDo.Ui.ViewModels;
|
||||
using ClaudeDo.Ui.ViewModels.Islands;
|
||||
using ClaudeDo.Ui.Views.Modals;
|
||||
using ClaudeDo.Ui.Views.Planning;
|
||||
|
||||
@@ -31,6 +33,21 @@ public partial class MainWindow : Window
|
||||
aboutVm.CloseAction = () => { dlg.Close(); tcs.TrySetResult(true); };
|
||||
await dlg.ShowDialog(this);
|
||||
};
|
||||
vm.ShowWorktreesOverviewModal = async (modal) =>
|
||||
{
|
||||
var dlg = new WorktreesOverviewModalView { DataContext = modal };
|
||||
modal.CloseAction = () => dlg.Close();
|
||||
modal.JumpToTaskAction = (listId, _) =>
|
||||
{
|
||||
if (DataContext is IslandsShellViewModel s)
|
||||
{
|
||||
var item = s.Lists?.UserLists.FirstOrDefault(l => l.Id == $"user:{listId}");
|
||||
if (item is not null && s.Lists is not null) s.Lists.SelectedList = item;
|
||||
}
|
||||
};
|
||||
// TODO: ShowDiffAction and ConfirmAction not wired in v1
|
||||
await dlg.ShowDialog(this);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user