feat(ui): live task updates from worker events + planning polish

Wire TasksIslandViewModel to TaskUpdated/WorktreeUpdated/TaskMessage worker
events so rows refresh without a full reload; add ForegroundHelper to permit
wt.exe to take foreground on planning launch; misc UI polish on lists, task
rows and settings modal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-04-24 11:12:27 +02:00
parent e455d85578
commit b7c60f5838
18 changed files with 200 additions and 56 deletions

View File

@@ -40,8 +40,9 @@ public sealed partial class ListsIslandViewModel : ViewModelBase
private async System.Threading.Tasks.Task OpenListSettingsAsync(ListNavItemViewModel? row)
{
if (row is null || ShowListSettingsModal is null || _services is null) return;
var rawId = row.Id.StartsWith("user:", StringComparison.Ordinal) ? row.Id["user:".Length..] : row.Id;
var vm = _services.GetRequiredService<ListSettingsModalViewModel>();
await vm.LoadAsync(row.Id, row.Name, row.WorkingDir, row.DefaultCommitType);
await vm.LoadAsync(rawId, row.Name, row.WorkingDir, row.DefaultCommitType);
await ShowListSettingsModal(vm);
await RefreshRowAsync(row.Id);
}
@@ -169,6 +170,46 @@ public sealed partial class ListsIslandViewModel : ViewModelBase
[RelayCommand]
private void Select(ListNavItemViewModel item) => SelectedList = item;
[RelayCommand]
private async Task CreateListAsync()
{
var entity = new ListEntity
{
Id = Guid.NewGuid().ToString("N"),
Name = "New list",
DefaultCommitType = "chore",
CreatedAt = DateTime.UtcNow,
};
await using (var ctx = await _dbFactory.CreateDbContextAsync())
{
var lists = new ListRepository(ctx);
await lists.AddAsync(entity);
}
var item = new ListNavItemViewModel
{
Id = $"user:{entity.Id}",
Name = entity.Name,
Kind = ListKind.User,
IconKey = "Folder",
DotColorKey = "Moss",
WorkingDir = entity.WorkingDir,
DefaultCommitType = entity.DefaultCommitType,
};
Items.Add(item);
UserLists.Add(item);
SelectedList = item;
if (ShowListSettingsModal is not null && _services is not null)
{
var vm = _services.GetRequiredService<ListSettingsModalViewModel>();
await vm.LoadAsync(entity.Id, entity.Name, entity.WorkingDir, entity.DefaultCommitType);
await ShowListSettingsModal(vm);
await RefreshRowAsync(item.Id);
}
}
partial void OnSelectedListChanged(ListNavItemViewModel? value)
{
foreach (var i in Items) i.IsActive = ReferenceEquals(i, value);
@@ -188,6 +229,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase
var entity = await lists.GetByIdAsync(rawId);
if (entity is null) return;
row.Name = entity.Name;
row.WorkingDir = entity.WorkingDir;
row.DefaultCommitType = entity.DefaultCommitType;
}