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
|
// ViewModels
|
||||||
sc.AddTransient<WorktreeModalViewModel>();
|
sc.AddTransient<WorktreeModalViewModel>();
|
||||||
|
sc.AddTransient<WorktreesOverviewModalViewModel>();
|
||||||
|
sc.AddTransient<Func<WorktreesOverviewModalViewModel>>(sp => () => sp.GetRequiredService<WorktreesOverviewModalViewModel>());
|
||||||
sc.AddSingleton<IPrimeScheduleApi, WorkerPrimeScheduleApi>();
|
sc.AddSingleton<IPrimeScheduleApi, WorkerPrimeScheduleApi>();
|
||||||
sc.AddTransient<PrimeClaudeTabViewModel>();
|
sc.AddTransient<PrimeClaudeTabViewModel>();
|
||||||
sc.AddTransient<SettingsModalViewModel>();
|
sc.AddTransient<SettingsModalViewModel>();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase
|
|||||||
|
|
||||||
public Func<SettingsModalViewModel, Task>? ShowSettingsModal { get; set; }
|
public Func<SettingsModalViewModel, Task>? ShowSettingsModal { get; set; }
|
||||||
public Func<ListSettingsModalViewModel, System.Threading.Tasks.Task>? ShowListSettingsModal { get; set; }
|
public Func<ListSettingsModalViewModel, System.Threading.Tasks.Task>? ShowListSettingsModal { get; set; }
|
||||||
|
public Func<WorktreesOverviewModalViewModel, Task>? ShowWorktreesOverviewModal { get; set; }
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task OpenSettings()
|
private async Task OpenSettings()
|
||||||
@@ -49,6 +50,18 @@ public sealed partial class ListsIslandViewModel : ViewModelBase
|
|||||||
await RefreshRowAsync(row.Id);
|
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> Items { get; } = new();
|
||||||
public ObservableCollection<ListNavItemViewModel> SmartLists { get; } = new();
|
public ObservableCollection<ListNavItemViewModel> SmartLists { get; } = new();
|
||||||
public ObservableCollection<ListNavItemViewModel> UserLists { get; } = new();
|
public ObservableCollection<ListNavItemViewModel> UserLists { get; } = new();
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public sealed partial class IslandsShellViewModel : ViewModelBase
|
|||||||
private readonly UpdateCheckService _updateCheck;
|
private readonly UpdateCheckService _updateCheck;
|
||||||
private readonly InstallerLocator _installerLocator;
|
private readonly InstallerLocator _installerLocator;
|
||||||
private readonly IDbContextFactory<ClaudeDoDbContext>? _dbFactory;
|
private readonly IDbContextFactory<ClaudeDoDbContext>? _dbFactory;
|
||||||
|
private readonly Func<WorktreesOverviewModalViewModel> _worktreesOverviewVmFactory = () => null!;
|
||||||
|
|
||||||
// Set by MainWindow to open the conflict resolution dialog.
|
// Set by MainWindow to open the conflict resolution dialog.
|
||||||
public Func<ConflictResolutionViewModel, Task>? ShowConflictDialog { get; set; }
|
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.
|
// Set by MainWindow to open the About dialog.
|
||||||
public Func<AboutModalViewModel, Task>? ShowAboutModal { get; set; }
|
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 bool _isUpdateBannerVisible;
|
||||||
[ObservableProperty] private string? _updateBannerLatestVersion;
|
[ObservableProperty] private string? _updateBannerLatestVersion;
|
||||||
[ObservableProperty] private string? _inlineUpdateStatus;
|
[ObservableProperty] private string? _inlineUpdateStatus;
|
||||||
@@ -159,12 +163,14 @@ public sealed partial class IslandsShellViewModel : ViewModelBase
|
|||||||
WorkerClient worker,
|
WorkerClient worker,
|
||||||
UpdateCheckService updateCheck,
|
UpdateCheckService updateCheck,
|
||||||
InstallerLocator installerLocator,
|
InstallerLocator installerLocator,
|
||||||
IDbContextFactory<ClaudeDoDbContext> dbFactory)
|
IDbContextFactory<ClaudeDoDbContext> dbFactory,
|
||||||
|
Func<WorktreesOverviewModalViewModel> worktreesOverviewVmFactory)
|
||||||
{
|
{
|
||||||
Lists = lists; Tasks = tasks; Details = details; Worker = worker;
|
Lists = lists; Tasks = tasks; Details = details; Worker = worker;
|
||||||
_updateCheck = updateCheck;
|
_updateCheck = updateCheck;
|
||||||
_installerLocator = installerLocator;
|
_installerLocator = installerLocator;
|
||||||
_dbFactory = dbFactory;
|
_dbFactory = dbFactory;
|
||||||
|
_worktreesOverviewVmFactory = worktreesOverviewVmFactory;
|
||||||
Lists.SelectionChanged += (_, _) => Tasks.LoadForList(Lists.SelectedList);
|
Lists.SelectionChanged += (_, _) => Tasks.LoadForList(Lists.SelectedList);
|
||||||
Tasks.SelectionChanged += (_, _) => Details.Bind(Tasks.SelectedTask);
|
Tasks.SelectionChanged += (_, _) => Details.Bind(Tasks.SelectedTask);
|
||||||
Tasks.TasksChanged += (_, _) => _ = Lists.RefreshCountsAsync();
|
Tasks.TasksChanged += (_, _) => _ = Lists.RefreshCountsAsync();
|
||||||
@@ -249,6 +255,16 @@ public sealed partial class IslandsShellViewModel : ViewModelBase
|
|||||||
if (ShowAboutModal is not null) await ShowAboutModal(vm);
|
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]
|
[RelayCommand]
|
||||||
private async Task CheckForUpdatesAsync()
|
private async Task CheckForUpdatesAsync()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -132,6 +132,9 @@
|
|||||||
<MenuItem Header="Settings..."
|
<MenuItem Header="Settings..."
|
||||||
Command="{Binding $parent[UserControl].((vm:ListsIslandViewModel)DataContext).OpenListSettingsCommand}"
|
Command="{Binding $parent[UserControl].((vm:ListsIslandViewModel)DataContext).OpenListSettingsCommand}"
|
||||||
CommandParameter="{Binding}"/>
|
CommandParameter="{Binding}"/>
|
||||||
|
<MenuItem Header="Worktrees anzeigen…"
|
||||||
|
Command="{Binding $parent[UserControl].((vm:ListsIslandViewModel)DataContext).OpenWorktreesOverviewCommand}"
|
||||||
|
CommandParameter="{Binding}"/>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</Border.ContextMenu>
|
</Border.ContextMenu>
|
||||||
<Grid ColumnDefinitions="20,*,Auto">
|
<Grid ColumnDefinitions="20,*,Auto">
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Linq;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using ClaudeDo.Ui.ViewModels.Islands;
|
using ClaudeDo.Ui.ViewModels.Islands;
|
||||||
@@ -25,6 +26,23 @@ public partial class ListsIslandView : UserControl
|
|||||||
if (top is null) window.Show();
|
if (top is null) window.Show();
|
||||||
else await window.ShowDialog(top);
|
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}"/>
|
Command="{Binding CheckForUpdatesCommand}"/>
|
||||||
<MenuItem Header="Restart worker"
|
<MenuItem Header="Restart worker"
|
||||||
Command="{Binding RestartWorkerCommand}"/>
|
Command="{Binding RestartWorkerCommand}"/>
|
||||||
|
<MenuItem Header="Worktrees…"
|
||||||
|
Command="{Binding OpenWorktreesOverviewGlobalCommand}"/>
|
||||||
<MenuItem Header="About…" Command="{Binding OpenAboutCommand}"/>
|
<MenuItem Header="About…" Command="{Binding OpenAboutCommand}"/>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
using System.Linq;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using ClaudeDo.Ui.ViewModels;
|
using ClaudeDo.Ui.ViewModels;
|
||||||
|
using ClaudeDo.Ui.ViewModels.Islands;
|
||||||
using ClaudeDo.Ui.Views.Modals;
|
using ClaudeDo.Ui.Views.Modals;
|
||||||
using ClaudeDo.Ui.Views.Planning;
|
using ClaudeDo.Ui.Views.Planning;
|
||||||
|
|
||||||
@@ -31,6 +33,21 @@ public partial class MainWindow : Window
|
|||||||
aboutVm.CloseAction = () => { dlg.Close(); tcs.TrySetResult(true); };
|
aboutVm.CloseAction = () => { dlg.Close(); tcs.TrySetResult(true); };
|
||||||
await dlg.ShowDialog(this);
|
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