diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bccb5e3..97e04675 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,12 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2 ## v2.12.0-dev.3 ### Added - Added Settings option "Console: History Size" to adjust the number of lines stored in the console history when running packages. Defaults to 9001 lines. -- Added "New Directory" and "Delete" options to the context menu of the tree view on the Checkpoints page. -- Added new toggle for dragging and dropping models on the Checkpoints page, when enabled, all selected models will now move together with the dragged model -- Added "File Size" sorting option to the Checkpoints page +#### Checkpoint Manager +- Added "New Directory" and "Delete" options to the context menu of the tree view. +- Added new toggle for drag & drop - when enabled, all selected models will now move together with the dragged model +- Added "File Size" sorting option +- Added "Hide Empty Categories" toggle +- Added "Select All" button to the InfoBar (shown when at least one model is selected) ### Changed - The "Download Failed" message for model downloads is now persistent until dismissed ### Fixed diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs index 29acccc3..2172f029 100644 --- a/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointsPageViewModel.cs @@ -129,6 +129,9 @@ ServiceManager dialogFactory [ObservableProperty] private bool dragMovesAllSelected = true; + [ObservableProperty] + private bool hideEmptyRootCategories; + public string ClearButtonText => SelectedBaseModels.Count == BaseModelOptions.Count ? Resources.Action_ClearSelection @@ -289,8 +292,7 @@ or nameof(SortConnectedModelsFirst) x ) ) - .Sort(comparerObservable) - .Bind(Models) + .SortAndBind(Models, comparerObservable) .WhenPropertyChanged(p => p.IsSelected) .Throttle(TimeSpan.FromMilliseconds(50)) .Subscribe(_ => @@ -298,9 +300,17 @@ or nameof(SortConnectedModelsFirst) NumItemsSelected = Models.Count(o => o.IsSelected); }); + var categoryFilterPredicate = Observable + .FromEventPattern(this, nameof(PropertyChanged)) + .Where(x => x.EventArgs.PropertyName is nameof(HideEmptyRootCategories)) + .Throttle(TimeSpan.FromMilliseconds(50)) + .Select(_ => (Func)FilterCategories) + .AsObservable(); + categoriesCache .Connect() .DeferUntilLoaded() + .Filter(categoryFilterPredicate) .SortAndBind( Categories, SortExpressionComparer @@ -362,6 +372,13 @@ or nameof(SortConnectedModelsFirst) true ); + settingsManager.RelayPropertyFor( + this, + vm => vm.HideEmptyRootCategories, + settings => settings.HideEmptyRootCategories, + true + ); + // make sure a sort happens OnPropertyChanged(nameof(SortConnectedModelsFirst)); } @@ -665,6 +682,12 @@ private async Task DeleteFolderAsync(object? treeViewItem) RefreshCategories(); } + [RelayCommand] + private void SelectAll() + { + Models.ForEach(x => x.IsSelected = true); + } + public async Task ImportFilesAsync(IEnumerable files, DirectoryPath destinationFolder) { if (destinationFolder.FullPath == settingsManager.ModelsDirectory) @@ -809,6 +832,13 @@ private void RefreshCategories() ) .ToList(); + foreach (var checkpointCategory in modelCategories.SelectMany(c => c.Flatten())) + { + checkpointCategory.Count = Directory + .EnumerateFileSystemEntries(checkpointCategory.Path, "*", SearchOption.AllDirectories) + .Count(x => LocalModelFile.SupportedCheckpointExtensions.Contains(Path.GetExtension(x))); + } + var rootCategory = new CheckpointCategory { Path = settingsManager.ModelsDirectory, @@ -843,13 +873,6 @@ private void RefreshCategories() previouslySelectedCategory ?? Categories.FirstOrDefault(x => x.Path == previouslySelectedCategory?.Path) ?? Categories.First(); - - foreach (var checkpointCategory in Categories.SelectMany(c => c.Flatten())) - { - checkpointCategory.Count = Directory - .EnumerateFileSystemEntries(checkpointCategory.Path, "*", SearchOption.AllDirectories) - .Count(x => LocalModelFile.SupportedCheckpointExtensions.Contains(Path.GetExtension(x))); - } } private ObservableCollection GetSubfolders(string strPath) @@ -953,4 +976,9 @@ is false ? folderPath.Contains(categoryRelativePath) : categoryRelativePath.Equals(folderPath); } + + private bool FilterCategories(CheckpointCategory category) + { + return !HideEmptyRootCategories || category is { Count: > 0 }; + } } diff --git a/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml b/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml index 05a93373..c74b733c 100644 --- a/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml +++ b/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml @@ -280,6 +280,13 @@ Label="Move All Selected Models" ToolTip.Tip="When enabled, dragging and dropping a model will also move any selected models to the drop location." IsChecked="{Binding DragMovesAllSelected, Mode=TwoWay}" /> + + + + + @@ -619,10 +626,18 @@ -