From 3625d1ad1129abe7531a12112278a06cc8bd5ece Mon Sep 17 00:00:00 2001 From: Robert Date: Sat, 30 Jul 2022 21:24:55 +0200 Subject: [PATCH] Plugin settings - Only enable install/uninstall prereqs when applicable Sidebar - Added missing context menu on profiles --- .../Screens/Plugins/PluginView.axaml | 2 +- .../Screens/Plugins/PluginView.axaml.cs | 6 + .../Screens/Plugins/PluginViewModel.cs | 36 +++--- .../Panels/ProfileTree/ProfileTreeView.axaml | 2 +- .../Screens/Sidebar/SidebarCategoryView.axaml | 9 -- .../SidebarProfileConfigurationView.axaml | 45 +++---- .../SidebarProfileConfigurationViewModel.cs | 110 ++++++++++++++++-- 7 files changed, 142 insertions(+), 68 deletions(-) diff --git a/src/Artemis.UI/Screens/Plugins/PluginView.axaml b/src/Artemis.UI/Screens/Plugins/PluginView.axaml index a576743f8..b16c1fd06 100644 --- a/src/Artemis.UI/Screens/Plugins/PluginView.axaml +++ b/src/Artemis.UI/Screens/Plugins/PluginView.axaml @@ -49,7 +49,7 @@ - + diff --git a/src/Artemis.UI/Screens/Plugins/PluginView.axaml.cs b/src/Artemis.UI/Screens/Plugins/PluginView.axaml.cs index 996ff5a97..7c0daa699 100644 --- a/src/Artemis.UI/Screens/Plugins/PluginView.axaml.cs +++ b/src/Artemis.UI/Screens/Plugins/PluginView.axaml.cs @@ -1,3 +1,4 @@ +using System; using Avalonia; using Avalonia.Controls; using Avalonia.Interactivity; @@ -27,4 +28,9 @@ public partial class PluginView : ReactiveUserControl { Dispatcher.UIThread.Post(() => ViewModel?.UpdateEnabled(!ViewModel.Plugin.IsEnabled)); } + + private void FlyoutBase_OnOpening(object? sender, EventArgs e) + { + ViewModel?.CheckPrerequisites(); + } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Plugins/PluginViewModel.cs b/src/Artemis.UI/Screens/Plugins/PluginViewModel.cs index 74904abe1..0206edf30 100644 --- a/src/Artemis.UI/Screens/Plugins/PluginViewModel.cs +++ b/src/Artemis.UI/Screens/Plugins/PluginViewModel.cs @@ -28,14 +28,13 @@ public class PluginViewModel : ActivatableViewModelBase private bool _canInstallPrerequisites; private bool _canRemovePrerequisites; private bool _enabling; - private bool _isSettingsPopupOpen; private Plugin _plugin; private Window? _window; - public PluginViewModel(Plugin plugin, - ReactiveCommand? reload, - ICoreService coreService, - IWindowService windowService, + public PluginViewModel(Plugin plugin, + ReactiveCommand? reload, + ICoreService coreService, + IWindowService windowService, INotificationService notificationService, IPluginManagementService pluginManagementService) { @@ -105,16 +104,6 @@ public class PluginViewModel : ActivatableViewModelBase public string Type => Plugin.GetType().BaseType?.Name ?? Plugin.GetType().Name; public bool IsEnabled => Plugin.IsEnabled; - public bool IsSettingsPopupOpen - { - get => _isSettingsPopupOpen; - set - { - if (!RaiseAndSetIfChanged(ref _isSettingsPopupOpen, value)) return; - CheckPrerequisites(); - } - } - public bool CanInstallPrerequisites { get => _canInstallPrerequisites; @@ -166,7 +155,7 @@ public class PluginViewModel : ActivatableViewModelBase _windowService.ShowExceptionDialog("Welp, we couldn't open the device's plugin folder for you", e); } } - + private async Task ExecuteInstallPrerequisites() { List subjects = new() {Plugin.Info}; @@ -309,12 +298,17 @@ public class PluginViewModel : ActivatableViewModelBase } - private void CheckPrerequisites() + public void CheckPrerequisites() { - CanInstallPrerequisites = Plugin.Info.PlatformPrerequisites.Any() || - Plugin.Features.Where(f => f.AlwaysEnabled).Any(f => f.PlatformPrerequisites.Any()); - CanRemovePrerequisites = Plugin.Info.PlatformPrerequisites.Any(p => p.UninstallActions.Any()) || - Plugin.Features.Where(f => f.AlwaysEnabled).Any(f => f.PlatformPrerequisites.Any(p => p.UninstallActions.Any())); + CanInstallPrerequisites = false; + CanRemovePrerequisites = false; + + Dispatcher.UIThread.Post(() => + { + CanInstallPrerequisites = !Plugin.Info.ArePrerequisitesMet() || Plugin.Features.Where(f => f.AlwaysEnabled).Any(f => !f.ArePrerequisitesMet()); + CanRemovePrerequisites = Plugin.Info.PlatformPrerequisites.Any(p => p.IsMet() && p.UninstallActions.Any()) || + Plugin.Features.Where(f => f.AlwaysEnabled).Any(f => f.PlatformPrerequisites.Any(p => p.IsMet() && p.UninstallActions.Any())); + }); } private void OnPluginToggled(object? sender, EventArgs e) diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml index 285501a8e..9164c768b 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml @@ -101,7 +101,7 @@ - + diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarCategoryView.axaml b/src/Artemis.UI/Screens/Sidebar/SidebarCategoryView.axaml index d375f623b..870a4b5a0 100644 --- a/src/Artemis.UI/Screens/Sidebar/SidebarCategoryView.axaml +++ b/src/Artemis.UI/Screens/Sidebar/SidebarCategoryView.axaml @@ -171,15 +171,6 @@ MinHeight="10" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled"> - - - - - - - - - diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationView.axaml b/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationView.axaml index 72953939d..94e2f3032 100644 --- a/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationView.axaml +++ b/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationView.axaml @@ -8,65 +8,56 @@ xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Artemis.UI.Screens.Sidebar.SidebarProfileConfigurationView" - x:DataType="sidebar:SidebarProfileConfigurationViewModel"> + x:DataType="sidebar:SidebarProfileConfigurationViewModel" + Background="Transparent"> - - - + + + - + - + - - + + - - + + - - + + - + - - - - - - - - - - - - + + - - + + ? _isSuspended; public ProfileConfiguration ProfileConfiguration { get; } - public SidebarProfileConfigurationViewModel(SidebarViewModel sidebarViewModel, ProfileConfiguration profileConfiguration, IProfileService profileService, IWindowService windowService) + public SidebarProfileConfigurationViewModel(SidebarViewModel sidebarViewModel, + ProfileConfiguration profileConfiguration, + IProfileService profileService, + IProfileEditorService profileEditorService, + IWindowService windowService) { _sidebarViewModel = sidebarViewModel; _profileService = profileService; + _profileEditorService = profileEditorService; _windowService = windowService; ProfileConfiguration = profileConfiguration; EditProfile = ReactiveCommand.CreateFromTask(ExecuteEditProfile); ToggleSuspended = ReactiveCommand.Create(ExecuteToggleSuspended); + ResumeAll = ReactiveCommand.Create(ExecuteResumeAll); + SuspendAll = ReactiveCommand.Create(ExecuteSuspendAll); + DeleteProfile = ReactiveCommand.CreateFromTask(ExecuteDeleteProfile); + ExportProfile = ReactiveCommand.CreateFromTask(ExecuteExportProfile); + DuplicateProfile = ReactiveCommand.Create(ExecuteDuplicateProfile); - this.WhenActivated(d => - { - _isSuspended = ProfileConfiguration.WhenAnyValue(c => c.IsSuspended).ToProperty(this, vm => vm.IsSuspended).DisposeWith(d); - }); + this.WhenActivated(d => { _isSuspended = ProfileConfiguration.WhenAnyValue(c => c.IsSuspended).ToProperty(this, vm => vm.IsSuspended).DisposeWith(d); }); _profileService.LoadProfileConfigurationIcon(ProfileConfiguration); } - + public ReactiveCommand EditProfile { get; } - public ReactiveCommand ToggleSuspended { get; } + public ReactiveCommand ToggleSuspended { get; } + public ReactiveCommand ResumeAll { get; } + public ReactiveCommand SuspendAll { get; } + public ReactiveCommand DeleteProfile { get; } + public ReactiveCommand ExportProfile { get; } + public ReactiveCommand DuplicateProfile { get; } public bool IsSuspended => _isSuspended?.Value ?? false; @@ -51,11 +69,85 @@ namespace Artemis.UI.Screens.Sidebar if (edited != null) _sidebarViewModel.UpdateProfileCategories(); } - + private void ExecuteToggleSuspended() { ProfileConfiguration.IsSuspended = !ProfileConfiguration.IsSuspended; _profileService.SaveProfileCategory(ProfileConfiguration.Category); } + + private void ExecuteResumeAll(string direction) + { + int index = ProfileConfiguration.Category.ProfileConfigurations.IndexOf(ProfileConfiguration); + if (direction == "above") + { + for (int i = 0; i < index; i++) + ProfileConfiguration.Category.ProfileConfigurations[i].IsSuspended = false; + } + else + { + for (int i = index + 1; i < ProfileConfiguration.Category.ProfileConfigurations.Count; i++) + ProfileConfiguration.Category.ProfileConfigurations[i].IsSuspended = false; + } + + _profileService.SaveProfileCategory(ProfileConfiguration.Category); + } + + private void ExecuteSuspendAll(string direction) + { + int index = ProfileConfiguration.Category.ProfileConfigurations.IndexOf(ProfileConfiguration); + if (direction == "above") + { + for (int i = 0; i < index; i++) + ProfileConfiguration.Category.ProfileConfigurations[i].IsSuspended = true; + } + else + { + for (int i = index + 1; i < ProfileConfiguration.Category.ProfileConfigurations.Count; i++) + ProfileConfiguration.Category.ProfileConfigurations[i].IsSuspended = true; + } + + _profileService.SaveProfileCategory(ProfileConfiguration.Category); + } + + private async Task ExecuteDeleteProfile() + { + if (!await _windowService.ShowConfirmContentDialog("Delete profile", "Are you sure you want to permanently delete this profile?")) + return; + + if (ProfileConfiguration.IsBeingEdited) + _profileEditorService.ChangeCurrentProfileConfiguration(null); + _profileService.RemoveProfileConfiguration(ProfileConfiguration); + } + + private async Task ExecuteExportProfile() + { + // Might not cover everything but then the dialog will complain and that's good enough + string fileName = Path.GetInvalidFileNameChars().Aggregate(ProfileConfiguration.Name, (current, c) => current.Replace(c, '-')); + string? result = await _windowService.CreateSaveFileDialog() + .HavingFilter(f => f.WithExtension("json").WithName("Artemis profile")) + .WithInitialFileName(fileName) + .ShowAsync(); + + if (result == null) + return; + + ProfileConfigurationExportModel export = _profileService.ExportProfile(ProfileConfiguration); + string json = JsonConvert.SerializeObject(export, IProfileService.ExportSettings); + try + { + await File.WriteAllTextAsync(result, json); + } + catch (Exception e) + { + _windowService.ShowExceptionDialog("Failed to export profile", e); + } + } + + private void ExecuteDuplicateProfile() + { + ProfileConfigurationExportModel export = _profileService.ExportProfile(ProfileConfiguration); + _profileService.ImportProfile(ProfileConfiguration.Category, export, true, false, "copy"); + } } } \ No newline at end of file