General Changes
This commit is contained in:
@@ -28,6 +28,7 @@ public partial class MainWindowViewModel : ViewModelBase, IDisposable
|
||||
public StatusBarViewModel StatusBar { get; }
|
||||
|
||||
private readonly Action<string> _onTaskChanged;
|
||||
private readonly Action<string> _onTaskSubtasksChanged;
|
||||
|
||||
public MainWindowViewModel(
|
||||
IDbContextFactory<ClaudeDoDbContext> dbFactory,
|
||||
@@ -45,13 +46,20 @@ public partial class MainWindowViewModel : ViewModelBase, IDisposable
|
||||
StatusBar = statusBar;
|
||||
|
||||
_onTaskChanged = taskId => _ = TaskList.RefreshSingleAsync(taskId);
|
||||
_onTaskSubtasksChanged = taskId =>
|
||||
{
|
||||
if (TaskDetail.CurrentTaskId == taskId)
|
||||
_ = TaskDetail.RefreshSubtasksFromDbAsync();
|
||||
};
|
||||
TaskList.SelectedTaskChanged += OnSelectedTaskChanged;
|
||||
TaskList.TaskSubtasksChanged += _onTaskSubtasksChanged;
|
||||
TaskDetail.TaskChanged += _onTaskChanged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
TaskList.SelectedTaskChanged -= OnSelectedTaskChanged;
|
||||
TaskList.TaskSubtasksChanged -= _onTaskSubtasksChanged;
|
||||
TaskDetail.TaskChanged -= _onTaskChanged;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ public partial class TaskDetailViewModel : ViewModelBase
|
||||
public ObservableCollection<SubtaskItemViewModel> Subtasks { get; } = new();
|
||||
|
||||
private string? _taskId;
|
||||
public string? CurrentTaskId => _taskId;
|
||||
private string? _listId;
|
||||
private bool _isLoading;
|
||||
// Cancels an in-flight LoadAsync when a new TaskUpdated event arrives
|
||||
@@ -267,11 +268,13 @@ public partial class TaskDetailViewModel : ViewModelBase
|
||||
var vm = SubtaskItemViewModel.From(entity);
|
||||
vm.PropertyChanged += OnSubtaskPropertyChanged;
|
||||
Subtasks.Add(vm);
|
||||
TaskChanged?.Invoke(_taskId);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task RemoveSubtask(SubtaskItemViewModel item)
|
||||
{
|
||||
if (_taskId is null) return;
|
||||
if (!string.IsNullOrEmpty(item.Id))
|
||||
{
|
||||
using var context = _dbFactory.CreateDbContext();
|
||||
@@ -280,6 +283,7 @@ public partial class TaskDetailViewModel : ViewModelBase
|
||||
}
|
||||
item.PropertyChanged -= OnSubtaskPropertyChanged;
|
||||
Subtasks.Remove(item);
|
||||
TaskChanged?.Invoke(_taskId);
|
||||
}
|
||||
|
||||
private async void OnSubtaskPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
@@ -301,6 +305,8 @@ public partial class TaskDetailViewModel : ViewModelBase
|
||||
OrderNum = Subtasks.IndexOf(vm),
|
||||
CreatedAt = orig?.CreatedAt ?? DateTime.UtcNow,
|
||||
});
|
||||
if (e.PropertyName == nameof(SubtaskItemViewModel.Completed))
|
||||
TaskChanged?.Invoke(_taskId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -309,6 +315,35 @@ public partial class TaskDetailViewModel : ViewModelBase
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RefreshSubtasksFromDbAsync()
|
||||
{
|
||||
if (_taskId is null) return;
|
||||
|
||||
List<SubtaskEntity> subtasks;
|
||||
using (var context = _dbFactory.CreateDbContext())
|
||||
{
|
||||
var subtaskRepo = new SubtaskRepository(context);
|
||||
subtasks = await subtaskRepo.GetByTaskIdAsync(_taskId);
|
||||
}
|
||||
|
||||
_isLoading = true;
|
||||
try
|
||||
{
|
||||
foreach (var old in Subtasks) old.PropertyChanged -= OnSubtaskPropertyChanged;
|
||||
Subtasks.Clear();
|
||||
foreach (var s in subtasks)
|
||||
{
|
||||
var vm = SubtaskItemViewModel.From(s);
|
||||
vm.PropertyChanged += OnSubtaskPropertyChanged;
|
||||
Subtasks.Add(vm);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetAgentFromPath(string path)
|
||||
{
|
||||
var existing = AvailableAgents.FirstOrDefault(a => a.Path == path);
|
||||
|
||||
@@ -32,13 +32,15 @@ public partial class TaskItemViewModel : ViewModelBase
|
||||
private readonly Func<string, Task>? _runNow;
|
||||
private readonly Func<bool> _canRunNow;
|
||||
private readonly Func<string, Task>? _toggleDone;
|
||||
private readonly Action<string>? _onSubtasksChanged;
|
||||
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;
|
||||
private bool _subtasksLoaded;
|
||||
|
||||
public TaskItemViewModel(TaskEntity entity, IReadOnlyList<TagEntity> tags,
|
||||
Func<string, Task>? runNow, Func<bool> canRunNow,
|
||||
IDbContextFactory<ClaudeDoDbContext> dbFactory, int subtaskCount,
|
||||
Func<string, Task>? toggleDone = null)
|
||||
Func<string, Task>? toggleDone = null,
|
||||
Action<string>? onSubtasksChanged = null)
|
||||
{
|
||||
Entity = entity;
|
||||
Id = entity.Id;
|
||||
@@ -52,6 +54,7 @@ public partial class TaskItemViewModel : ViewModelBase
|
||||
_runNow = runNow;
|
||||
_canRunNow = canRunNow;
|
||||
_toggleDone = toggleDone;
|
||||
_onSubtasksChanged = onSubtasksChanged;
|
||||
_dbFactory = dbFactory;
|
||||
_subtaskCount = subtaskCount;
|
||||
_hasSubtasks = subtaskCount > 0;
|
||||
@@ -154,6 +157,8 @@ public partial class TaskItemViewModel : ViewModelBase
|
||||
entity.Completed = vm.Completed;
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
_onSubtasksChanged?.Invoke(Id);
|
||||
}
|
||||
|
||||
public async Task RefreshSubtasksAsync(int newCount)
|
||||
|
||||
@@ -29,10 +29,14 @@ public partial class TaskListViewModel : ViewModelBase
|
||||
[ObservableProperty] private string _inlineAddTitle = "";
|
||||
|
||||
public event Action<TaskItemViewModel?>? SelectedTaskChanged;
|
||||
public event Action<string>? TaskSubtasksChanged;
|
||||
|
||||
partial void OnSelectedTaskChanged(TaskItemViewModel? value) =>
|
||||
SelectedTaskChanged?.Invoke(value);
|
||||
|
||||
private void NotifySubtasksChanged(string taskId) =>
|
||||
TaskSubtasksChanged?.Invoke(taskId);
|
||||
|
||||
public TaskListViewModel(IDbContextFactory<ClaudeDoDbContext> dbFactory, WorkerClient worker,
|
||||
Func<TaskEditorViewModel> editorFactory, Action<string> showMessage)
|
||||
{
|
||||
@@ -101,7 +105,7 @@ public partial class TaskListViewModel : ViewModelBase
|
||||
var tags = await taskRepo.GetEffectiveTagsAsync(e.Id);
|
||||
subtaskCounts.TryGetValue(e.Id, out var count);
|
||||
Tasks.Add(new TaskItemViewModel(e, tags, RunNowAsync, () => _worker.IsConnected,
|
||||
_dbFactory, count, ToggleDoneAsync));
|
||||
_dbFactory, count, ToggleDoneAsync, NotifySubtasksChanged));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -143,7 +147,7 @@ public partial class TaskListViewModel : ViewModelBase
|
||||
await taskRepo.AddAsync(entity);
|
||||
var tags = await taskRepo.GetEffectiveTagsAsync(entity.Id);
|
||||
var vm = new TaskItemViewModel(entity, tags, RunNowAsync, () => _worker.IsConnected,
|
||||
_dbFactory, 0, ToggleDoneAsync);
|
||||
_dbFactory, 0, ToggleDoneAsync, NotifySubtasksChanged);
|
||||
Tasks.Add(vm);
|
||||
SelectedTask = vm;
|
||||
InlineAddTitle = "";
|
||||
@@ -195,7 +199,7 @@ public partial class TaskListViewModel : ViewModelBase
|
||||
|
||||
var tags = await taskRepo.GetEffectiveTagsAsync(saved.Id);
|
||||
Tasks.Add(new TaskItemViewModel(saved, tags, RunNowAsync, () => _worker.IsConnected,
|
||||
_dbFactory, 0, ToggleDoneAsync));
|
||||
_dbFactory, 0, ToggleDoneAsync, NotifySubtasksChanged));
|
||||
|
||||
// Auto wake-queue if agent+queued
|
||||
if (saved.Status == TaskStatus.Queued &&
|
||||
|
||||
Reference in New Issue
Block a user