mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 03:48:56 +00:00
Sidebar - Fixed removed categories not dissapearing
Sidebar - Fixed exception when creating a category with an already in use name
This commit is contained in:
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);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user