feat(ui): planning commands and expand/collapse in TasksIslandViewModel
- Add IWorkerClient interface; WorkerClient implements it - TasksIslandViewModel accepts IWorkerClient? and gains OpenPlanningSession, ResumePlanningSession, DiscardPlanningSession, FinalizePlanningSession, and ToggleExpand commands - Regroup() is hierarchy-aware: children of collapsed planning parents are hidden - InternalsVisibleTo ClaudeDo.Worker.Tests for Regroup() - 4 new unit tests covering collapse/expand and guard logic Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,8 @@ namespace ClaudeDo.Ui.ViewModels.Islands;
|
||||
public sealed partial class TasksIslandViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;
|
||||
private readonly WorkerClient? _worker;
|
||||
private readonly IWorkerClient? _worker;
|
||||
private readonly Dictionary<string, bool> _expandedState = new();
|
||||
private ListNavItemViewModel? _currentList;
|
||||
private CancellationTokenSource? _loadCts;
|
||||
|
||||
@@ -41,7 +42,7 @@ public sealed partial class TasksIslandViewModel : ViewModelBase
|
||||
[ObservableProperty] private bool _showOpenLabel;
|
||||
[ObservableProperty] private string _completedHeader = "COMPLETED";
|
||||
|
||||
public TasksIslandViewModel(IDbContextFactory<ClaudeDoDbContext> dbFactory, WorkerClient? worker = null)
|
||||
public TasksIslandViewModel(IDbContextFactory<ClaudeDoDbContext> dbFactory, IWorkerClient? worker = null)
|
||||
{
|
||||
_dbFactory = dbFactory;
|
||||
_worker = worker;
|
||||
@@ -105,14 +106,35 @@ public sealed partial class TasksIslandViewModel : ViewModelBase
|
||||
catch (OperationCanceledException) { }
|
||||
}
|
||||
|
||||
private void Regroup()
|
||||
internal void Regroup()
|
||||
{
|
||||
OverdueItems.Clear();
|
||||
OpenItems.Clear();
|
||||
CompletedItems.Clear();
|
||||
|
||||
var today = DateTime.Today;
|
||||
// Restore IsExpanded from saved state
|
||||
foreach (var r in Items)
|
||||
{
|
||||
if (_expandedState.TryGetValue(r.Id, out var saved))
|
||||
r.IsExpanded = saved;
|
||||
}
|
||||
|
||||
// Build hierarchy-aware flat list: top-level rows interleaved with visible children.
|
||||
// Items is already ordered by SortOrder from the DB query.
|
||||
var topLevel = Items.Where(r => !r.IsChild);
|
||||
var flat = new List<TaskRowViewModel>();
|
||||
foreach (var parent in topLevel)
|
||||
{
|
||||
flat.Add(parent);
|
||||
if (parent.IsPlanningParent && parent.IsExpanded)
|
||||
{
|
||||
var children = Items.Where(r => r.ParentTaskId == parent.Id);
|
||||
flat.AddRange(children);
|
||||
}
|
||||
}
|
||||
|
||||
var today = DateTime.Today;
|
||||
foreach (var r in flat)
|
||||
{
|
||||
if (r.Done)
|
||||
CompletedItems.Add(r);
|
||||
@@ -356,6 +378,48 @@ public sealed partial class TasksIslandViewModel : ViewModelBase
|
||||
[RelayCommand]
|
||||
private void OpenListSettings() => OpenListSettingsRequested?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
[RelayCommand]
|
||||
private async Task OpenPlanningSessionAsync(TaskRowViewModel? row)
|
||||
{
|
||||
if (row is null || row.Status != TaskStatus.Manual) return;
|
||||
try { await _worker!.StartPlanningSessionAsync(row.Id); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task ResumePlanningSessionAsync(TaskRowViewModel? row)
|
||||
{
|
||||
if (row is null || !row.IsPlanningParent) return;
|
||||
try { await _worker!.ResumePlanningSessionAsync(row.Id); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task DiscardPlanningSessionAsync(TaskRowViewModel? row)
|
||||
{
|
||||
if (row is null) return;
|
||||
try { await _worker!.DiscardPlanningSessionAsync(row.Id); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task FinalizePlanningSessionAsync(TaskRowViewModel? row)
|
||||
{
|
||||
if (row is null) return;
|
||||
try { await _worker!.FinalizePlanningSessionAsync(row.Id, queueAgentTasks: true); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ToggleExpand(TaskRowViewModel? row)
|
||||
{
|
||||
if (row is null) return;
|
||||
var next = !(_expandedState.TryGetValue(row.Id, out var current) ? current : row.IsExpanded);
|
||||
_expandedState[row.Id] = next;
|
||||
row.IsExpanded = next;
|
||||
Regroup();
|
||||
}
|
||||
|
||||
partial void OnSelectedTaskChanged(TaskRowViewModel? value)
|
||||
{
|
||||
foreach (var i in Items) i.IsSelected = ReferenceEquals(i, value);
|
||||
|
||||
Reference in New Issue
Block a user