feat(ui): wire avalonia desktop ui to data and worker
App: build a ServiceProvider in Program.cs (AppSettings, SqliteConnectionFactory, all repositories, GitService, WorkerClient, all view-models), apply schema, then hand control to Avalonia. App.OnFrameworkInitializationCompleted resolves MainWindowViewModel from the container. Ui: - AppSettings POCO loaded from ~/.todo-app/ui.config.json (db path, hub url). - WorkerClient wraps HubConnection with auto-reconnect, exposes IsConnected and ActiveTasks plus C# events for TaskStarted/Finished/Message/Updated and WorktreeUpdated; all inbound events are marshalled to the UI thread. - ViewModels: MainWindow (lists CRUD via ListEditor dialog), TaskList (load by list, add/edit/delete, auto WakeQueue on agent+queued create), TaskItem (RunNow gated on connection + status), TaskDetail (description, result, live ndjson rolling buffer of 500 lines, worktree branch/diff with merge/keep/ discard via GitService), StatusBar, ListEditor, TaskEditor. - Views: 3-pane MainWindow (lists | tasks | detail) with GridSplitters, status bar, dialog windows for the editors. Status badges via StatusColorConverter. - Markdown rendering, folder picker, delete-confirmation, settings dialog and scroll-to-bottom on the live log are intentionally TODO -- functional scaffold only. Tests: also debounce the FIFO queue test (poll instead of Task.Delay(200)) so the assertion isn't racy when the suite runs alongside the slower git tests. 38 tests pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
52
src/ClaudeDo.Ui/ViewModels/StatusBarViewModel.cs
Normal file
52
src/ClaudeDo.Ui/ViewModels/StatusBarViewModel.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Specialized;
|
||||
using ClaudeDo.Ui.Services;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace ClaudeDo.Ui.ViewModels;
|
||||
|
||||
public partial class StatusBarViewModel : ViewModelBase
|
||||
{
|
||||
private readonly WorkerClient _worker;
|
||||
|
||||
[ObservableProperty] private string _connectionStatus = "Offline";
|
||||
[ObservableProperty] private string _activeTasksSummary = "";
|
||||
[ObservableProperty] private string _statusMessage = "";
|
||||
|
||||
public StatusBarViewModel(WorkerClient worker)
|
||||
{
|
||||
_worker = worker;
|
||||
|
||||
worker.PropertyChanged += (_, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(WorkerClient.IsConnected))
|
||||
{
|
||||
ConnectionStatus = worker.IsConnected ? "Online" : "Offline";
|
||||
}
|
||||
};
|
||||
|
||||
worker.ActiveTasks.CollectionChanged += OnActiveTasksChanged;
|
||||
RefreshActiveSummary();
|
||||
}
|
||||
|
||||
private void OnActiveTasksChanged(object? sender, NotifyCollectionChangedEventArgs e) =>
|
||||
RefreshActiveSummary();
|
||||
|
||||
private void RefreshActiveSummary()
|
||||
{
|
||||
if (_worker.ActiveTasks.Count == 0)
|
||||
{
|
||||
ActiveTasksSummary = "";
|
||||
return;
|
||||
}
|
||||
|
||||
var parts = _worker.ActiveTasks
|
||||
.Select(t => $"{t.Slot}: {Shorten(t.TaskId)}")
|
||||
.ToList();
|
||||
ActiveTasksSummary = string.Join(" | ", parts);
|
||||
}
|
||||
|
||||
private static string Shorten(string id) =>
|
||||
id.Length > 8 ? id[..8] : id;
|
||||
|
||||
public void ShowMessage(string msg) => StatusMessage = msg;
|
||||
}
|
||||
Reference in New Issue
Block a user