feat(ui): ListsIslandViewModel with smart/virtual/user lists

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-04-20 10:19:58 +02:00
parent 05404f46f2
commit 06cc141176
3 changed files with 54 additions and 1 deletions

View File

@@ -6,6 +6,7 @@ public sealed partial class ListNavItemViewModel : ViewModelBase
{ {
public required string Id { get; init; } public required string Id { get; init; }
public required string Name { get; init; } public required string Name { get; init; }
public required ListKind Kind { get; init; }
[ObservableProperty] private int _count; [ObservableProperty] private int _count;
[ObservableProperty] private bool _isActive; [ObservableProperty] private bool _isActive;
public string? IconKey { get; init; } public string? IconKey { get; init; }

View File

@@ -1,11 +1,62 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ClaudeDo.Data;
using ClaudeDo.Data.Repositories;
using Microsoft.EntityFrameworkCore;
namespace ClaudeDo.Ui.ViewModels.Islands; namespace ClaudeDo.Ui.ViewModels.Islands;
public enum ListKind { Smart, Virtual, User }
public sealed partial class ListsIslandViewModel : ViewModelBase public sealed partial class ListsIslandViewModel : ViewModelBase
{ {
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;
public event EventHandler? SelectionChanged; public event EventHandler? SelectionChanged;
public ObservableCollection<ListNavItemViewModel> Items { get; } = new();
[ObservableProperty] private string _searchText = "";
[ObservableProperty] private ListNavItemViewModel? _selectedList; [ObservableProperty] private ListNavItemViewModel? _selectedList;
partial void OnSelectedListChanged(ListNavItemViewModel? value) =>
public ListsIslandViewModel(IDbContextFactory<ClaudeDoDbContext> dbFactory)
{
_dbFactory = dbFactory;
}
public async Task LoadAsync(CancellationToken ct = default)
{
Items.Clear();
Items.Add(new ListNavItemViewModel { Id = "smart:my-day", Name = "My Day", Kind = ListKind.Smart, IconKey = "Sun" });
Items.Add(new ListNavItemViewModel { Id = "smart:important", Name = "Important", Kind = ListKind.Smart, IconKey = "Star" });
Items.Add(new ListNavItemViewModel { Id = "smart:planned", Name = "Planned", Kind = ListKind.Smart, IconKey = "Calendar" });
Items.Add(new ListNavItemViewModel { Id = "virtual:running", Name = "Running", Kind = ListKind.Virtual, IconKey = "Pulse" });
Items.Add(new ListNavItemViewModel { Id = "virtual:review", Name = "Review", Kind = ListKind.Virtual, IconKey = "Eye" });
await using var ctx = await _dbFactory.CreateDbContextAsync(ct);
var lists = new ListRepository(ctx);
var seedNames = new HashSet<string>(new[] { "My Day", "Important", "Planned" });
foreach (var l in await lists.GetAllAsync(ct))
if (!seedNames.Contains(l.Name))
Items.Add(new ListNavItemViewModel { Id = $"user:{l.Id}", Name = l.Name, Kind = ListKind.User, IconKey = "Folder" });
await RefreshCountsAsync(ct);
SelectedList = Items.FirstOrDefault();
}
public async Task RefreshCountsAsync(CancellationToken ct = default)
{
foreach (var i in Items) i.Count = 0;
await Task.CompletedTask;
}
[RelayCommand]
private void Select(ListNavItemViewModel item) => SelectedList = item;
partial void OnSelectedListChanged(ListNavItemViewModel? value)
{
foreach (var i in Items) i.IsActive = ReferenceEquals(i, value);
SelectionChanged?.Invoke(this, EventArgs.Empty); SelectionChanged?.Invoke(this, EventArgs.Empty);
}
} }

View File

@@ -29,5 +29,6 @@ public sealed partial class IslandsShellViewModel : ViewModelBase
Lists = lists; Tasks = tasks; Details = details; Lists = lists; Tasks = tasks; Details = details;
Lists.SelectionChanged += (_, _) => Tasks.LoadForList(Lists.SelectedList); Lists.SelectionChanged += (_, _) => Tasks.LoadForList(Lists.SelectedList);
Tasks.SelectionChanged += (_, _) => Details.Bind(Tasks.SelectedTask); Tasks.SelectionChanged += (_, _) => Details.Bind(Tasks.SelectedTask);
_ = Lists.LoadAsync();
} }
} }