1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-12 13:28:33 +00:00

Compare commits

...

2 Commits

Author SHA1 Message Date
Robert
108cbaae3d Replace profile-from-workshop-dialog with a page 2025-12-10 23:06:14 +01:00
Robert
638dbd11eb Revert regrets 2025-12-09 20:57:51 +01:00
18 changed files with 216 additions and 60 deletions

View File

@ -103,7 +103,9 @@ internal class Router : CorePropertyChanged, IRouter, IDisposable
{
if (_root == null)
throw new ArtemisRoutingException("Cannot navigate without a root having been set");
if (PathEquals(path, options) || (_currentNavigation != null && _currentNavigation.PathEquals(path, options)))
// If navigating to the same path, don't do anything
if ((_currentNavigation == null && PathEquals(path, options)) || (_currentNavigation != null && _currentNavigation.PathEquals(path, options)))
return;
string? previousPath = _currentRouteSubject.Value;
@ -128,12 +130,8 @@ internal class Router : CorePropertyChanged, IRouter, IDisposable
await navigation.Navigate(args);
// If it was cancelled before completion, don't add it to history or update the current path
// Do reload the current path because it may have been partially navigated away from
if (navigation.Cancelled)
{
await Reload();
return;
}
if (options.AddToHistory && previousPath != null)
{

View File

@ -11,12 +11,15 @@ using Artemis.UI.Screens.Device.Leds;
using Artemis.UI.Screens.Plugins;
using Artemis.UI.Screens.Plugins.Features;
using Artemis.UI.Screens.Plugins.Prerequisites;
using Artemis.UI.Screens.ProfileEditor;
using Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
using Artemis.UI.Screens.ProfileEditor.ProfileTree;
using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
using Artemis.UI.Screens.ProfileEditor.Properties;
using Artemis.UI.Screens.ProfileEditor.Properties.DataBinding;
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline;
using Artemis.UI.Screens.ProfileEditor.Properties.Tree;
using Artemis.UI.Screens.ProfileEditor.VisualEditor.Visualizers;
using Artemis.UI.Screens.Settings;
using Artemis.UI.Screens.Settings.Updating;
using Artemis.UI.Screens.Sidebar;
@ -26,14 +29,6 @@ using Artemis.UI.Screens.VisualScripting.Pins;
using Artemis.WebClient.Updating;
using DryIoc;
using ReactiveUI;
using LayerShapeVisualizerViewModel = Artemis.UI.Screens.ProfileEditor.VisualEditor.Visualizers.LayerShapeVisualizerViewModel;
using LayerVisualizerViewModel = Artemis.UI.Screens.ProfileEditor.VisualEditor.Visualizers.LayerVisualizerViewModel;
using ProfileEditorViewModel = Artemis.UI.Screens.ProfileEditor.ProfileEditorViewModel;
using PropertyGroupViewModel = Artemis.UI.Screens.ProfileEditor.Properties.PropertyGroupViewModel;
using PropertyViewModel = Artemis.UI.Screens.ProfileEditor.Properties.PropertyViewModel;
using SingleLedAdaptionHintViewModel = Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints.SingleLedAdaptionHintViewModel;
using TimelineGroupViewModel = Artemis.UI.Screens.ProfileEditor.Properties.Timeline.TimelineGroupViewModel;
using TreeItemViewModel = Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItemViewModel;
namespace Artemis.UI.DryIoc.Factories;

View File

@ -2,13 +2,10 @@
using Artemis.Core;
using Artemis.UI.DryIoc.Factories;
using Artemis.UI.Exceptions;
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline;
using Artemis.UI.Screens.ProfileEditor.Properties.Tree;
using Artemis.UI.Screens.ProfileEditor.Properties;
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline;
using Artemis.UI.Screens.ProfileEditor.Properties.Tree;
using DryIoc;
using PropertyViewModel = Artemis.UI.Screens.ProfileEditor.Properties.PropertyViewModel;
namespace Artemis.UI.DryIoc.InstanceProviders;

View File

@ -15,8 +15,6 @@ using Artemis.UI.Screens.Workshop.Library.Tabs;
using Artemis.UI.Screens.Workshop.Plugins;
using Artemis.UI.Screens.Workshop.Profile;
using Artemis.UI.Shared.Routing;
using PluginDetailsViewModel = Artemis.UI.Screens.Workshop.Plugins.PluginDetailsViewModel;
using ProfileEditorViewModel = Artemis.UI.Screens.ProfileEditor.ProfileEditorViewModel;
namespace Artemis.UI.Routing
{
@ -66,7 +64,10 @@ namespace Artemis.UI.Routing
new RouteRegistration<AccountTabViewModel>("account"),
new RouteRegistration<AboutTabViewModel>("about")
]),
new RouteRegistration<ProfileEditorViewModel>("profile-editor/{profileConfigurationId:guid}")
new RouteRegistration<ProfileViewModel>("profile/{profileConfigurationId:guid}", [
new RouteRegistration<ProfileEditorViewModel>("editor"),
new RouteRegistration<WorkshopProfileViewModel>("workshop")
]),
];
}
}

View File

@ -15,11 +15,8 @@ using Artemis.UI.Screens.ProfileEditor.StatusBar;
using Artemis.UI.Screens.ProfileEditor.VisualEditor;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.MainWindow;
using Artemis.UI.Shared.Services.ProfileEditor;
using Artemis.WebClient.Workshop.Models;
using Artemis.WebClient.Workshop.Services;
using DynamicData;
using DynamicData.Binding;
using PropertyChanged.SourceGenerator;
@ -27,14 +24,12 @@ using ReactiveUI;
namespace Artemis.UI.Screens.ProfileEditor;
public partial class ProfileEditorViewModel : RoutableScreen<ProfileEditorViewModelParameters>, IMainScreenViewModel
public partial class ProfileEditorViewModel : RoutableScreen<ProfileViewModelParameters>, IMainScreenViewModel
{
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileService _profileService;
private readonly ISettingsService _settingsService;
private readonly IMainWindowService _mainWindowService;
private readonly IWorkshopService _workshopService;
private readonly IWindowService _windowService;
private readonly SourceList<IToolViewModel> _tools;
private ObservableAsPropertyHelper<ProfileEditorHistory?>? _history;
private ObservableAsPropertyHelper<bool>? _suspendedEditing;
@ -53,16 +48,12 @@ public partial class ProfileEditorViewModel : RoutableScreen<ProfileEditorViewMo
StatusBarViewModel statusBarViewModel,
IEnumerable<IToolViewModel> toolViewModels,
IMainWindowService mainWindowService,
IInputService inputService,
IWorkshopService workshopService,
IWindowService windowService)
IInputService inputService)
{
_profileService = profileService;
_profileEditorService = profileEditorService;
_settingsService = settingsService;
_mainWindowService = mainWindowService;
_workshopService = workshopService;
_windowService = windowService;
_tools = new SourceList<IToolViewModel>();
_tools.AddRange(toolViewModels);
@ -75,6 +66,7 @@ public partial class ProfileEditorViewModel : RoutableScreen<ProfileEditorViewMo
Tools = tools;
visualEditorViewModel.SetTools(_tools);
ParameterSource = ParameterSource.Route;
StatusBarViewModel = statusBarViewModel;
VisualEditorViewModel = visualEditorViewModel;
ProfileTreeViewModel = profileTreeViewModel;
@ -193,7 +185,7 @@ public partial class ProfileEditorViewModel : RoutableScreen<ProfileEditorViewMo
#region Overrides of RoutableScreen<object,ProfileEditorViewModelParameters>
/// <inheritdoc />
public override async Task OnNavigating(ProfileEditorViewModelParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
public override async Task OnNavigating(ProfileViewModelParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
{
ProfileConfiguration? profileConfiguration = _profileService.ProfileCategories.SelectMany(c => c.ProfileConfigurations).FirstOrDefault(c => c.ProfileId == parameters.ProfileId);
@ -204,23 +196,6 @@ public partial class ProfileEditorViewModel : RoutableScreen<ProfileEditorViewMo
return;
}
// If the profile is from the workshop, warn the user that auto-updates will be disabled
InstalledEntry? workshopEntry = _workshopService.GetInstalledEntryByProfile(profileConfiguration);
if (workshopEntry != null && workshopEntry.AutoUpdate)
{
bool confirmed = await _windowService.ShowConfirmContentDialog(
"Editing a workshop profile",
"You are about to edit a profile from the workshop, to preserve your changes auto-updating will be disabled.",
"Disable auto-update");
if (confirmed)
_workshopService.SetAutoUpdate(workshopEntry, false);
else
{
args.Cancel();
return;
}
}
await _profileEditorService.ChangeCurrentProfileConfiguration(profileConfiguration);
ProfileConfiguration = profileConfiguration;
}
@ -237,8 +212,3 @@ public partial class ProfileEditorViewModel : RoutableScreen<ProfileEditorViewMo
#endregion
}
public class ProfileEditorViewModelParameters
{
public Guid ProfileId { get; set; }
}

View File

@ -0,0 +1,14 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:ui="clr-namespace:Artemis.UI"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileView">
<controls:Frame Name="RouterFrame" IsNavigationStackEnabled="False" CacheSize="0">
<controls:Frame.NavigationPageFactory>
<ui:PageFactory/>
</controls:Frame.NavigationPageFactory>
</controls:Frame>
</UserControl>

View File

@ -0,0 +1,19 @@
using System;
using System.Reactive.Disposables;
using Artemis.UI.Shared.Routing;
using Avalonia.ReactiveUI;
using Avalonia.Threading;
using ReactiveUI;
namespace Artemis.UI.Screens.ProfileEditor;
public partial class ProfileView : ReactiveUserControl<ProfileViewModel>
{
public ProfileView()
{
InitializeComponent();
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Screen)
.WhereNotNull()
.Subscribe(screen => RouterFrame.NavigateFromObject(screen))
.DisposeWith(d));
}
}

View File

@ -0,0 +1,62 @@
using System;
using System.Linq;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing;
using Artemis.WebClient.Workshop.Models;
using Artemis.WebClient.Workshop.Services;
using ReactiveUI;
namespace Artemis.UI.Screens.ProfileEditor;
public class ProfileViewModel : RoutableHostScreen<RoutableScreen, ProfileViewModelParameters>, IMainScreenViewModel
{
private readonly IProfileService _profileService;
private readonly IWorkshopService _workshopService;
private readonly ObservableAsPropertyHelper<ViewModelBase?> _titleBarViewModel;
public ProfileViewModel(IProfileService profileService, IWorkshopService workshopService)
{
_profileService = profileService;
_workshopService = workshopService;
_titleBarViewModel = this.WhenAnyValue(vm => vm.Screen).Select(screen => screen as IMainScreenViewModel)
.Select(mainScreen => mainScreen?.TitleBarViewModel)
.ToProperty(this, vm => vm.TitleBarViewModel);
}
public ViewModelBase? TitleBarViewModel => _titleBarViewModel.Value;
/// <inheritdoc />
public override async Task OnNavigating(ProfileViewModelParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
{
ProfileConfiguration? profileConfiguration = _profileService.ProfileCategories.SelectMany(c => c.ProfileConfigurations).FirstOrDefault(c => c.ProfileId == parameters.ProfileId);
// If the profile doesn't exist, cancel navigation
if (profileConfiguration == null)
{
args.Cancel();
return;
}
// If the profile is from the workshop, redirect to the workshop page
InstalledEntry? workshopEntry = _workshopService.GetInstalledEntryByProfile(profileConfiguration);
if (workshopEntry != null && workshopEntry.AutoUpdate)
{
if (!args.Path.EndsWith("workshop"))
await args.Router.Navigate($"profile/{parameters.ProfileId}/workshop");
}
// Otherwise, show the profile editor if not already on the editor page
else if (!args.Path.EndsWith("editor"))
await args.Router.Navigate($"profile/{parameters.ProfileId}/editor");
}
}
public class ProfileViewModelParameters
{
public Guid ProfileId { get; set; }
}

View File

@ -0,0 +1,23 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:profileEditor="clr-namespace:Artemis.UI.Screens.ProfileEditor"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.WorkshopProfileView"
x:DataType="profileEditor:WorkshopProfileViewModel">
<Border Classes="router-container">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Vertical" Spacing="10" MaxWidth="800">
<ContentControl Content="{CompiledBinding EntryViewModel}"></ContentControl>
<TextBlock TextWrapping="Wrap">
The profile you're opening is a workshop profile.
</TextBlock>
<TextBlock TextWrapping="Wrap">
You cannot make change to it without disabling auto-update, as any updates to the profile on the workshop would override your own modifications.
</TextBlock>
<Button Command="{CompiledBinding DisableAutoUpdate}" Classes="accent">Disable auto-update</Button>
</StackPanel>
</Border>
</UserControl>

View File

@ -0,0 +1,11 @@
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.ProfileEditor;
public partial class WorkshopProfileView : ReactiveUserControl<WorkshopProfileViewModel>
{
public WorkshopProfileView()
{
InitializeComponent();
}
}

View File

@ -0,0 +1,65 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Screens.Workshop.Library.Tabs;
using Artemis.UI.Shared.Routing;
using Artemis.WebClient.Workshop.Models;
using Artemis.WebClient.Workshop.Services;
using PropertyChanged.SourceGenerator;
namespace Artemis.UI.Screens.ProfileEditor;
public partial class WorkshopProfileViewModel : RoutableScreen<ProfileViewModelParameters>
{
private readonly IProfileService _profileService;
private readonly IWorkshopService _workshopService;
private readonly IRouter _router;
private readonly Func<InstalledEntry, InstalledTabItemViewModel> _getInstalledTabItemViewModel;
[Notify] private ProfileConfiguration? _profileConfiguration;
[Notify] private InstalledEntry? _workshopEntry;
[Notify] private InstalledTabItemViewModel? _entryViewModel;
public WorkshopProfileViewModel(IProfileService profileService, IWorkshopService workshopService, IRouter router, Func<InstalledEntry, InstalledTabItemViewModel> getInstalledTabItemViewModel)
{
_profileService = profileService;
_workshopService = workshopService;
_router = router;
_getInstalledTabItemViewModel = getInstalledTabItemViewModel;
ParameterSource = ParameterSource.Route;
}
public async Task DisableAutoUpdate()
{
if (WorkshopEntry != null)
{
_workshopService.SetAutoUpdate(WorkshopEntry, false);
}
if (ProfileConfiguration != null)
{
await _router.Navigate($"profile/{ProfileConfiguration.ProfileId}/editor");
}
}
public override Task OnNavigating(ProfileViewModelParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
{
ProfileConfiguration = _profileService.ProfileCategories.SelectMany(c => c.ProfileConfigurations).FirstOrDefault(c => c.ProfileId == parameters.ProfileId);
// If the profile doesn't exist, cancel navigation
if (ProfileConfiguration == null)
{
args.Cancel();
return Task.CompletedTask;
}
WorkshopEntry = _workshopService.GetInstalledEntryByProfile(ProfileConfiguration);
EntryViewModel = WorkshopEntry != null ? _getInstalledTabItemViewModel(WorkshopEntry) : null;
if (EntryViewModel != null)
EntryViewModel.DisplayManagement = false;
return Task.CompletedTask;
}
}

View File

@ -65,7 +65,7 @@ public partial class SidebarCategoryViewModel : ActivatableViewModelBase
// 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}))
.Subscribe(s => _router.Navigate($"profile/{s.ProfileConfiguration.ProfileId}/editor", new RouterNavigationOptions {IgnoreOnPartialMatch = true, RecycleScreens = false}))
.DisposeWith(d);
_router.CurrentPath.WhereNotNull().Subscribe(r => SelectedProfileConfiguration = ProfileConfigurations.FirstOrDefault(c => c.Matches(r))).DisposeWith(d);

View File

@ -132,6 +132,6 @@ public class SidebarProfileConfigurationViewModel : ActivatableViewModelBase
public bool Matches(string s)
{
return s.StartsWith("profile-editor") && s.EndsWith(ProfileConfiguration.ProfileId.ToString());
return s == $"profile/{ProfileConfiguration.ProfileId}/editor";
}
}

View File

@ -71,6 +71,9 @@ public partial class DefaultEntryItemViewModel : ActivatableViewModelBase
else if (result.Entry?.EntryType == EntryType.Plugin)
{
await EnablePluginAndFeatures(result.Entry);
} else if (result.Entry?.EntryType == EntryType.Profile)
{
}
return result.IsSuccess;

View File

@ -92,7 +92,7 @@
</StackPanel>
<!-- Management -->
<Border Grid.Column="3" Grid.Row="0" Grid.RowSpan="2" BorderBrush="{DynamicResource ButtonBorderBrush}" BorderThickness="1 0 0 0" Margin="10 0 0 0" Padding="10 0 0 0">
<Border Grid.Column="3" Grid.Row="0" Grid.RowSpan="2" BorderBrush="{DynamicResource ButtonBorderBrush}" BorderThickness="1 0 0 0" Margin="10 0 0 0" Padding="10 0 0 0" IsVisible="{CompiledBinding DisplayManagement}">
<StackPanel VerticalAlignment="Center">
<StackPanel Orientation="Horizontal" Spacing="5">
<Button Command="{CompiledBinding ViewLocal}" HorizontalAlignment="Stretch" >Open</Button>

View File

@ -35,6 +35,7 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
[Notify] private bool _updateAvailable;
[Notify] private bool _autoUpdate;
[Notify] private bool _displayManagement = true;
public InstalledTabItemViewModel(InstalledEntry entry,
IWorkshopClient client,
@ -87,7 +88,7 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
public async Task ViewLocal()
{
if (Entry.EntryType == EntryType.Profile && Entry.TryGetMetadata("ProfileId", out Guid profileId))
await _router.Navigate($"profile-editor/{profileId}");
await _router.Navigate($"profile/{profileId}/editor");
else if (Entry.EntryType == EntryType.Plugin)
await _router.Navigate($"workshop/entries/plugins/details/{Entry.Id}/manage");
else if (Entry.EntryType == EntryType.Layout)

View File

@ -4,7 +4,6 @@ using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs;
using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using PropertyChanged.SourceGenerator;

View File

@ -7,8 +7,6 @@ using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs;
using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs;
using Artemis.UI.Screens.Workshop.SubmissionWizard.Models;
using Artemis.UI.Shared.Services;
using Artemis.WebClient.Workshop.Handlers.UploadHandlers;
using DynamicData;