Sidebar - Fixed removed categories not dissapearing

Sidebar - Fixed exception when creating a category with an already in use name
This commit is contained in:
Robert committed 2022-10-12 21:20:39 +02:00
1 parent 6a12286783
commit d4bd44b504
10 files changed
+193 -144

No files matched your search

@@ -1,4 +1,5 @@
using System.Reactive;
using System.Linq;
using System.Reactive;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Shared;
@@ -23,7 +24,8 @@ public class SidebarCategoryEditViewModel : ContentDialogViewModelBase
_categoryName = _category.Name;
Confirm = ReactiveCommand.Create(ExecuteConfirm, ValidationContext.Valid);
this.ValidationRule(vm => vm.CategoryName, categoryName => !string.IsNullOrWhiteSpace(categoryName), "You must specify a valid name");
this.ValidationRule(vm => vm.CategoryName, categoryName => !string.IsNullOrWhiteSpace(categoryName?.Trim()), "You must specify a valid name");
this.ValidationRule(vm => vm.CategoryName, categoryName => profileService.ProfileCategories.All(c => c.Name != categoryName?.Trim()), "You must specify a unique name");
}
public string? CategoryName
@@ -38,12 +40,12 @@ public class SidebarCategoryEditViewModel : ContentDialogViewModelBase
{
if (_category != null)
{
_category.Name = CategoryName!;
_category.Name = CategoryName!.Trim();
_profileService.SaveProfileCategory(_category);
}
else
{
_profileService.CreateProfileCategory(CategoryName!);
_profileService.CreateProfileCategory(CategoryName!.Trim());
}
ContentDialog?.Hide(ContentDialogResult.Primary);
@@ -24,17 +24,18 @@ namespace Artemis.UI.Screens.Sidebar;
public class SidebarCategoryViewModel : ActivatableViewModelBase
{
private readonly IProfileService _profileService;
private readonly SidebarViewModel _sidebarViewModel;
private readonly ISidebarVmFactory _vmFactory;
private readonly IWindowService _windowService;
private ObservableAsPropertyHelper<bool>? _isCollapsed;
private ObservableAsPropertyHelper<bool>? _isSuspended;
private SidebarProfileConfigurationViewModel? _selectedProfileConfiguration;
public SidebarCategoryViewModel(SidebarViewModel sidebarViewModel, ProfileCategory profileCategory, IProfileService profileService, IWindowService windowService,
IProfileEditorService profileEditorService, ISidebarVmFactory vmFactory)
public SidebarCategoryViewModel(ProfileCategory profileCategory,
IProfileService profileService,
IWindowService windowService,
IProfileEditorService profileEditorService,
ISidebarVmFactory vmFactory)
{
_sidebarViewModel = sidebarViewModel;
_profileService = profileService;
_windowService = windowService;
_vmFactory = vmFactory;
@@ -47,7 +48,7 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase
profileConfigurations.Connect()
.Filter(profileConfigurationsFilter)
.Sort(SortExpressionComparer<ProfileConfiguration>.Ascending(c => c.Order))
.Transform(c => _vmFactory.SidebarProfileConfigurationViewModel(_sidebarViewModel, c))
.Transform(c => _vmFactory.SidebarProfileConfigurationViewModel(c))
.Bind(out ReadOnlyObservableCollection<SidebarProfileConfigurationViewModel> profileConfigurationViewModels)
.Subscribe();
ProfileConfigurations = profileConfigurationViewModels;
@@ -93,7 +94,7 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase
_windowService.ShowExceptionDialog(s.ProfileConfiguration.BrokenState, s.ProfileConfiguration.BrokenStateException);
else
_windowService.ShowExceptionDialog(e.Message, e);
profileEditorService.ChangeCurrentProfileConfiguration(null);
SelectedProfileConfiguration = null;
}
@@ -148,8 +149,6 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase
.WithCloseButtonText("Cancel")
.WithDefaultButton(ContentDialogButton.Primary)
.ShowAsync();
_sidebarViewModel.UpdateProfileCategories();
}
private async Task ExecuteDeleteCategory()
@@ -166,7 +165,7 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase
);
if (result != null)
{
SidebarProfileConfigurationViewModel viewModel = _vmFactory.SidebarProfileConfigurationViewModel(_sidebarViewModel, result);
SidebarProfileConfigurationViewModel viewModel = _vmFactory.SidebarProfileConfigurationViewModel(result);
SelectedProfileConfiguration = viewModel;
}
}
@@ -230,8 +229,6 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase
ProfileCategory.Order--;
_profileService.SaveProfileCategory(categories[index - 1]);
_profileService.SaveProfileCategory(ProfileCategory);
_sidebarViewModel.UpdateProfileCategories();
}
private void ExecuteMoveDown()
@@ -245,7 +242,5 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase
ProfileCategory.Order++;
_profileService.SaveProfileCategory(categories[index + 1]);
_profileService.SaveProfileCategory(ProfileCategory);
_sidebarViewModel.UpdateProfileCategories();
}
}
@@ -19,17 +19,11 @@ public class SidebarProfileConfigurationViewModel : ActivatableViewModelBase
{
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileService _profileService;
private readonly SidebarViewModel _sidebarViewModel;
private readonly IWindowService _windowService;
private ObservableAsPropertyHelper<bool>? _isDisabled;
public SidebarProfileConfigurationViewModel(SidebarViewModel sidebarViewModel,
ProfileConfiguration profileConfiguration,
IProfileService profileService,
IProfileEditorService profileEditorService,
IWindowService windowService)
public SidebarProfileConfigurationViewModel(ProfileConfiguration profileConfiguration, IProfileService profileService, IProfileEditorService profileEditorService, IWindowService windowService)
{
_sidebarViewModel = sidebarViewModel;
_profileService = profileService;
_profileEditorService = profileEditorService;
_windowService = windowService;
@@ -63,13 +57,10 @@ public class SidebarProfileConfigurationViewModel : ActivatableViewModelBase
private async Task ExecuteEditProfile()
{
ProfileConfiguration? edited = await _windowService.ShowDialogAsync<ProfileConfigurationEditViewModel, ProfileConfiguration?>(
await _windowService.ShowDialogAsync<ProfileConfigurationEditViewModel, ProfileConfiguration?>(
("profileCategory", ProfileConfiguration.Category),
("profileConfiguration", ProfileConfiguration)
);
if (edited != null)
_sidebarViewModel.UpdateProfileCategories();
}
private void ExecuteToggleSuspended()
@@ -4,8 +4,10 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:sidebar="clr-namespace:Artemis.UI.Screens.Sidebar"
mc:Ignorable="d" d:DesignWidth="240" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Sidebar.SidebarView">
x:Class="Artemis.UI.Screens.Sidebar.SidebarView"
x:DataType="sidebar:SidebarViewModel">
<UserControl.Styles>
<StyleInclude Source="avares://Avalonia.Xaml.Interactions/Draggable/Styles.axaml" />
</UserControl.Styles>
@@ -24,18 +26,18 @@
<ListBox Classes="sidebar-listbox"
Grid.Row="1"
Margin="10 2"
Items="{Binding SidebarScreens}"
SelectedItem="{Binding SelectedSidebarScreen}" />
Items="{CompiledBinding SidebarScreens}"
SelectedItem="{CompiledBinding SelectedSidebarScreen}" />
<Separator Grid.Row="2" Margin="8" Height="1" Background="#FF6c6c6c" />
<!-- Categories -->
<ScrollViewer Grid.Row="3" VerticalScrollBarVisibility="Auto">
<StackPanel>
<ItemsControl Margin="10 2" Items="{Binding SidebarCategories}" Classes="profile-categories" />
<ItemsControl Margin="10 2" Items="{CompiledBinding SidebarCategories}" Classes="profile-categories" />
<Button Content="Add new category"
Margin="10"
HorizontalAlignment="Stretch"
Command="{Binding AddCategory}" />
Command="{CompiledBinding AddCategory}" />
</StackPanel>
</ScrollViewer>
@@ -1,7 +1,9 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
@@ -15,35 +17,38 @@ using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.Builders;
using Artemis.UI.Shared.Services.ProfileEditor;
using Avalonia.Threading;
using DynamicData;
using DynamicData.Binding;
using Material.Icons;
using Ninject;
using ReactiveUI;
using RGB.NET.Core;
namespace Artemis.UI.Screens.Sidebar;
public class SidebarViewModel : ActivatableViewModelBase
{
private readonly IScreen _hostScreen;
private readonly IKernel _kernel;
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileService _profileService;
private readonly IRgbService _rgbService;
private readonly ISidebarVmFactory _sidebarVmFactory;
private readonly IProfileEditorVmFactory _profileEditorVmFactory;
private readonly IWindowService _windowService;
private ArtemisDevice? _headerDevice;
private SidebarScreenViewModel? _selectedSidebarScreen;
private ReadOnlyObservableCollection<SidebarCategoryViewModel> _sidebarCategories = new(new ObservableCollection<SidebarCategoryViewModel>());
public SidebarViewModel(IScreen hostScreen, IKernel kernel, IProfileService profileService, IRgbService rgbService, IWindowService windowService,
IProfileEditorService profileEditorService, ISidebarVmFactory sidebarVmFactory, IProfileEditorVmFactory profileEditorVmFactory)
public SidebarViewModel(IScreen hostScreen,
IKernel kernel,
IProfileService profileService,
IWindowService windowService,
IProfileEditorService profileEditorService,
ISidebarVmFactory sidebarVmFactory,
IProfileEditorVmFactory profileEditorVmFactory)
{
_hostScreen = hostScreen;
_profileService = profileService;
_rgbService = rgbService;
_kernel = kernel;
_windowService = windowService;
_profileEditorService = profileEditorService;
_sidebarVmFactory = sidebarVmFactory;
_profileEditorVmFactory = profileEditorVmFactory;
SidebarScreens = new ObservableCollection<SidebarScreenViewModel>
{
@@ -55,45 +60,52 @@ public class SidebarViewModel : ActivatableViewModelBase
new SidebarScreenViewModel<SettingsViewModel>(MaterialIconKind.Cog, "Settings")
};
UpdateProfileCategories();
UpdateHeaderDevice();
AddCategory = ReactiveCommand.CreateFromTask(ExecuteAddCategory);
this.WhenActivated(disposables =>
SourceList<ProfileCategory> profileCategories = new();
this.WhenActivated(d =>
{
this.WhenAnyObservable(vm => vm._hostScreen.Router.CurrentViewModel)
.WhereNotNull()
this.WhenAnyObservable(vm => vm._hostScreen.Router.CurrentViewModel).WhereNotNull()
.Subscribe(c => SelectedSidebarScreen = SidebarScreens.FirstOrDefault(s => s.ScreenType == c.GetType()))
.DisposeWith(disposables);
.DisposeWith(d);
this.WhenAnyValue(vm => vm.SelectedSidebarScreen)
.WhereNotNull()
.Subscribe(s =>
{
_hostScreen.Router.Navigate.Execute(s.CreateInstance(kernel, _hostScreen));
profileEditorService.ChangeCurrentProfileConfiguration(null);
});
this.WhenAnyValue(vm => vm.SelectedSidebarScreen).WhereNotNull().Subscribe(NavigateToScreen);
this.WhenAnyObservable(vm => vm._profileEditorService.ProfileConfiguration).Subscribe(NavigateToProfile).DisposeWith(d);
this.WhenAnyObservable(vm => vm._profileEditorService.ProfileConfiguration)
.Subscribe(profile =>
{
if (profile == null && _hostScreen.Router.GetCurrentViewModel() is ProfileEditorViewModel)
SelectedSidebarScreen = SidebarScreens.FirstOrDefault();
else if (profile != null && _hostScreen.Router.GetCurrentViewModel() is not ProfileEditorViewModel)
_hostScreen.Router.Navigate.Execute(profileEditorVmFactory.ProfileEditorViewModel(_hostScreen));
})
.DisposeWith(disposables);
Observable.FromEventPattern<ProfileCategoryEventArgs>(x => profileService.ProfileCategoryAdded += x, x => profileService.ProfileCategoryAdded -= x)
.Subscribe(e => profileCategories.Add(e.EventArgs.ProfileCategory))
.DisposeWith(d);
Observable.FromEventPattern<ProfileCategoryEventArgs>(x => profileService.ProfileCategoryRemoved += x, x => profileService.ProfileCategoryRemoved -= x)
.Subscribe(e => profileCategories.Remove(e.EventArgs.ProfileCategory))
.DisposeWith(d);
profileCategories.Edit(c =>
{
c.Clear();
c.AddRange(profileService.ProfileCategories);
});
profileCategories.Connect()
.AutoRefresh(p => p.Order)
.Sort(SortExpressionComparer<ProfileCategory>.Ascending(p => p.Order))
.Transform(sidebarVmFactory.SidebarCategoryViewModel)
.ObserveOn(AvaloniaScheduler.Instance)
.Bind(out ReadOnlyObservableCollection<SidebarCategoryViewModel> categoryViewModels)
.Subscribe()
.DisposeWith(d);
SidebarCategories = categoryViewModels;
SelectedSidebarScreen = SidebarScreens.First();
});
}
public ObservableCollection<SidebarScreenViewModel> SidebarScreens { get; }
public ObservableCollection<SidebarCategoryViewModel> SidebarCategories { get; } = new();
public ArtemisDevice? HeaderDevice
public ReadOnlyObservableCollection<SidebarCategoryViewModel> SidebarCategories
{
get => _headerDevice;
set => RaiseAndSetIfChanged(ref _headerDevice, value);
get => _sidebarCategories;
set => RaiseAndSetIfChanged(ref _sidebarCategories, value);
}
public SidebarScreenViewModel? SelectedSidebarScreen
@@ -102,14 +114,9 @@ public class SidebarViewModel : ActivatableViewModelBase
set => RaiseAndSetIfChanged(ref _selectedSidebarScreen, value);
}
public SidebarCategoryViewModel AddProfileCategoryViewModel(ProfileCategory profileCategory)
{
SidebarCategoryViewModel viewModel = _sidebarVmFactory.SidebarCategoryViewModel(this, profileCategory);
SidebarCategories.Add(viewModel);
return viewModel;
}
public ReactiveCommand<Unit, Unit> AddCategory { get; }
public async Task AddCategory()
private async Task ExecuteAddCategory()
{
await _windowService.CreateContentDialog()
.WithTitle("Add new category")
@@ -118,19 +125,19 @@ public class SidebarViewModel : ActivatableViewModelBase
.WithCloseButtonText("Cancel")
.WithDefaultButton(ContentDialogButton.Primary)
.ShowAsync();
UpdateProfileCategories();
}
public void UpdateProfileCategories()
private void NavigateToProfile(ProfileConfiguration? profile)
{
SidebarCategories.Clear();
foreach (ProfileCategory profileCategory in _profileService.ProfileCategories.OrderBy(p => p.Order))
AddProfileCategoryViewModel(profileCategory);
if (profile == null && _hostScreen.Router.GetCurrentViewModel() is ProfileEditorViewModel)
SelectedSidebarScreen = SidebarScreens.FirstOrDefault();
else if (profile != null && _hostScreen.Router.GetCurrentViewModel() is not ProfileEditorViewModel)
_hostScreen.Router.Navigate.Execute(_profileEditorVmFactory.ProfileEditorViewModel(_hostScreen));
}
private void UpdateHeaderDevice()
private void NavigateToScreen(SidebarScreenViewModel sidebarScreenViewModel)
{
HeaderDevice = _rgbService.Devices.FirstOrDefault(d => d.DeviceType == RGBDeviceType.Keyboard && d.Layout is {IsValid: true});
_hostScreen.Router.Navigate.Execute(sidebarScreenViewModel.CreateInstance(_kernel, _hostScreen));
_profileEditorService.ChangeCurrentProfileConfiguration(null);
}
}