1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2026-01-02 02:33:32 +00:00
Artemis/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
2024-01-16 09:33:29 +01:00

123 lines
4.8 KiB
C#

using System;
using System.Collections.ObjectModel;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
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 Avalonia.ReactiveUI;
using Avalonia.Threading;
using DynamicData;
using DynamicData.Binding;
using Material.Icons;
using PropertyChanged.SourceGenerator;
using ReactiveUI;
namespace Artemis.UI.Screens.Sidebar;
public partial class SidebarViewModel : ActivatableViewModelBase
{
public const string ROOT_SCREEN = "root";
private readonly IRouter _router;
private readonly IWindowService _windowService;
private bool _updating;
[Notify] private ReadOnlyObservableCollection<SidebarCategoryViewModel> _sidebarCategories = new(new ObservableCollection<SidebarCategoryViewModel>());
[Notify] private SidebarScreenViewModel? _selectedScreen;
public SidebarViewModel(IRouter router, IProfileService profileService, IWindowService windowService, ISidebarVmFactory sidebarVmFactory)
{
_router = router;
_windowService = windowService;
SidebarScreen = new SidebarScreenViewModel(MaterialIconKind.Abacus, ROOT_SCREEN, "", null, new ObservableCollection<SidebarScreenViewModel>()
{
new(MaterialIconKind.HomeOutline, "Home", "home"),
new(MaterialIconKind.TestTube, "Workshop", "workshop", null, new ObservableCollection<SidebarScreenViewModel>
{
new(MaterialIconKind.FolderVideo, "Profiles", "workshop/entries/profiles/1", "workshop/entries/profiles"),
new(MaterialIconKind.KeyboardVariant, "Layouts", "workshop/entries/layouts/1", "workshop/entries/layouts"),
new(MaterialIconKind.Bookshelf, "Library", "workshop/library"),
}),
new(MaterialIconKind.Devices, "Surface Editor", "surface-editor"),
new(MaterialIconKind.SettingsOutline, "Settings", "settings")
});
AddCategory = ReactiveCommand.CreateFromTask(ExecuteAddCategory);
this.WhenAnyValue(vm => vm.SelectedScreen).WhereNotNull().Subscribe(s => SidebarScreen.ExpandIfRequired(s));
SourceList<ProfileCategory> profileCategories = new();
this.WhenActivated(d =>
{
_router.CurrentPath.WhereNotNull().Subscribe(r =>
{
_updating = true;
SelectedScreen = SidebarScreen.GetMatch(r);
_updating = false;
}).DisposeWith(d);
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;
});
}
public SidebarScreenViewModel SidebarScreen { get; }
public ReactiveCommand<Unit, Unit> AddCategory { get; }
private async Task ExecuteAddCategory()
{
await _windowService.CreateContentDialog()
.WithTitle("Add new category")
.WithViewModel(out SidebarCategoryEditViewModel vm, ProfileCategory.Empty)
.HavingPrimaryButton(b => b.WithText("Confirm").WithCommand(vm.Confirm))
.WithCloseButtonText("Cancel")
.WithDefaultButton(ContentDialogButton.Primary)
.ShowAsync();
}
public void NavigateToScreen(SidebarScreenViewModel sidebarScreenViewModel)
{
if (_updating)
return;
Dispatcher.UIThread.Invoke(async () =>
{
try
{
await _router.Navigate(sidebarScreenViewModel.Path);
}
catch (Exception e)
{
_windowService.ShowExceptionDialog("Navigation failed", e);
}
});
}
}