style(ui): lists icons, section headers, active state

- Add central icon library (Icon.Sun/Activity/Star/Calendar/Eye/Inbox/Folder/Search/Plus/MoreHorizontal/GitBranch/Copy/Trash/Sort/X/Check) to IslandStyles.axaml
- Add list-section-label, search-wrap, kbd, new-list-btn, avatar-circle styles
- Add UpperCaseConverter, IconKeyConverter, DotBrushConverter; register in App.axaml
- Expose SmartLists / UserLists filtered collections from ListsIslandViewModel
- Add DotColorKey (Moss/Peat/Sage rotation) and UserInitials/UserName/MachineName props

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-04-20 11:22:35 +02:00
parent 0bf2d78fba
commit 4531b95c42
7 changed files with 256 additions and 7 deletions

View File

@@ -10,4 +10,5 @@ public sealed partial class ListNavItemViewModel : ViewModelBase
[ObservableProperty] private int _count;
[ObservableProperty] private bool _isActive;
public string? IconKey { get; init; }
public string? DotColorKey { get; init; }
}

View File

@@ -18,30 +18,63 @@ public sealed partial class ListsIslandViewModel : ViewModelBase
public void RequestFocusSearch() => FocusSearchRequested?.Invoke(this, EventArgs.Empty);
public ObservableCollection<ListNavItemViewModel> Items { get; } = new();
public ObservableCollection<ListNavItemViewModel> SmartLists { get; } = new();
public ObservableCollection<ListNavItemViewModel> UserLists { get; } = new();
[ObservableProperty] private string _searchText = "";
[ObservableProperty] private ListNavItemViewModel? _selectedList;
public string UserName { get; } = Environment.UserName;
public string MachineName { get; } = Environment.MachineName;
public string UserInitials { get; }
public ListsIslandViewModel(IDbContextFactory<ClaudeDoDbContext> dbFactory)
{
_dbFactory = dbFactory;
var parts = Environment.UserName.Split('.', '_', '-', ' ');
UserInitials = parts.Length >= 2
? $"{parts[0][0]}{parts[1][0]}".ToUpperInvariant()
: Environment.UserName.Length >= 2
? Environment.UserName[..2].ToUpperInvariant()
: Environment.UserName.ToUpperInvariant();
}
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" });
SmartLists.Clear();
UserLists.Clear();
var smart = new[]
{
new ListNavItemViewModel { Id = "smart:my-day", Name = "My Day", Kind = ListKind.Smart, IconKey = "Sun" },
new ListNavItemViewModel { Id = "smart:important", Name = "Important", Kind = ListKind.Smart, IconKey = "Star" },
new ListNavItemViewModel { Id = "smart:planned", Name = "Planned", Kind = ListKind.Smart, IconKey = "Calendar" },
new ListNavItemViewModel { Id = "virtual:running", Name = "Running", Kind = ListKind.Virtual, IconKey = "Activity" },
new ListNavItemViewModel { Id = "virtual:review", Name = "Review", Kind = ListKind.Virtual, IconKey = "Eye" },
};
foreach (var s in smart) { Items.Add(s); SmartLists.Add(s); }
await using var ctx = await _dbFactory.CreateDbContextAsync(ct);
var lists = new ListRepository(ctx);
var seedNames = new HashSet<string>(new[] { "My Day", "Important", "Planned" });
var dotColors = new[] { "Moss", "Peat", "Sage" };
int idx = 0;
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" });
{
if (seedNames.Contains(l.Name)) continue;
var item = new ListNavItemViewModel
{
Id = $"user:{l.Id}",
Name = l.Name,
Kind = ListKind.User,
IconKey = "Folder",
DotColorKey = dotColors[idx % dotColors.Length],
};
Items.Add(item);
UserLists.Add(item);
idx++;
}
await RefreshCountsAsync(ct);
SelectedList = Items.FirstOrDefault();