mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 03:48:56 +00:00
UI - Added routing (#802)
ColorGradient - Fixed GetColor returning the first stop if position was after the last stop
This commit is contained in:
1 parent
79309dcee7
commit
962b13c6ed
77 files changed
+2034
-854
No files matched your search
@@ -149,7 +149,7 @@ public class ProfileConfigurationEditViewModel : DialogViewModelBase<ProfileConf
|
||||
return;
|
||||
|
||||
if (_profileConfiguration.IsBeingEdited)
|
||||
_profileEditorService.ChangeCurrentProfileConfiguration(null);
|
||||
await _profileEditorService.ChangeCurrentProfileConfiguration(null);
|
||||
_profileService.RemoveProfileConfiguration(_profileConfiguration);
|
||||
Close(_profileConfiguration);
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.DryIoc.Factories;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Routing;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.Builders;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using DynamicData;
|
||||
using DynamicData.Binding;
|
||||
using Newtonsoft.Json;
|
||||
@@ -24,23 +24,19 @@ namespace Artemis.UI.Screens.Sidebar;
|
||||
public class SidebarCategoryViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly IProfileService _profileService;
|
||||
private readonly ISidebarVmFactory _vmFactory;
|
||||
private readonly IWindowService _windowService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly ISidebarVmFactory _vmFactory;
|
||||
private readonly IRouter _router;
|
||||
private ObservableAsPropertyHelper<bool>? _isCollapsed;
|
||||
private ObservableAsPropertyHelper<bool>? _isSuspended;
|
||||
private SidebarProfileConfigurationViewModel? _selectedProfileConfiguration;
|
||||
|
||||
public SidebarCategoryViewModel(ProfileCategory profileCategory,
|
||||
IProfileService profileService,
|
||||
IWindowService windowService,
|
||||
IProfileEditorService profileEditorService,
|
||||
ISidebarVmFactory vmFactory)
|
||||
public SidebarCategoryViewModel(ProfileCategory profileCategory, IProfileService profileService, IWindowService windowService, ISidebarVmFactory vmFactory, IRouter router)
|
||||
{
|
||||
_profileService = profileService;
|
||||
_windowService = windowService;
|
||||
_profileEditorService = profileEditorService;
|
||||
_vmFactory = vmFactory;
|
||||
_router = router;
|
||||
|
||||
ProfileCategory = profileCategory;
|
||||
SourceList<ProfileConfiguration> profileConfigurations = new();
|
||||
@@ -66,6 +62,14 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
// Navigate on selection change
|
||||
this.WhenAnyValue(vm => vm.SelectedProfileConfiguration)
|
||||
.WhereNotNull()
|
||||
.Subscribe(s => _router.Navigate($"profile-editor/{s.ProfileConfiguration.ProfileId}", new RouterNavigationOptions {IgnoreOnPartialMatch = true, RecycleScreens = false}))
|
||||
.DisposeWith(d);
|
||||
|
||||
_router.CurrentPath.WhereNotNull().Subscribe(r => SelectedProfileConfiguration = ProfileConfigurations.FirstOrDefault(c => c.Matches(r))).DisposeWith(d);
|
||||
|
||||
// Update the list of profiles whenever the category fires events
|
||||
Observable.FromEventPattern<ProfileConfigurationEventArgs>(x => profileCategory.ProfileConfigurationAdded += x, x => profileCategory.ProfileConfigurationAdded -= x)
|
||||
.Subscribe(e => profileConfigurations.Add(e.EventArgs.ProfileConfiguration))
|
||||
@@ -73,34 +77,9 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase
|
||||
Observable.FromEventPattern<ProfileConfigurationEventArgs>(x => profileCategory.ProfileConfigurationRemoved += x, x => profileCategory.ProfileConfigurationRemoved -= x)
|
||||
.Subscribe(e => profileConfigurations.RemoveMany(profileConfigurations.Items.Where(c => c == e.EventArgs.ProfileConfiguration)))
|
||||
.DisposeWith(d);
|
||||
|
||||
profileEditorService.ProfileConfiguration
|
||||
.Subscribe(p => SelectedProfileConfiguration = ProfileConfigurations.FirstOrDefault(c => ReferenceEquals(c.ProfileConfiguration, p)))
|
||||
.DisposeWith(d);
|
||||
|
||||
|
||||
_isCollapsed = ProfileCategory.WhenAnyValue(vm => vm.IsCollapsed).ToProperty(this, vm => vm.IsCollapsed).DisposeWith(d);
|
||||
_isSuspended = ProfileCategory.WhenAnyValue(vm => vm.IsSuspended).ToProperty(this, vm => vm.IsSuspended).DisposeWith(d);
|
||||
|
||||
// Change the current profile configuration when a new one is selected
|
||||
this.WhenAnyValue(vm => vm.SelectedProfileConfiguration)
|
||||
.WhereNotNull()
|
||||
.Subscribe(s =>
|
||||
{
|
||||
try
|
||||
{
|
||||
profileEditorService.ChangeCurrentProfileConfiguration(s.ProfileConfiguration);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (s.ProfileConfiguration.BrokenState != null && s.ProfileConfiguration.BrokenStateException != null)
|
||||
_windowService.ShowExceptionDialog(s.ProfileConfiguration.BrokenState, s.ProfileConfiguration.BrokenStateException);
|
||||
else
|
||||
_windowService.ShowExceptionDialog(e.Message, e);
|
||||
|
||||
profileEditorService.ChangeCurrentProfileConfiguration(null);
|
||||
SelectedProfileConfiguration = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
profileConfigurations.Edit(updater =>
|
||||
@@ -158,7 +137,7 @@ public class SidebarCategoryViewModel : ActivatableViewModelBase
|
||||
if (await _windowService.ShowConfirmContentDialog($"Delete {ProfileCategory.Name}", "Do you want to delete this category and all its profiles?"))
|
||||
{
|
||||
if (ProfileCategory.ProfileConfigurations.Any(c => c.IsBeingEdited))
|
||||
_profileEditorService.ChangeCurrentProfileConfiguration(null);
|
||||
await _router.Navigate("home");
|
||||
_profileService.DeleteProfileCategory(ProfileCategory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Routing;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Newtonsoft.Json;
|
||||
@@ -17,15 +18,15 @@ namespace Artemis.UI.Screens.Sidebar;
|
||||
|
||||
public class SidebarProfileConfigurationViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IRouter _router;
|
||||
private readonly IProfileService _profileService;
|
||||
private readonly IWindowService _windowService;
|
||||
private ObservableAsPropertyHelper<bool>? _isDisabled;
|
||||
|
||||
public SidebarProfileConfigurationViewModel(ProfileConfiguration profileConfiguration, IProfileService profileService, IProfileEditorService profileEditorService, IWindowService windowService)
|
||||
public SidebarProfileConfigurationViewModel(IRouter router, ProfileConfiguration profileConfiguration, IProfileService profileService, IWindowService windowService)
|
||||
{
|
||||
_router = router;
|
||||
_profileService = profileService;
|
||||
_profileEditorService = profileEditorService;
|
||||
_windowService = windowService;
|
||||
|
||||
ProfileConfiguration = profileConfiguration;
|
||||
@@ -98,7 +99,7 @@ public class SidebarProfileConfigurationViewModel : ActivatableViewModelBase
|
||||
return;
|
||||
|
||||
if (ProfileConfiguration.IsBeingEdited)
|
||||
_profileEditorService.ChangeCurrentProfileConfiguration(null);
|
||||
await _router.Navigate("home");
|
||||
_profileService.RemoveProfileConfiguration(ProfileConfiguration);
|
||||
}
|
||||
|
||||
@@ -131,4 +132,9 @@ public class SidebarProfileConfigurationViewModel : ActivatableViewModelBase
|
||||
ProfileConfigurationExportModel export = _profileService.ExportProfile(ProfileConfiguration);
|
||||
_profileService.ImportProfile(ProfileConfiguration.Category, export, true, false, "copy");
|
||||
}
|
||||
|
||||
public bool Matches(string s)
|
||||
{
|
||||
return s.StartsWith("profile-editor") && s.EndsWith(ProfileConfiguration.ProfileId.ToString());
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,25 @@
|
||||
using System;
|
||||
using Artemis.UI.Shared;
|
||||
using DryIoc;
|
||||
using Material.Icons;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Sidebar;
|
||||
|
||||
public class SidebarScreenViewModel<T> : SidebarScreenViewModel where T : MainScreenViewModel
|
||||
public class SidebarScreenViewModel : ViewModelBase
|
||||
{
|
||||
public SidebarScreenViewModel(MaterialIconKind icon, string displayName) : base(icon, displayName)
|
||||
{
|
||||
}
|
||||
|
||||
public override Type ScreenType => typeof(T);
|
||||
|
||||
public override MainScreenViewModel CreateInstance(IContainer container, IScreen screen)
|
||||
{
|
||||
return container.Resolve<T>(new object[] { screen });
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class SidebarScreenViewModel : ViewModelBase
|
||||
{
|
||||
protected SidebarScreenViewModel(MaterialIconKind icon, string displayName)
|
||||
public SidebarScreenViewModel(MaterialIconKind icon, string displayName, string path)
|
||||
{
|
||||
Icon = icon;
|
||||
Path = path;
|
||||
DisplayName = displayName;
|
||||
}
|
||||
|
||||
public MaterialIconKind Icon { get; }
|
||||
public string Path { get; }
|
||||
|
||||
public abstract Type ScreenType { get; }
|
||||
public abstract MainScreenViewModel CreateInstance(IContainer container, IScreen screen);
|
||||
public bool Matches(string? path)
|
||||
{
|
||||
if (path == null)
|
||||
return false;
|
||||
return path.StartsWith(Path, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
}
|
||||
@@ -8,17 +8,12 @@ using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.DryIoc.Factories;
|
||||
using Artemis.UI.Screens.Home;
|
||||
using Artemis.UI.Screens.ProfileEditor;
|
||||
using Artemis.UI.Screens.Settings;
|
||||
using Artemis.UI.Screens.SurfaceEditor;
|
||||
using Artemis.UI.Screens.Workshop;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Routing;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.Builders;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Avalonia.ReactiveUI;
|
||||
using DryIoc;
|
||||
using Avalonia.Threading;
|
||||
using DynamicData;
|
||||
using DynamicData.Binding;
|
||||
using Material.Icons;
|
||||
@@ -28,50 +23,34 @@ namespace Artemis.UI.Screens.Sidebar;
|
||||
|
||||
public class SidebarViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly IScreen _hostScreen;
|
||||
private readonly IContainer _container;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IProfileEditorVmFactory _profileEditorVmFactory;
|
||||
private readonly IRouter _router;
|
||||
private readonly IWindowService _windowService;
|
||||
private SidebarScreenViewModel? _selectedSidebarScreen;
|
||||
private ReadOnlyObservableCollection<SidebarCategoryViewModel> _sidebarCategories = new(new ObservableCollection<SidebarCategoryViewModel>());
|
||||
|
||||
public SidebarViewModel(IScreen hostScreen,
|
||||
IContainer container,
|
||||
IProfileService profileService,
|
||||
IWindowService windowService,
|
||||
IProfileEditorService profileEditorService,
|
||||
ISidebarVmFactory sidebarVmFactory,
|
||||
IProfileEditorVmFactory profileEditorVmFactory)
|
||||
public SidebarViewModel(IRouter router, IProfileService profileService, IWindowService windowService, ISidebarVmFactory sidebarVmFactory)
|
||||
{
|
||||
_hostScreen = hostScreen;
|
||||
_container = container;
|
||||
_router = router;
|
||||
_windowService = windowService;
|
||||
_profileEditorService = profileEditorService;
|
||||
_profileEditorVmFactory = profileEditorVmFactory;
|
||||
|
||||
SidebarScreens = new ObservableCollection<SidebarScreenViewModel>
|
||||
{
|
||||
new SidebarScreenViewModel<HomeViewModel>(MaterialIconKind.Home, "Home"),
|
||||
new(MaterialIconKind.Home, "Home", "home"),
|
||||
#if DEBUG
|
||||
new SidebarScreenViewModel<WorkshopViewModel>(MaterialIconKind.TestTube, "Workshop"),
|
||||
new(MaterialIconKind.TestTube, "Workshop", "workshop"),
|
||||
#endif
|
||||
new SidebarScreenViewModel<SurfaceEditorViewModel>(MaterialIconKind.Devices, "Surface Editor"),
|
||||
new SidebarScreenViewModel<SettingsViewModel>(MaterialIconKind.Cog, "Settings")
|
||||
new(MaterialIconKind.Devices, "Surface Editor", "surface-editor"),
|
||||
new(MaterialIconKind.Cog, "Settings", "settings")
|
||||
};
|
||||
|
||||
AddCategory = ReactiveCommand.CreateFromTask(ExecuteAddCategory);
|
||||
|
||||
SourceList<ProfileCategory> profileCategories = new();
|
||||
|
||||
this.WhenAnyValue(vm => vm.SelectedSidebarScreen).WhereNotNull().Subscribe(NavigateToScreen);
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
this.WhenAnyObservable(vm => vm._hostScreen.Router.CurrentViewModel).WhereNotNull()
|
||||
.Subscribe(c => SelectedSidebarScreen = SidebarScreens.FirstOrDefault(s => s.ScreenType == c.GetType()))
|
||||
.DisposeWith(d);
|
||||
|
||||
this.WhenAnyValue(vm => vm.SelectedSidebarScreen).WhereNotNull().Subscribe(NavigateToScreen);
|
||||
this.WhenAnyObservable(vm => vm._profileEditorService.ProfileConfiguration).Subscribe(NavigateToProfile).DisposeWith(d);
|
||||
_router.CurrentPath.WhereNotNull().Subscribe(r => SelectedSidebarScreen = SidebarScreens.FirstOrDefault(s => s.Matches(r))).DisposeWith(d);
|
||||
|
||||
Observable.FromEventPattern<ProfileCategoryEventArgs>(x => profileService.ProfileCategoryAdded += x, x => profileService.ProfileCategoryAdded -= x)
|
||||
.Subscribe(e => profileCategories.Add(e.EventArgs.ProfileCategory))
|
||||
@@ -127,21 +106,18 @@ public class SidebarViewModel : ActivatableViewModelBase
|
||||
.ShowAsync();
|
||||
}
|
||||
|
||||
private void NavigateToProfile(ProfileConfiguration? 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));
|
||||
}
|
||||
|
||||
private void NavigateToScreen(SidebarScreenViewModel sidebarScreenViewModel)
|
||||
{
|
||||
// If the current screen changed through external means and already matches, don't navigate again
|
||||
if (_hostScreen.Router.GetCurrentViewModel()?.GetType() == sidebarScreenViewModel.ScreenType)
|
||||
return;
|
||||
|
||||
_hostScreen.Router.Navigate.Execute(sidebarScreenViewModel.CreateInstance(_container, _hostScreen));
|
||||
_profileEditorService.ChangeCurrentProfileConfiguration(null);
|
||||
Dispatcher.UIThread.Invoke(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await _router.Navigate(sidebarScreenViewModel.Path, new RouterNavigationOptions {IgnoreOnPartialMatch = true});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_windowService.ShowExceptionDialog("Navigation failed", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user