1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Plugin settings - Only enable install/uninstall prereqs when applicable

Sidebar - Added missing context menu on profiles
This commit is contained in:
Robert 2022-07-30 21:24:55 +02:00
parent 45e810c3ac
commit 3625d1ad11
7 changed files with 142 additions and 68 deletions

View File

@ -49,7 +49,7 @@
<StackPanel Orientation="Horizontal">
<controls:SplitButton Content="Settings" Command="{CompiledBinding OpenSettings}">
<controls:SplitButton.Flyout>
<MenuFlyout Placement="Bottom" IsOpen="{CompiledBinding IsSettingsPopupOpen, Mode=OneWayToSource}">
<MenuFlyout Placement="Bottom" Opening="FlyoutBase_OnOpening">
<MenuItem Header="Open plugin directory" Command="{CompiledBinding OpenPluginDirectory}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="FolderOpen" />

View File

@ -1,3 +1,4 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
@ -27,4 +28,9 @@ public partial class PluginView : ReactiveUserControl<PluginViewModel>
{
Dispatcher.UIThread.Post(() => ViewModel?.UpdateEnabled(!ViewModel.Plugin.IsEnabled));
}
private void FlyoutBase_OnOpening(object? sender, EventArgs e)
{
ViewModel?.CheckPrerequisites();
}
}

View File

@ -28,7 +28,6 @@ public class PluginViewModel : ActivatableViewModelBase
private bool _canInstallPrerequisites;
private bool _canRemovePrerequisites;
private bool _enabling;
private bool _isSettingsPopupOpen;
private Plugin _plugin;
private Window? _window;
@ -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;
@ -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)

View File

@ -101,7 +101,7 @@
</TreeView.Styles>
<TreeView.ItemTemplate>
<TreeDataTemplate ItemsSource="{Binding Children}">
<ContentControl Content="{Binding}" x:DataType="profileTree:TreeItemViewModel">
<ContentControl Content="{Binding}" x:DataType="profileTree:TreeItemViewModel" Background="Transparent">
<ContentControl.ContextFlyout>
<MenuFlyout IsOpen="{CompiledBinding IsFlyoutOpen, Mode=OneWayToSource}">
<MenuItem Header="Add new folder" Command="{CompiledBinding AddFolder}">

View File

@ -171,15 +171,6 @@
MinHeight="10"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Paste">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="ContentPaste" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
</Border>
</Grid>

View File

@ -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">
<UserControl.Resources>
<converters:ValuesAdditionConverter x:Key="ValuesAddition" />
</UserControl.Resources>
<UserControl.ContextMenu>
<ContextMenu>
<MenuItem Header="View properties">
<UserControl.ContextFlyout>
<MenuFlyout>
<MenuItem Header="View properties" Command="{CompiledBinding EditProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Cog" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Suspend">
<MenuItem Header="Suspend" Command="{CompiledBinding ToggleSuspended}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Pause" />
<avalonia:MaterialIcon Kind="Check" IsVisible="{CompiledBinding IsSuspended}" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Suspend all">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Pause" />
</MenuItem.Icon>
<MenuItem Header="Above" CommandParameter="suspend" />
<MenuItem Header="Below" CommandParameter="suspend" />
<MenuItem Header="Above" Command="{CompiledBinding SuspendAll}" CommandParameter="above" />
<MenuItem Header="Below" Command="{CompiledBinding SuspendAll}" CommandParameter="below" />
</MenuItem>
<MenuItem Header="Resume all">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Play" />
</MenuItem.Icon>
<MenuItem Header="Above" CommandParameter="resume" />
<MenuItem Header="Below" CommandParameter="resume" />
<MenuItem Header="Above" Command="{CompiledBinding ResumeAll}" CommandParameter="above" />
<MenuItem Header="Below" Command="{CompiledBinding ResumeAll}" CommandParameter="below" />
</MenuItem>
<Separator />
<MenuItem Header="Export">
<MenuItem Header="-" />
<MenuItem Header="Export" Command="{CompiledBinding ExportProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Export" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Duplicate">
<MenuItem Header="Duplicate" Command="{CompiledBinding DuplicateProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="ContentDuplicate" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Copy">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="ContentCopy" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Paste">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="ContentPaste" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="Delete">
<MenuItem Header="-" />
<MenuItem Header="Delete" Command="{CompiledBinding DeleteProfile}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="Trash" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</UserControl.ContextMenu>
</MenuFlyout>
</UserControl.ContextFlyout>
<Grid ColumnDefinitions="Auto,*,Auto,Auto">
<shared:ProfileConfigurationIcon Grid.Column="0"
x:Name="ProfileIcon"

View File

@ -1,4 +1,7 @@
using System.Reactive;
using System;
using System.IO;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
@ -6,6 +9,8 @@ using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.ProfileEditor;
using Newtonsoft.Json;
using ReactiveUI;
namespace Artemis.UI.Screens.Sidebar
@ -14,30 +19,43 @@ namespace Artemis.UI.Screens.Sidebar
{
private readonly SidebarViewModel _sidebarViewModel;
private readonly IProfileService _profileService;
private readonly IProfileEditorService _profileEditorService;
private readonly IWindowService _windowService;
private ObservableAsPropertyHelper<bool>? _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<string>(ExecuteResumeAll);
SuspendAll = ReactiveCommand.Create<string>(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<Unit, Unit> EditProfile { get; }
public ReactiveCommand<Unit,Unit> ToggleSuspended { get; }
public ReactiveCommand<Unit, Unit> ToggleSuspended { get; }
public ReactiveCommand<string, Unit> ResumeAll { get; }
public ReactiveCommand<string, Unit> SuspendAll { get; }
public ReactiveCommand<Unit, Unit> DeleteProfile { get; }
public ReactiveCommand<Unit, Unit> ExportProfile { get; }
public ReactiveCommand<Unit, Unit> DuplicateProfile { get; }
public bool IsSuspended => _isSuspended?.Value ?? false;
@ -57,5 +75,79 @@ namespace Artemis.UI.Screens.Sidebar
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");
}
}
}