diff --git a/src/ClaudeDo.Ui/ViewModels/Islands/ListFolderNavItemViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Islands/ListFolderNavItemViewModel.cs index e90fc12e..aa3264dd 100644 --- a/src/ClaudeDo.Ui/ViewModels/Islands/ListFolderNavItemViewModel.cs +++ b/src/ClaudeDo.Ui/ViewModels/Islands/ListFolderNavItemViewModel.cs @@ -16,9 +16,16 @@ public sealed partial class ListFolderNavItemViewModel : ViewModelBase public string? ParentFolderId { get; set; } [ObservableProperty] private string _name = ""; [ObservableProperty] private string _iconKey = "Folder"; - [ObservableProperty] private bool _isCollapsed; + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(ShowCount))] + private bool _isCollapsed; // Sum of the descendant lists' counts, recursive — a collapsed folder still shows what's inside it. - [ObservableProperty] private int _count; + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(ShowCount))] + private int _count; + + /// Badge only while collapsed — expanded, the children show their own counts. + public bool ShowCount => IsCollapsed && Count > 0; // Set while a dragged list row hovers over the middle of this folder header (move-into-folder). [ObservableProperty] private bool _isDropTarget; // Insert-position hints for a drop next to the folder instead of into it. Drawn around the diff --git a/src/ClaudeDo.Ui/ViewModels/Islands/ListNavItemViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Islands/ListNavItemViewModel.cs index 447551a8..87245e08 100644 --- a/src/ClaudeDo.Ui/ViewModels/Islands/ListNavItemViewModel.cs +++ b/src/ClaudeDo.Ui/ViewModels/Islands/ListNavItemViewModel.cs @@ -8,7 +8,12 @@ public sealed partial class ListNavItemViewModel : ViewModelBase public required string Id { get; init; } public required ListKind Kind { get; init; } [ObservableProperty] private string _name = ""; - [ObservableProperty] private int _count; + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(HasCount))] + private int _count; + + /// Hides a "0" badge — an empty list reads as noise next to the real counts. + public bool HasCount => Count > 0; [ObservableProperty] private bool _isActive; [ObservableProperty] private string? _workingDir; [ObservableProperty] private string _defaultCommitType = CommitTypeRegistry.DefaultType; diff --git a/src/ClaudeDo.Ui/ViewModels/Islands/ListsIslandViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Islands/ListsIslandViewModel.cs index 95803af2..63f687f9 100644 --- a/src/ClaudeDo.Ui/ViewModels/Islands/ListsIslandViewModel.cs +++ b/src/ClaudeDo.Ui/ViewModels/Islands/ListsIslandViewModel.cs @@ -30,6 +30,9 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable /// Icon key a folder falls back to when it has none of its own. public const string ListFolderIcon = "Folder"; + /// Icon key a list falls back to — deliberately not the folder icon, so the two stay distinguishable. + public const string ListIcon = ListSettingsModalViewModel.DefaultIcon; + private readonly IDbContextFactory _dbFactory; private readonly IServiceProvider? _services; private readonly IWorkerClient? _worker; @@ -368,7 +371,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable Id = $"user:{l.Id}", Name = l.Name, Kind = ListKind.User, - IconKey = l.Icon ?? "Folder", + IconKey = l.Icon ?? ListIcon, WorkingDir = l.WorkingDir, DefaultCommitType = l.DefaultCommitType, IsManual = l.IsManual, @@ -473,7 +476,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable Id = $"user:{entity.Id}", Name = entity.Name, Kind = ListKind.User, - IconKey = "Folder", + IconKey = ListIcon, WorkingDir = entity.WorkingDir, DefaultCommitType = entity.DefaultCommitType, }; @@ -840,7 +843,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable row.DefaultCommitType = entity.DefaultCommitType; row.IsManual = entity.IsManual; row.FindingsTracked = entity.FindingsTracked; - row.IconKey = entity.Icon ?? "Folder"; + row.IconKey = entity.Icon ?? ListIcon; row.HasTicketProject = hasTicketProject; RecomputeHasNoLinkedRepo(); } @@ -886,7 +889,7 @@ public sealed partial class ListsIslandViewModel : ViewModelBase, IDisposable Id = $"user:{entity.Id}", Name = entity.Name, Kind = ListKind.User, - IconKey = entity.Icon ?? "Folder", + IconKey = entity.Icon ?? ListIcon, WorkingDir = entity.WorkingDir, DefaultCommitType = entity.DefaultCommitType, IsManual = entity.IsManual, diff --git a/src/ClaudeDo.Ui/ViewModels/Modals/ListSettingsModalViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Modals/ListSettingsModalViewModel.cs index 791ae825..cea6a3fe 100644 --- a/src/ClaudeDo.Ui/ViewModels/Modals/ListSettingsModalViewModel.cs +++ b/src/ClaudeDo.Ui/ViewModels/Modals/ListSettingsModalViewModel.cs @@ -111,7 +111,10 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase public ObservableCollection CommitTypeOptions { get; } = new(CommitTypeRegistry.Types); - public const string DefaultIcon = "Folder"; + public const string DefaultIcon = "Text"; + + /// Default icon for folders, kept apart from so lists never look like folders. + public const string DefaultFolderIcon = "Folder"; // Curated subset of the Icon.* geometry library in IslandStyles.axaml — window chrome and // pure stroke icons (PathIcon fills, so those render invisible) are deliberately left out. @@ -171,7 +174,7 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase IsFolder = true; CanToggleFolder = false; Name = name; - Icon = IconOptions.Contains(icon) ? icon! : DefaultIcon; + Icon = IconOptions.Contains(icon) ? icon! : DefaultFolderIcon; } public async Task LoadAsync( @@ -261,6 +264,13 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase // A manual list without a WorkingDir is untouched (empty is always valid) — this only fires // for the "picked a folder that turns out not to be a repo" case the audit found: it would // otherwise only surface as a Failed task the first time the worker tries to use it. + // The create-flow toggle swaps the untouched default so a new folder doesn't get the list icon. + partial void OnIsFolderChanged(bool value) + { + if (Icon == (value ? DefaultIcon : DefaultFolderIcon)) + Icon = value ? DefaultFolderIcon : DefaultIcon; + } + partial void OnWorkingDirChanged(string value) { if (string.IsNullOrWhiteSpace(value)) { WorkingDirWarning = ""; return; } diff --git a/src/ClaudeDo.Ui/Views/Islands/ListsIslandView.axaml b/src/ClaudeDo.Ui/Views/Islands/ListsIslandView.axaml index a9358906..181ce0a1 100644 --- a/src/ClaudeDo.Ui/Views/Islands/ListsIslandView.axaml +++ b/src/ClaudeDo.Ui/Views/Islands/ListsIslandView.axaml @@ -57,9 +57,11 @@ CommandParameter="{Binding}"/> - + + - @@ -70,18 +72,18 @@ Margin="-8,0,0,0"/> - - - + @@ -131,17 +133,21 @@ Data="{Binding IconKey, Converter={StaticResource IconKey}}" HorizontalAlignment="Center" VerticalAlignment="Center"/> + Text="{Binding Count}" IsVisible="{Binding ShowCount}"/> - + + + + +