mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 03:48:56 +00:00
Profiles - Added module activation requirements
Editor - Refactored tools and selected keyframes management Timeline - Added keyframe duplicating, copying and pasting Windows UI - Added logging of fatal exceptions
This commit is contained in:
1 parent
d563d17270
commit
dd40bdd544
31 files changed
+719
-178
No files matched your search
@@ -0,0 +1,42 @@
|
||||
<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:sidebar="clr-namespace:Artemis.UI.Screens.Sidebar"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Sidebar.ModuleActivationRequirementView"
|
||||
x:DataType="sidebar:ModuleActivationRequirementViewModel">
|
||||
<UserControl.Styles>
|
||||
<Styles>
|
||||
<Style Selector="Border.status-border">
|
||||
<Setter Property="Width" Value="32" />
|
||||
<Setter Property="Height" Value="32" />
|
||||
<Setter Property="CornerRadius" Value="16" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="Border.status-border avalonia|MaterialIcon">
|
||||
<Setter Property="Width" Value="16" />
|
||||
<Setter Property="Height" Value="16" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</Styles>
|
||||
</UserControl.Styles>
|
||||
<StackPanel>
|
||||
<Separator Classes="card-separator" />
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding RequirementName}" />
|
||||
<TextBlock Classes="subtitle" TextWrapping="Wrap" Text="{CompiledBinding RequirementDescription}" />
|
||||
</StackPanel>
|
||||
|
||||
<Border Grid.Row="0" Grid.Column="1" Classes="status-border" IsVisible="{CompiledBinding !RequirementMet}" Background="#ff3838">
|
||||
<avalonia:MaterialIcon Kind="Close" />
|
||||
</Border>
|
||||
<Border Grid.Row="0" Grid.Column="1" Classes="status-border" IsVisible="{CompiledBinding RequirementMet}" Background="#32a852">
|
||||
<avalonia:MaterialIcon Kind="Check" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,17 @@
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Sidebar;
|
||||
|
||||
public class ModuleActivationRequirementView : ReactiveUserControl<ModuleActivationRequirementViewModel>
|
||||
{
|
||||
public ModuleActivationRequirementView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using Artemis.Core.Modules;
|
||||
using Artemis.UI.Shared;
|
||||
using Avalonia.Threading;
|
||||
using Humanizer;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Sidebar;
|
||||
|
||||
public class ModuleActivationRequirementViewModel : ActivatableViewModelBase
|
||||
{
|
||||
private readonly IModuleActivationRequirement _activationRequirement;
|
||||
private string _requirementDescription;
|
||||
private bool _requirementMet;
|
||||
private DispatcherTimer? _updateTimer;
|
||||
|
||||
public ModuleActivationRequirementViewModel(IModuleActivationRequirement activationRequirement)
|
||||
{
|
||||
RequirementName = activationRequirement.GetType().Name.Humanize();
|
||||
_requirementDescription = activationRequirement.GetUserFriendlyDescription();
|
||||
_activationRequirement = activationRequirement;
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
_updateTimer = new DispatcherTimer(TimeSpan.FromMilliseconds(500), DispatcherPriority.Normal, Update);
|
||||
_updateTimer.Start();
|
||||
|
||||
Disposable.Create(() =>
|
||||
{
|
||||
_updateTimer?.Stop();
|
||||
_updateTimer = null;
|
||||
}).DisposeWith(d);
|
||||
});
|
||||
}
|
||||
|
||||
public string RequirementName { get; }
|
||||
|
||||
public string RequirementDescription
|
||||
{
|
||||
get => _requirementDescription;
|
||||
set => RaiseAndSetIfChanged(ref _requirementDescription, value);
|
||||
}
|
||||
|
||||
public bool RequirementMet
|
||||
{
|
||||
get => _requirementMet;
|
||||
set => RaiseAndSetIfChanged(ref _requirementMet, value);
|
||||
}
|
||||
|
||||
private void Update(object? sender, EventArgs e)
|
||||
{
|
||||
RequirementDescription = _activationRequirement.GetUserFriendlyDescription();
|
||||
RequirementMet = _activationRequirement.Evaluate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<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:sidebar="clr-namespace:Artemis.UI.Screens.Sidebar"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Sidebar.ModuleActivationRequirementsView"
|
||||
x:DataType="sidebar:ModuleActivationRequirementsViewModel">
|
||||
<StackPanel>
|
||||
<Grid ColumnDefinitions="*,Auto,*">
|
||||
<Separator Grid.Column="0" Height="1" Background="{DynamicResource TextFillColorTertiaryBrush}" />
|
||||
<TextBlock Grid.Column="1" Margin="16 0">AND</TextBlock>
|
||||
<Separator Grid.Column="2" Height="1" Background="{DynamicResource TextFillColorTertiaryBrush}" />
|
||||
</Grid>
|
||||
<Border Classes="card" Margin="0 5">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="This module has built-in activation requirements and your profile won't activate until " TextWrapping="Wrap" />
|
||||
<TextBlock Text="{CompiledBinding ActivationType}" Foreground="{DynamicResource TextFillColorSecondaryBrush}" FontWeight="Medium" TextWrapping="Wrap" />
|
||||
<TextBlock Text="." />
|
||||
</StackPanel>
|
||||
<TextBlock TextWrapping="Wrap">These requirements allow the module creator to decide when the data is available to your profile you cannot override them.</TextBlock>
|
||||
|
||||
<ItemsControl Items="{CompiledBinding ActivationRequirements}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,17 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Artemis.UI.Screens.Sidebar;
|
||||
|
||||
public class ModuleActivationRequirementsView : UserControl
|
||||
{
|
||||
public ModuleActivationRequirementsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Artemis.Core.Modules;
|
||||
using Artemis.UI.Shared;
|
||||
|
||||
namespace Artemis.UI.Screens.Sidebar;
|
||||
|
||||
public class ModuleActivationRequirementsViewModel : ViewModelBase
|
||||
{
|
||||
public ModuleActivationRequirementsViewModel(Module module)
|
||||
{
|
||||
ActivationType = module.ActivationRequirementMode == ActivationRequirementType.All ? "all requirements are met" : "any requirements are met";
|
||||
ActivationRequirements = module.ActivationRequirements != null
|
||||
? new ObservableCollection<ModuleActivationRequirementViewModel>(module.ActivationRequirements.Select(r => new ModuleActivationRequirementViewModel(r)))
|
||||
: new ObservableCollection<ModuleActivationRequirementViewModel>();
|
||||
}
|
||||
|
||||
public string ActivationType { get; }
|
||||
public ObservableCollection<ModuleActivationRequirementViewModel> ActivationRequirements { get; }
|
||||
}
|
||||
@@ -53,10 +53,10 @@
|
||||
</ItemsPanelTemplate>
|
||||
</ComboBox.ItemsPanel>
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type local:ProfileModuleViewModel}">
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<shared:ArtemisIcon Icon="{CompiledBinding Icon}" Width="16" Height="16" Margin="0 0 5 0" />
|
||||
<TextBlock Text="{CompiledBinding Name}" />
|
||||
<shared:ArtemisIcon Icon="{CompiledBinding Icon, FallbackValue='Close'}" Width="16" Height="16" Margin="0 0 5 0" />
|
||||
<TextBlock Text="{CompiledBinding Name, FallbackValue='None'}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
@@ -167,7 +167,7 @@
|
||||
<TextBlock Classes="h5 section-header">Activation conditions</TextBlock>
|
||||
<TextBlock Classes="subtitle section-subtitle">Set up certain conditions under which the profile should be active</TextBlock>
|
||||
</StackPanel>
|
||||
<Border Classes="card" Margin="0 5 0 15">
|
||||
<Border Classes="card" Margin="0 5">
|
||||
<Grid>
|
||||
<Border CornerRadius="5" ClipToBounds="True">
|
||||
<ContentControl Content="{CompiledBinding VisualEditorViewModel}" Height="150" />
|
||||
@@ -182,8 +182,9 @@
|
||||
Edit condition script
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
</Border>
|
||||
|
||||
<ContentControl Content="{CompiledBinding ModuleActivationRequirementsViewModel}" />
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Modules;
|
||||
@@ -39,6 +40,7 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
private ProfileIconViewModel? _selectedMaterialIcon;
|
||||
private ProfileModuleViewModel? _selectedModule;
|
||||
private SvgImage? _selectedSvgSource;
|
||||
private readonly ObservableAsPropertyHelper<ModuleActivationRequirementsViewModel?> _moduleActivationRequirementsViewModel;
|
||||
|
||||
public ProfileConfigurationEditViewModel(
|
||||
ProfileCategory profileCategory,
|
||||
@@ -64,11 +66,12 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
|
||||
IsNew = profileConfiguration == null;
|
||||
DisplayName = IsNew ? "Artemis | Add profile" : "Artemis | Edit profile";
|
||||
Modules = new ObservableCollection<ProfileModuleViewModel>(
|
||||
Modules = new ObservableCollection<ProfileModuleViewModel?>(
|
||||
pluginManagementService.GetFeaturesOfType<Module>().Where(m => !m.IsAlwaysAvailable).Select(m => new ProfileModuleViewModel(m))
|
||||
);
|
||||
Modules.Insert(0, null);
|
||||
|
||||
VisualEditorViewModel = nodeVmFactory.NodeScriptViewModel(_profileConfiguration.ActivationCondition, true);
|
||||
Dispatcher.UIThread.Post(LoadIcon, DispatcherPriority.Background);
|
||||
|
||||
BrowseBitmapFile = ReactiveCommand.CreateFromTask(ExecuteBrowseBitmapFile);
|
||||
BrowseSvgFile = ReactiveCommand.CreateFromTask(ExecuteBrowseSvgFile);
|
||||
@@ -77,7 +80,12 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
Import = ReactiveCommand.CreateFromTask(ExecuteImport);
|
||||
Delete = ReactiveCommand.CreateFromTask(ExecuteDelete);
|
||||
Cancel = ReactiveCommand.Create(ExecuteCancel);
|
||||
|
||||
|
||||
_moduleActivationRequirementsViewModel = this.WhenAnyValue(vm => vm.SelectedModule)
|
||||
.Select(m => m != null ? new ModuleActivationRequirementsViewModel(m.Module) : null)
|
||||
.ToProperty(this, vm => vm.ModuleActivationRequirementsViewModel);
|
||||
|
||||
Dispatcher.UIThread.Post(LoadIcon, DispatcherPriority.Background);
|
||||
}
|
||||
|
||||
public bool IsNew { get; }
|
||||
@@ -112,7 +120,7 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
set => RaiseAndSetIfChanged(ref _disableHotkey, value);
|
||||
}
|
||||
|
||||
public ObservableCollection<ProfileModuleViewModel> Modules { get; }
|
||||
public ObservableCollection<ProfileModuleViewModel?> Modules { get; }
|
||||
|
||||
public ProfileModuleViewModel? SelectedModule
|
||||
{
|
||||
@@ -121,6 +129,7 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
}
|
||||
|
||||
public NodeScriptViewModel VisualEditorViewModel { get; }
|
||||
public ModuleActivationRequirementsViewModel? ModuleActivationRequirementsViewModel => _moduleActivationRequirementsViewModel.Value;
|
||||
|
||||
public ReactiveCommand<Unit, Unit> OpenConditionEditor { get; }
|
||||
public ReactiveCommand<Unit, Unit> BrowseBitmapFile { get; }
|
||||
@@ -129,7 +138,7 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
public ReactiveCommand<Unit, Unit> Import { get; }
|
||||
public ReactiveCommand<Unit, Unit> Delete { get; }
|
||||
public new ReactiveCommand<Unit, Unit> Cancel { get; }
|
||||
|
||||
|
||||
private async Task ExecuteImport()
|
||||
{
|
||||
if (!IsNew)
|
||||
@@ -306,7 +315,7 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
SelectedSvgSource = new SvgImage {Source = newSource};
|
||||
_selectedIconPath = result[0];
|
||||
}
|
||||
|
||||
|
||||
private async Task ExecuteOpenConditionEditor()
|
||||
{
|
||||
await _windowService.ShowDialogAsync<NodeScriptWindowViewModel, bool>(("nodeScript", ProfileConfiguration.ActivationCondition));
|
||||
|
||||
Reference in new issue
Block a user