mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Merge branch 'development'
This commit is contained in:
commit
e512780592
2
.github/workflows/docfx.yml
vendored
2
.github/workflows/docfx.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
|||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v2
|
uses: actions/setup-dotnet@v2
|
||||||
with:
|
with:
|
||||||
dotnet-version: '6.0.x'
|
dotnet-version: "7.0.x"
|
||||||
- name: Setup DocFX
|
- name: Setup DocFX
|
||||||
run: choco install docfx -y
|
run: choco install docfx -y
|
||||||
- name: Build Core
|
- name: Build Core
|
||||||
|
|||||||
2
.github/workflows/master.yml
vendored
2
.github/workflows/master.yml
vendored
@ -3,6 +3,8 @@ name: Master - Build
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
version:
|
version:
|
||||||
|
|||||||
2
.github/workflows/nuget.yml
vendored
2
.github/workflows/nuget.yml
vendored
@ -3,6 +3,8 @@ name: Publish Nuget packages
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
version:
|
version:
|
||||||
|
|||||||
@ -45,30 +45,8 @@ public class ArtemisPluginException : Exception
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new instance of the <see cref="ArtemisPluginException" /> class
|
|
||||||
/// </summary>
|
|
||||||
public ArtemisPluginException(string message, string helpDocument) : base(message)
|
|
||||||
{
|
|
||||||
HelpDocument = helpDocument;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new instance of the <see cref="ArtemisPluginException" /> class
|
|
||||||
/// </summary>
|
|
||||||
public ArtemisPluginException(string message, Exception inner, string helpDocument) : base(message, inner)
|
|
||||||
{
|
|
||||||
HelpDocument = helpDocument;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin the error is related to
|
/// Gets the plugin the error is related to
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Plugin? Plugin { get; }
|
public Plugin? Plugin { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the help document related to this exception.
|
|
||||||
/// </summary>
|
|
||||||
public string? HelpDocument { get; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ public abstract class BreakableModel : CorePropertyChanged, IBreakableModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void SetBrokenState(string state, Exception? exception)
|
public void SetBrokenState(string state, Exception? exception = null)
|
||||||
{
|
{
|
||||||
BrokenState = state ?? throw new ArgumentNullException(nameof(state));
|
BrokenState = state ?? throw new ArgumentNullException(nameof(state));
|
||||||
BrokenStateException = exception;
|
BrokenStateException = exception;
|
||||||
|
|||||||
@ -16,6 +16,9 @@ namespace Artemis.Core;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class Layer : RenderProfileElement
|
public sealed class Layer : RenderProfileElement
|
||||||
{
|
{
|
||||||
|
private const string BROKEN_STATE_BRUSH_NOT_FOUND = "Failed to load layer brush, ensure the plugin is enabled";
|
||||||
|
private const string BROKEN_STATE_INIT_FAILED = "Failed to initialize layer brush";
|
||||||
|
|
||||||
private readonly List<Layer> _renderCopies = new();
|
private readonly List<Layer> _renderCopies = new();
|
||||||
private LayerGeneralProperties _general = new();
|
private LayerGeneralProperties _general = new();
|
||||||
private LayerTransformProperties _transform = new();
|
private LayerTransformProperties _transform = new();
|
||||||
@ -261,7 +264,10 @@ public sealed class Layer : RenderProfileElement
|
|||||||
private void LayerBrushStoreOnLayerBrushRemoved(object? sender, LayerBrushStoreEvent e)
|
private void LayerBrushStoreOnLayerBrushRemoved(object? sender, LayerBrushStoreEvent e)
|
||||||
{
|
{
|
||||||
if (LayerBrush?.Descriptor == e.Registration.LayerBrushDescriptor)
|
if (LayerBrush?.Descriptor == e.Registration.LayerBrushDescriptor)
|
||||||
|
{
|
||||||
DeactivateLayerBrush();
|
DeactivateLayerBrush();
|
||||||
|
SetBrokenState(BROKEN_STATE_BRUSH_NOT_FOUND);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LayerBrushStoreOnLayerBrushAdded(object? sender, LayerBrushStoreEvent e)
|
private void LayerBrushStoreOnLayerBrushAdded(object? sender, LayerBrushStoreEvent e)
|
||||||
@ -807,33 +813,46 @@ public sealed class Layer : RenderProfileElement
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Changes the current layer brush to the provided layer brush and activates it
|
/// Changes the current layer brush to the provided layer brush and activates it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ChangeLayerBrush(BaseLayerBrush? layerBrush)
|
public void ChangeLayerBrush(BaseLayerBrush layerBrush)
|
||||||
{
|
{
|
||||||
BaseLayerBrush? oldLayerBrush = LayerBrush;
|
if (layerBrush == null)
|
||||||
|
throw new ArgumentNullException(nameof(layerBrush));
|
||||||
|
|
||||||
General.BrushReference.SetCurrentValue(layerBrush != null ? new LayerBrushReference(layerBrush.Descriptor) : null);
|
BaseLayerBrush? oldLayerBrush = LayerBrush;
|
||||||
|
General.BrushReference.SetCurrentValue(new LayerBrushReference(layerBrush.Descriptor));
|
||||||
LayerBrush = layerBrush;
|
LayerBrush = layerBrush;
|
||||||
|
|
||||||
|
// Don't dispose the brush, only disable it
|
||||||
|
// That way an undo-action does not need to worry about disposed brushes
|
||||||
oldLayerBrush?.InternalDisable();
|
oldLayerBrush?.InternalDisable();
|
||||||
|
ActivateLayerBrush();
|
||||||
if (LayerBrush != null)
|
|
||||||
ActivateLayerBrush();
|
|
||||||
else
|
|
||||||
OnLayerBrushUpdated();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ActivateLayerBrush()
|
private void ActivateLayerBrush()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// If the brush is null, try to instantiate it
|
||||||
if (LayerBrush == null)
|
if (LayerBrush == null)
|
||||||
{
|
{
|
||||||
// If the brush is null, try to instantiate it
|
// Ensure the provider is loaded and still provides the expected brush
|
||||||
LayerBrushReference? brushReference = General.BrushReference.CurrentValue;
|
LayerBrushReference? brushReference = General.BrushReference.CurrentValue;
|
||||||
if (brushReference?.LayerBrushProviderId != null && brushReference.BrushType != null)
|
if (brushReference?.LayerBrushProviderId != null && brushReference.BrushType != null)
|
||||||
ChangeLayerBrush(LayerBrushStore.Get(brushReference.LayerBrushProviderId, brushReference.BrushType)?.LayerBrushDescriptor.CreateInstance(this, LayerEntity.LayerBrush));
|
{
|
||||||
// If that's not possible there's nothing to do
|
// Only apply the brush if it is successfully retrieved from the store and instantiated
|
||||||
return;
|
BaseLayerBrush? layerBrush = LayerBrushStore.Get(brushReference.LayerBrushProviderId, brushReference.BrushType)?.LayerBrushDescriptor.CreateInstance(this, LayerEntity.LayerBrush);
|
||||||
|
if (layerBrush != null)
|
||||||
|
{
|
||||||
|
ClearBrokenState(BROKEN_STATE_BRUSH_NOT_FOUND);
|
||||||
|
ChangeLayerBrush(layerBrush);
|
||||||
|
}
|
||||||
|
// If that's not possible there's nothing to do
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetBrokenState(BROKEN_STATE_BRUSH_NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
General.ShapeType.IsHidden = LayerBrush != null && !LayerBrush.SupportsTransformation;
|
General.ShapeType.IsHidden = LayerBrush != null && !LayerBrush.SupportsTransformation;
|
||||||
@ -846,15 +865,15 @@ public sealed class Layer : RenderProfileElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
OnLayerBrushUpdated();
|
OnLayerBrushUpdated();
|
||||||
ClearBrokenState("Failed to initialize layer brush");
|
ClearBrokenState(BROKEN_STATE_INIT_FAILED);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
SetBrokenState("Failed to initialize layer brush", e);
|
SetBrokenState(BROKEN_STATE_INIT_FAILED, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void DeactivateLayerBrush()
|
private void DeactivateLayerBrush()
|
||||||
{
|
{
|
||||||
if (LayerBrush == null)
|
if (LayerBrush == null)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -27,6 +27,7 @@ public class PluginInfo : CorePropertyChanged, IPrerequisitesSubject
|
|||||||
private bool _requiresAdmin;
|
private bool _requiresAdmin;
|
||||||
private string _version = null!;
|
private string _version = null!;
|
||||||
private Uri? _website;
|
private Uri? _website;
|
||||||
|
private Uri? _helpPage;
|
||||||
|
|
||||||
internal PluginInfo()
|
internal PluginInfo()
|
||||||
{
|
{
|
||||||
@ -92,6 +93,16 @@ public class PluginInfo : CorePropertyChanged, IPrerequisitesSubject
|
|||||||
set => SetAndNotify(ref _repository, value);
|
set => SetAndNotify(ref _repository, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the help page of this plugin
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty]
|
||||||
|
public Uri? HelpPage
|
||||||
|
{
|
||||||
|
get => _helpPage;
|
||||||
|
set => SetAndNotify(ref _helpPage, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The plugins display icon that's shown in the settings see <see href="https://materialdesignicons.com" /> for
|
/// The plugins display icon that's shown in the settings see <see href="https://materialdesignicons.com" /> for
|
||||||
/// available icons
|
/// available icons
|
||||||
|
|||||||
@ -78,6 +78,6 @@ public class OpenFileDialogBuilder
|
|||||||
public async Task<string[]?> ShowAsync()
|
public async Task<string[]?> ShowAsync()
|
||||||
{
|
{
|
||||||
IReadOnlyList<IStorageFile> files = await _parent.StorageProvider.OpenFilePickerAsync(_options);
|
IReadOnlyList<IStorageFile> files = await _parent.StorageProvider.OpenFilePickerAsync(_options);
|
||||||
return files.Select(f => f.Path.AbsolutePath).ToArray();
|
return files.Select(f => f.Path.LocalPath).ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,7 +54,8 @@ public class ChangeLayerBrush : IProfileEditorCommand, IDisposable
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Undo()
|
public void Undo()
|
||||||
{
|
{
|
||||||
_layer.ChangeLayerBrush(_previousBrush);
|
if (_previousBrush != null)
|
||||||
|
_layer.ChangeLayerBrush(_previousBrush);
|
||||||
_executed = false;
|
_executed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
<!-- Custom styles -->
|
<!-- Custom styles -->
|
||||||
<StyleInclude Source="/Styles/Border.axaml" />
|
<StyleInclude Source="/Styles/Border.axaml" />
|
||||||
|
<StyleInclude Source="/Styles/BrokenState.axaml" />
|
||||||
<StyleInclude Source="/Styles/Skeleton.axaml" />
|
<StyleInclude Source="/Styles/Skeleton.axaml" />
|
||||||
<StyleInclude Source="/Styles/Button.axaml" />
|
<StyleInclude Source="/Styles/Button.axaml" />
|
||||||
<StyleInclude Source="/Styles/Condensed.axaml" />
|
<StyleInclude Source="/Styles/Condensed.axaml" />
|
||||||
|
|||||||
20
src/Artemis.UI.Shared/Styles/BrokenState.axaml
Normal file
20
src/Artemis.UI.Shared/Styles/BrokenState.axaml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<Styles xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia">
|
||||||
|
<Design.PreviewWith>
|
||||||
|
|
||||||
|
<controls:HyperlinkButton Grid.Column="0" Classes="icon-button icon-button-small broken-state-button" Margin="50">
|
||||||
|
<avalonia:MaterialIcon Kind="AlertCircle" />
|
||||||
|
</controls:HyperlinkButton>
|
||||||
|
</Design.PreviewWith>
|
||||||
|
|
||||||
|
<!-- Add Styles Here -->
|
||||||
|
<Style Selector="controls|HyperlinkButton.broken-state-button avalonia|MaterialIcon">
|
||||||
|
<Setter Property="Foreground" Value="#E74C4C" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="controls|HyperlinkButton.broken-state-button:pointerover avalonia|MaterialIcon">
|
||||||
|
<Setter Property="Foreground" Value="#B93F3F" />
|
||||||
|
</Style>
|
||||||
|
</Styles>
|
||||||
@ -52,5 +52,17 @@
|
|||||||
<DependentUpon>UpdatingTabView.axaml</DependentUpon>
|
<DependentUpon>UpdatingTabView.axaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="Screens\Plugins\Features\PluginFeatureView.axaml.cs">
|
||||||
|
<DependentUpon>PluginFeatureView.axaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Screens\Plugins\Prerequisites\PluginPrerequisiteActionView.axaml.cs">
|
||||||
|
<DependentUpon>PluginPrerequisiteActionView.axaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Screens\Plugins\Prerequisites\PluginPrerequisiteView.axaml.cs">
|
||||||
|
<DependentUpon>PluginPrerequisiteView.axaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -7,6 +7,8 @@ using Artemis.Core.LayerEffects;
|
|||||||
using Artemis.Core.ScriptingProviders;
|
using Artemis.Core.ScriptingProviders;
|
||||||
using Artemis.UI.Screens.Device;
|
using Artemis.UI.Screens.Device;
|
||||||
using Artemis.UI.Screens.Plugins;
|
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;
|
||||||
using Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
|
using Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
|
||||||
using Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
using Artemis.UI.Screens.ProfileEditor.ProfileTree;
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
|
xmlns:prerequisites="clr-namespace:Artemis.UI.Screens.Plugins.Prerequisites"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Plugins.PluginPrerequisitesInstallDialogView"
|
x:Class="Artemis.UI.Screens.Plugins.PluginPrerequisitesInstallDialogView"
|
||||||
x:DataType="plugins:PluginPrerequisitesInstallDialogViewModel">
|
x:DataType="plugins:PluginPrerequisitesInstallDialogViewModel">
|
||||||
@ -34,7 +35,7 @@
|
|||||||
SelectedItem="{CompiledBinding ActivePrerequisite, Mode=OneWay}"
|
SelectedItem="{CompiledBinding ActivePrerequisite, Mode=OneWay}"
|
||||||
IsHitTestVisible="False">
|
IsHitTestVisible="False">
|
||||||
<ListBox.ItemTemplate>
|
<ListBox.ItemTemplate>
|
||||||
<DataTemplate DataType="{x:Type plugins:PluginPrerequisiteViewModel}">
|
<DataTemplate DataType="{x:Type prerequisites:PluginPrerequisiteViewModel}">
|
||||||
<Grid ColumnDefinitions="Auto,*" Margin="0 6">
|
<Grid ColumnDefinitions="Auto,*" Margin="0 6">
|
||||||
<Border Grid.Row="0" Grid.Column="0" Classes="status-border" IsVisible="{CompiledBinding !IsMet}" Background="#ff3838">
|
<Border Grid.Row="0" Grid.Column="0" Classes="status-border" IsVisible="{CompiledBinding !IsMet}" Background="#ff3838">
|
||||||
<avalonia:MaterialIcon Kind="Close" />
|
<avalonia:MaterialIcon Kind="Close" />
|
||||||
|
|||||||
@ -8,6 +8,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.UI.DryIoc.Factories;
|
using Artemis.UI.DryIoc.Factories;
|
||||||
|
using Artemis.UI.Screens.Plugins.Prerequisites;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
|
xmlns:prerequisites="clr-namespace:Artemis.UI.Screens.Plugins.Prerequisites"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Plugins.PluginPrerequisitesUninstallDialogView"
|
x:Class="Artemis.UI.Screens.Plugins.PluginPrerequisitesUninstallDialogView"
|
||||||
x:DataType="plugins:PluginPrerequisitesUninstallDialogViewModel">
|
x:DataType="plugins:PluginPrerequisitesUninstallDialogViewModel">
|
||||||
@ -34,7 +35,7 @@
|
|||||||
SelectedItem="{CompiledBinding ActivePrerequisite, Mode=OneWay}"
|
SelectedItem="{CompiledBinding ActivePrerequisite, Mode=OneWay}"
|
||||||
IsHitTestVisible="False">
|
IsHitTestVisible="False">
|
||||||
<ListBox.ItemTemplate>
|
<ListBox.ItemTemplate>
|
||||||
<DataTemplate DataType="{x:Type plugins:PluginPrerequisiteViewModel}">
|
<DataTemplate DataType="{x:Type prerequisites:PluginPrerequisiteViewModel}">
|
||||||
<StackPanel Margin="0 6" VerticalAlignment="Stretch">
|
<StackPanel Margin="0 6" VerticalAlignment="Stretch">
|
||||||
<TextBlock FontWeight="Bold" Text="{CompiledBinding PluginPrerequisite.Name}" TextWrapping="Wrap" />
|
<TextBlock FontWeight="Bold" Text="{CompiledBinding PluginPrerequisite.Name}" TextWrapping="Wrap" />
|
||||||
<TextBlock Text="{CompiledBinding PluginPrerequisite.Description}" TextWrapping="Wrap" />
|
<TextBlock Text="{CompiledBinding PluginPrerequisite.Description}" TextWrapping="Wrap" />
|
||||||
|
|||||||
@ -9,6 +9,7 @@ using System.Threading.Tasks;
|
|||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.DryIoc.Factories;
|
using Artemis.UI.DryIoc.Factories;
|
||||||
|
using Artemis.UI.Screens.Plugins.Prerequisites;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
|||||||
@ -5,9 +5,10 @@
|
|||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||||
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
||||||
|
xmlns:features="clr-namespace:Artemis.UI.Screens.Plugins.Features"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Plugins.PluginFeatureView"
|
x:Class="Artemis.UI.Screens.Plugins.Features.PluginFeatureView"
|
||||||
x:DataType="plugins:PluginFeatureViewModel">
|
x:DataType="features:PluginFeatureViewModel">
|
||||||
<Grid ColumnDefinitions="30,*,Auto">
|
<Grid ColumnDefinitions="30,*,Auto">
|
||||||
<Grid.ContextFlyout>
|
<Grid.ContextFlyout>
|
||||||
<MenuFlyout>
|
<MenuFlyout>
|
||||||
@ -1,7 +1,6 @@
|
|||||||
using Avalonia.Markup.Xaml;
|
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Plugins;
|
namespace Artemis.UI.Screens.Plugins.Features;
|
||||||
|
|
||||||
public partial class PluginFeatureView : ReactiveUserControl<PluginFeatureViewModel>
|
public partial class PluginFeatureView : ReactiveUserControl<PluginFeatureViewModel>
|
||||||
{
|
{
|
||||||
@ -18,12 +18,11 @@ using Avalonia.Threading;
|
|||||||
using Material.Icons;
|
using Material.Icons;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Plugins;
|
namespace Artemis.UI.Screens.Plugins.Features;
|
||||||
|
|
||||||
public class PluginFeatureViewModel : ActivatableViewModelBase
|
public class PluginFeatureViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
private readonly ICoreService _coreService;
|
private readonly ICoreService _coreService;
|
||||||
private readonly INotificationService _notificationService;
|
|
||||||
private readonly IPluginManagementService _pluginManagementService;
|
private readonly IPluginManagementService _pluginManagementService;
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
private bool _enabling;
|
private bool _enabling;
|
||||||
@ -32,12 +31,10 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
|
|||||||
bool showShield,
|
bool showShield,
|
||||||
ICoreService coreService,
|
ICoreService coreService,
|
||||||
IWindowService windowService,
|
IWindowService windowService,
|
||||||
INotificationService notificationService,
|
|
||||||
IPluginManagementService pluginManagementService)
|
IPluginManagementService pluginManagementService)
|
||||||
{
|
{
|
||||||
_coreService = coreService;
|
_coreService = coreService;
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
_notificationService = notificationService;
|
|
||||||
_pluginManagementService = pluginManagementService;
|
_pluginManagementService = pluginManagementService;
|
||||||
|
|
||||||
FeatureInfo = pluginFeatureInfo;
|
FeatureInfo = pluginFeatureInfo;
|
||||||
@ -176,11 +173,7 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
|
|||||||
if (FeatureInfo.Instance == null)
|
if (FeatureInfo.Instance == null)
|
||||||
{
|
{
|
||||||
this.RaisePropertyChanged(nameof(IsEnabled));
|
this.RaisePropertyChanged(nameof(IsEnabled));
|
||||||
_notificationService.CreateNotification()
|
await ShowFailureDialog($"Failed to enable '{FeatureInfo.Name}'", $"Feature '{FeatureInfo.Name}' is in a broken state and cannot enable.");
|
||||||
.WithMessage($"Feature '{FeatureInfo.Name}' is in a broken state and cannot enable.")
|
|
||||||
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
|
|
||||||
.WithSeverity(NotificationSeverity.Error)
|
|
||||||
.Show();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,11 +208,7 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_notificationService.CreateNotification()
|
await ShowFailureDialog($"Failed to enable '{FeatureInfo.Name}'", e.Message);
|
||||||
.WithMessage($"Failed to enable '{FeatureInfo.Name}'.\r\n{e.Message}")
|
|
||||||
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
|
|
||||||
.WithSeverity(NotificationSeverity.Error)
|
|
||||||
.Show();
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -254,4 +243,17 @@ public class PluginFeatureViewModel : ActivatableViewModelBase
|
|||||||
{
|
{
|
||||||
this.RaisePropertyChanged(nameof(CanToggleEnabled));
|
this.RaisePropertyChanged(nameof(CanToggleEnabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ShowFailureDialog(string action, string message)
|
||||||
|
{
|
||||||
|
ContentDialogBuilder builder = _windowService.CreateContentDialog()
|
||||||
|
.WithTitle(action)
|
||||||
|
.WithContent(message)
|
||||||
|
.HavingPrimaryButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder));
|
||||||
|
// If available, add a secondary button pointing to the support page
|
||||||
|
if (FeatureInfo.Plugin.Info.HelpPage != null)
|
||||||
|
builder = builder.HavingSecondaryButton(b => b.WithText("Open support page").WithAction(() => Utilities.OpenUrl(FeatureInfo.Plugin.Info.HelpPage.ToString())));
|
||||||
|
|
||||||
|
await builder.ShowAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
|||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.DryIoc.Factories;
|
using Artemis.UI.DryIoc.Factories;
|
||||||
|
using Artemis.UI.Screens.Plugins.Features;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|||||||
@ -3,10 +3,12 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia"
|
xmlns:windowing="clr-namespace:FluentAvalonia.UI.Windowing;assembly=FluentAvalonia"
|
||||||
|
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Plugins.PluginSettingsWindowView"
|
x:Class="Artemis.UI.Screens.Plugins.PluginSettingsWindowView"
|
||||||
|
x:DataType="plugins:PluginSettingsWindowViewModel"
|
||||||
Icon="/Assets/Images/Logo/application.ico"
|
Icon="/Assets/Images/Logo/application.ico"
|
||||||
Title="{Binding DisplayName}"
|
Title="{CompiledBinding DisplayName}"
|
||||||
Width="800"
|
Width="800"
|
||||||
Height="800"
|
Height="800"
|
||||||
WindowStartupLocation="CenterOwner">
|
WindowStartupLocation="CenterOwner">
|
||||||
|
|||||||
@ -46,9 +46,9 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid Grid.Row="1" ColumnDefinitions="*,Auto">
|
<Grid Grid.Row="1" ColumnDefinitions="*,Auto">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||||
<SplitButton Content="Settings" Command="{CompiledBinding OpenSettings}">
|
<DropDownButton Content="Manage">
|
||||||
<SplitButton.Flyout>
|
<DropDownButton.Flyout>
|
||||||
<MenuFlyout Placement="Bottom" Opening="FlyoutBase_OnOpening">
|
<MenuFlyout Placement="Bottom" Opening="FlyoutBase_OnOpening">
|
||||||
<MenuItem Header="Open plugin directory" Command="{CompiledBinding OpenPluginDirectory}">
|
<MenuItem Header="Open plugin directory" Command="{CompiledBinding OpenPluginDirectory}">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
@ -70,6 +70,7 @@
|
|||||||
<avalonia:MaterialIcon Kind="Delete" />
|
<avalonia:MaterialIcon Kind="Delete" />
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<Separator/>
|
||||||
<MenuItem Header="Clear plugin settings" Command="{CompiledBinding RemoveSettings}">
|
<MenuItem Header="Clear plugin settings" Command="{CompiledBinding RemoveSettings}">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<avalonia:MaterialIcon Kind="DatabaseRemove" />
|
<avalonia:MaterialIcon Kind="DatabaseRemove" />
|
||||||
@ -81,19 +82,31 @@
|
|||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuFlyout>
|
</MenuFlyout>
|
||||||
</SplitButton.Flyout>
|
</DropDownButton.Flyout>
|
||||||
</SplitButton>
|
</DropDownButton>
|
||||||
|
|
||||||
<controls:HyperlinkButton Classes="icon-button icon-button-large"
|
<controls:HyperlinkButton Classes="icon-button icon-button-large"
|
||||||
Margin="5 0"
|
IsVisible="{CompiledBinding Plugin.ConfigurationDialog, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||||
|
Command="{CompiledBinding OpenSettings}"
|
||||||
|
ToolTip.Tip="Open settings">
|
||||||
|
<avalonia:MaterialIcon Kind="Cog" />
|
||||||
|
</controls:HyperlinkButton>
|
||||||
|
<controls:HyperlinkButton Classes="icon-button icon-button-large"
|
||||||
|
IsVisible="{CompiledBinding Plugin.Info.HelpPage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||||
|
NavigateUri="{CompiledBinding Plugin.Info.HelpPage}"
|
||||||
|
ToolTip.Tip="{CompiledBinding Plugin.Info.HelpPage}">
|
||||||
|
<avalonia:MaterialIcon Kind="HelpCircle" />
|
||||||
|
</controls:HyperlinkButton>
|
||||||
|
<controls:HyperlinkButton Classes="icon-button icon-button-large"
|
||||||
IsVisible="{CompiledBinding Plugin.Info.Website, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
IsVisible="{CompiledBinding Plugin.Info.Website, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||||
NavigateUri="{CompiledBinding Plugin.Info.Website}">
|
NavigateUri="{CompiledBinding Plugin.Info.Website}"
|
||||||
|
ToolTip.Tip="{CompiledBinding Plugin.Info.Website}">
|
||||||
<avalonia:MaterialIcon Kind="Web" />
|
<avalonia:MaterialIcon Kind="Web" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
<controls:HyperlinkButton Classes="icon-button icon-button-large"
|
<controls:HyperlinkButton Classes="icon-button icon-button-large"
|
||||||
Margin="5 0"
|
|
||||||
IsVisible="{CompiledBinding Plugin.Info.Repository, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
IsVisible="{CompiledBinding Plugin.Info.Repository, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||||
NavigateUri="{CompiledBinding Plugin.Info.Repository}">
|
NavigateUri="{CompiledBinding Plugin.Info.Repository}"
|
||||||
|
ToolTip.Tip="{CompiledBinding Plugin.Info.Repository}">
|
||||||
<avalonia:MaterialIcon Kind="Git" />
|
<avalonia:MaterialIcon Kind="Git" />
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@ -28,7 +28,7 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
private bool _canRemovePrerequisites;
|
private bool _canRemovePrerequisites;
|
||||||
private bool _enabling;
|
private bool _enabling;
|
||||||
private Plugin _plugin;
|
private Plugin _plugin;
|
||||||
private Window? _window;
|
private Window? _settingsWindow;
|
||||||
|
|
||||||
public PluginViewModel(Plugin plugin,
|
public PluginViewModel(Plugin plugin,
|
||||||
ReactiveCommand<Unit, Unit>? reload,
|
ReactiveCommand<Unit, Unit>? reload,
|
||||||
@ -72,7 +72,7 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
{
|
{
|
||||||
Plugin.Enabled -= OnPluginToggled;
|
Plugin.Enabled -= OnPluginToggled;
|
||||||
Plugin.Disabled -= OnPluginToggled;
|
Plugin.Disabled -= OnPluginToggled;
|
||||||
_window?.Close();
|
_settingsWindow?.Close();
|
||||||
}).DisposeWith(d);
|
}).DisposeWith(d);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -128,11 +128,7 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await Dispatcher.UIThread.InvokeAsync(() => _notificationService.CreateNotification()
|
await ShowUpdateEnableFailure(enable, e);
|
||||||
.WithSeverity(NotificationSeverity.Error)
|
|
||||||
.WithMessage($"Failed to disable plugin {Plugin.Info.Name}\r\n{e.Message}")
|
|
||||||
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
|
|
||||||
.Show());
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -167,11 +163,7 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
await Dispatcher.UIThread.InvokeAsync(() => _notificationService.CreateNotification()
|
await ShowUpdateEnableFailure(enable, e);
|
||||||
.WithSeverity(NotificationSeverity.Error)
|
|
||||||
.WithMessage($"Failed to enable plugin {Plugin.Info.Name}\r\n{e.Message}")
|
|
||||||
.HavingButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder))
|
|
||||||
.Show());
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -180,7 +172,6 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void CheckPrerequisites()
|
public void CheckPrerequisites()
|
||||||
{
|
{
|
||||||
CanInstallPrerequisites = false;
|
CanInstallPrerequisites = false;
|
||||||
@ -199,10 +190,10 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
if (Plugin.ConfigurationDialog == null)
|
if (Plugin.ConfigurationDialog == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_window != null)
|
if (_settingsWindow != null)
|
||||||
{
|
{
|
||||||
_window.WindowState = WindowState.Normal;
|
_settingsWindow.WindowState = WindowState.Normal;
|
||||||
_window.Activate();
|
_settingsWindow.Activate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,8 +202,8 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
if (Plugin.Resolve(Plugin.ConfigurationDialog.Type) is not PluginConfigurationViewModel viewModel)
|
if (Plugin.Resolve(Plugin.ConfigurationDialog.Type) is not PluginConfigurationViewModel viewModel)
|
||||||
throw new ArtemisUIException($"The type of a plugin configuration dialog must inherit {nameof(PluginConfigurationViewModel)}");
|
throw new ArtemisUIException($"The type of a plugin configuration dialog must inherit {nameof(PluginConfigurationViewModel)}");
|
||||||
|
|
||||||
_window = _windowService.ShowWindow(new PluginSettingsWindowViewModel(viewModel));
|
_settingsWindow = _windowService.ShowWindow(new PluginSettingsWindowViewModel(viewModel));
|
||||||
_window.Closed += (_, _) => _window = null;
|
_settingsWindow.Closed += (_, _) => _settingsWindow = null;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -307,13 +298,27 @@ public class PluginViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ShowUpdateEnableFailure(bool enable, Exception e)
|
||||||
|
{
|
||||||
|
string action = enable ? "enable" : "disable";
|
||||||
|
ContentDialogBuilder builder = _windowService.CreateContentDialog()
|
||||||
|
.WithTitle($"Failed to {action} plugin {Plugin.Info.Name}")
|
||||||
|
.WithContent(e.Message)
|
||||||
|
.HavingPrimaryButton(b => b.WithText("View logs").WithCommand(ShowLogsFolder));
|
||||||
|
// If available, add a secondary button pointing to the support page
|
||||||
|
if (Plugin.Info.HelpPage != null)
|
||||||
|
builder = builder.HavingSecondaryButton(b => b.WithText("Open support page").WithAction(() => Utilities.OpenUrl(Plugin.Info.HelpPage.ToString())));
|
||||||
|
|
||||||
|
await builder.ShowAsync();
|
||||||
|
}
|
||||||
|
|
||||||
private void OnPluginToggled(object? sender, EventArgs e)
|
private void OnPluginToggled(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
this.RaisePropertyChanged(nameof(IsEnabled));
|
this.RaisePropertyChanged(nameof(IsEnabled));
|
||||||
if (!IsEnabled)
|
if (!IsEnabled)
|
||||||
_window?.Close();
|
_settingsWindow?.Close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,9 +3,10 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
||||||
|
xmlns:prerequisites="clr-namespace:Artemis.UI.Screens.Plugins.Prerequisites"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Plugins.PluginPrerequisiteActionView"
|
x:Class="Artemis.UI.Screens.Plugins.Prerequisites.PluginPrerequisiteActionView"
|
||||||
x:DataType="plugins:PluginPrerequisiteActionViewModel">
|
x:DataType="prerequisites:PluginPrerequisiteActionViewModel">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<ProgressBar Value="{CompiledBinding Action.Progress.Percentage, Mode=OneWay}"
|
<ProgressBar Value="{CompiledBinding Action.Progress.Percentage, Mode=OneWay}"
|
||||||
IsIndeterminate="{CompiledBinding Action.ProgressIndeterminate, Mode=OneWay}"
|
IsIndeterminate="{CompiledBinding Action.ProgressIndeterminate, Mode=OneWay}"
|
||||||
@ -1,7 +1,6 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Markup.Xaml;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Plugins;
|
namespace Artemis.UI.Screens.Plugins.Prerequisites;
|
||||||
|
|
||||||
public partial class PluginPrerequisiteActionView : UserControl
|
public partial class PluginPrerequisiteActionView : UserControl
|
||||||
{
|
{
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Plugins;
|
namespace Artemis.UI.Screens.Plugins.Prerequisites;
|
||||||
|
|
||||||
public class PluginPrerequisiteActionViewModel : ViewModelBase
|
public class PluginPrerequisiteActionViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
@ -3,9 +3,10 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Plugins"
|
||||||
|
xmlns:prerequisites="clr-namespace:Artemis.UI.Screens.Plugins.Prerequisites"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Plugins.PluginPrerequisiteView"
|
x:Class="Artemis.UI.Screens.Plugins.Prerequisites.PluginPrerequisiteView"
|
||||||
x:DataType="plugins:PluginPrerequisiteViewModel">
|
x:DataType="prerequisites:PluginPrerequisiteViewModel">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding PluginPrerequisite.Name, Mode=OneWay}" />
|
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding PluginPrerequisite.Name, Mode=OneWay}" />
|
||||||
<TextBlock Classes="subtitle" TextWrapping="Wrap" Text="{CompiledBinding PluginPrerequisite.Description, Mode=OneWay}" Margin="0 0 0 15" />
|
<TextBlock Classes="subtitle" TextWrapping="Wrap" Text="{CompiledBinding PluginPrerequisite.Description, Mode=OneWay}" Margin="0 0 0 15" />
|
||||||
@ -1,7 +1,6 @@
|
|||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.ReactiveUI;
|
||||||
using Avalonia.ReactiveUI;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Plugins;
|
namespace Artemis.UI.Screens.Plugins.Prerequisites;
|
||||||
|
|
||||||
public partial class PluginPrerequisiteView : ReactiveUserControl<PluginPrerequisiteViewModel>
|
public partial class PluginPrerequisiteView : ReactiveUserControl<PluginPrerequisiteViewModel>
|
||||||
{
|
{
|
||||||
@ -8,7 +8,7 @@ using Artemis.Core;
|
|||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Plugins;
|
namespace Artemis.UI.Screens.Plugins.Prerequisites;
|
||||||
|
|
||||||
public class PluginPrerequisiteViewModel : ActivatableViewModelBase
|
public class PluginPrerequisiteViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
@ -4,21 +4,19 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:profileTree="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree"
|
xmlns:profileTree="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree"
|
||||||
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.FolderTreeItemView"
|
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.FolderTreeItemView"
|
||||||
x:DataType="profileTree:FolderTreeItemViewModel">
|
x:DataType="profileTree:FolderTreeItemViewModel">
|
||||||
<Grid ColumnDefinitions="Auto,Auto,*,Auto,Auto">
|
<Grid ColumnDefinitions="Auto,Auto,*,Auto,Auto">
|
||||||
<Button Grid.Column="0"
|
<controls:HyperlinkButton Grid.Column="0"
|
||||||
ToolTip.Tip="{CompiledBinding ProfileElement.BrokenState}"
|
Classes="icon-button icon-button-small broken-state-button"
|
||||||
IsVisible="{CompiledBinding ProfileElement.BrokenState, Converter={x:Static ObjectConverters.IsNotNull}}"
|
Margin="0 0 5 0"
|
||||||
Classes="icon-button icon-button-small"
|
Command="{CompiledBinding ShowBrokenStateExceptions}"
|
||||||
Foreground="White"
|
IsVisible="{CompiledBinding ProfileElement.BrokenState, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||||
Background="#E74C4C"
|
ToolTip.Tip="{CompiledBinding ProfileElement.BrokenState, FallbackValue=''}">
|
||||||
BorderBrush="#E74C4C"
|
|
||||||
Margin="0 0 5 0"
|
|
||||||
Command="{Binding ShowBrokenStateExceptions}">
|
|
||||||
<avalonia:MaterialIcon Kind="AlertCircle" />
|
<avalonia:MaterialIcon Kind="AlertCircle" />
|
||||||
</Button>
|
</controls:HyperlinkButton>
|
||||||
<avalonia:MaterialIcon Grid.Column="1"
|
<avalonia:MaterialIcon Grid.Column="1"
|
||||||
Kind="Folder"
|
Kind="Folder"
|
||||||
Margin="0 0 5 0"
|
Margin="0 0 5 0"
|
||||||
|
|||||||
@ -4,19 +4,19 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:profileTree="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree"
|
xmlns:profileTree="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree"
|
||||||
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.LayerTreeItemView"
|
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.LayerTreeItemView"
|
||||||
x:DataType="profileTree:LayerTreeItemViewModel">
|
x:DataType="profileTree:LayerTreeItemViewModel">
|
||||||
<Grid ColumnDefinitions="Auto,Auto,*,Auto,Auto">
|
<Grid ColumnDefinitions="Auto,Auto,*,Auto,Auto">
|
||||||
<Button Grid.Column="0"
|
<controls:HyperlinkButton Grid.Column="0"
|
||||||
ToolTip.Tip="{CompiledBinding ProfileElement.BrokenState}"
|
Classes="icon-button icon-button-small broken-state-button"
|
||||||
IsVisible="{CompiledBinding ProfileElement.BrokenState, Converter={x:Static ObjectConverters.IsNotNull}}"
|
Margin="0 0 5 0"
|
||||||
Classes="icon-button icon-button-small"
|
Command="{CompiledBinding ShowBrokenStateExceptions}"
|
||||||
Foreground="#E74C4C"
|
IsVisible="{CompiledBinding ProfileElement.BrokenState, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||||
Margin="0 0 5 0"
|
ToolTip.Tip="{CompiledBinding ProfileElement.BrokenState, FallbackValue=''}">
|
||||||
Command="{Binding ShowBrokenStateExceptions}">
|
|
||||||
<avalonia:MaterialIcon Kind="AlertCircle" />
|
<avalonia:MaterialIcon Kind="AlertCircle" />
|
||||||
</Button>
|
</controls:HyperlinkButton>
|
||||||
<avalonia:MaterialIcon Grid.Column="1" Kind="{CompiledBinding Layer.LayerBrush.Descriptor.Icon, FallbackValue=Layers}" Margin="0 0 5 0" />
|
<avalonia:MaterialIcon Grid.Column="1" Kind="{CompiledBinding Layer.LayerBrush.Descriptor.Icon, FallbackValue=Layers}" Margin="0 0 5 0" />
|
||||||
<TextBox Grid.Column="2"
|
<TextBox Grid.Column="2"
|
||||||
Margin="-5 0 0 0"
|
Margin="-5 0 0 0"
|
||||||
|
|||||||
@ -4,9 +4,6 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:updating="clr-namespace:Artemis.UI.Screens.Settings.Updating"
|
xmlns:updating="clr-namespace:Artemis.UI.Screens.Settings.Updating"
|
||||||
xmlns:avalonia="clr-namespace:Markdown.Avalonia;assembly=Markdown.Avalonia"
|
xmlns:avalonia="clr-namespace:Markdown.Avalonia;assembly=Markdown.Avalonia"
|
||||||
xmlns:mdc="clr-namespace:Markdown.Avalonia.Controls;assembly=Markdown.Avalonia"
|
|
||||||
xmlns:mde="clr-namespace:Markdown.Avalonia.Extensions;assembly=Markdown.Avalonia"
|
|
||||||
xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia"
|
|
||||||
xmlns:avalonia1="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia1="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
||||||
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="1400"
|
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="1400"
|
||||||
@ -158,17 +155,7 @@
|
|||||||
|
|
||||||
<avalonia:MarkdownScrollViewer Grid.Row="2" Markdown="{CompiledBinding Changelog}" MarkdownStyleName="FluentAvalonia">
|
<avalonia:MarkdownScrollViewer Grid.Row="2" Markdown="{CompiledBinding Changelog}" MarkdownStyleName="FluentAvalonia">
|
||||||
<avalonia:MarkdownScrollViewer.Styles>
|
<avalonia:MarkdownScrollViewer.Styles>
|
||||||
<Style Selector="ctxt|CHyperlink">
|
<StyleInclude Source="/Styles/Markdown.axaml"/>
|
||||||
<Setter Property="Foreground" Value="{DynamicResource SystemAccentColorLight3}" />
|
|
||||||
</Style>
|
|
||||||
<Style Selector="ctxt|CHyperlink:pointerover">
|
|
||||||
<Setter Property="Foreground" Value="{DynamicResource SystemAccentColorLight1}" />
|
|
||||||
</Style>
|
|
||||||
<Style Selector="Grid.List">
|
|
||||||
<Style.Setters>
|
|
||||||
<Setter Property="Margin" Value="20,0,0,0"/>
|
|
||||||
</Style.Setters>
|
|
||||||
</Style>
|
|
||||||
</avalonia:MarkdownScrollViewer.Styles>
|
</avalonia:MarkdownScrollViewer.Styles>
|
||||||
</avalonia:MarkdownScrollViewer>
|
</avalonia:MarkdownScrollViewer>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@ -39,22 +39,17 @@
|
|||||||
Background="{DynamicResource ContentDialogBackground}">
|
Background="{DynamicResource ContentDialogBackground}">
|
||||||
<Border Background="{DynamicResource TaskDialogHeaderBackground}">
|
<Border Background="{DynamicResource TaskDialogHeaderBackground}">
|
||||||
<Grid Classes="node-header" VerticalAlignment="Top" ColumnDefinitions="Auto,*,Auto,Auto">
|
<Grid Classes="node-header" VerticalAlignment="Top" ColumnDefinitions="Auto,*,Auto,Auto">
|
||||||
<Button Grid.Column="0"
|
<controls:HyperlinkButton Grid.Column="0"
|
||||||
VerticalAlignment="Center"
|
Classes="icon-button icon-button-small broken-state-button"
|
||||||
IsVisible="{CompiledBinding Node.BrokenState, Converter={x:Static ObjectConverters.IsNotNull}}"
|
Margin="5 0 0 0"
|
||||||
Classes="icon-button icon-button-small"
|
Command="{CompiledBinding ShowBrokenState}"
|
||||||
Foreground="White"
|
IsVisible="{CompiledBinding Node.BrokenState, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||||
Background="#E74C4C"
|
ToolTip.Tip="{CompiledBinding Node.BrokenState}">
|
||||||
BorderBrush="#E74C4C"
|
<avalonia:MaterialIcon Kind="AlertCircle" />
|
||||||
Margin="5 0 0 0"
|
</controls:HyperlinkButton>
|
||||||
ToolTip.Tip="{CompiledBinding Node.BrokenState}"
|
|
||||||
Command="{CompiledBinding ShowBrokenState}">
|
|
||||||
<avalonia:MaterialIcon Kind="AlertCircle"></avalonia:MaterialIcon>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="10 0 0 0" Text="{CompiledBinding Node.Name}" ToolTip.Tip="{CompiledBinding Node.Description}" />
|
<TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="10 0 0 0" Text="{CompiledBinding Node.Name}" ToolTip.Tip="{CompiledBinding Node.Description}" />
|
||||||
|
|
||||||
|
|
||||||
<controls:HyperlinkButton Grid.Column="2"
|
<controls:HyperlinkButton Grid.Column="2"
|
||||||
IsVisible="{CompiledBinding Node.HelpUrl, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
IsVisible="{CompiledBinding Node.HelpUrl, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
|
|||||||
60
src/Artemis.UI/Styles/Markdown.axaml
Normal file
60
src/Artemis.UI/Styles/Markdown.axaml
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<Styles xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:avalonia="clr-namespace:Markdown.Avalonia;assembly=Markdown.Avalonia"
|
||||||
|
xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia">
|
||||||
|
<Style Selector="ctxt|CHyperlink">
|
||||||
|
<Setter Property="Foreground" Value="{DynamicResource SystemAccentColorLight3}" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="ctxt|CHyperlink:pointerover">
|
||||||
|
<Setter Property="Foreground" Value="{DynamicResource SystemAccentColorLight1}" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Grid.List">
|
||||||
|
<Style.Setters>
|
||||||
|
<Setter Property="Margin" Value="10,0,0,0" />
|
||||||
|
</Style.Setters>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="ctxt|CTextBlock">
|
||||||
|
<Style.Setters>
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="Margin" Value="0,5" />
|
||||||
|
</Style.Setters>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="TextBlock">
|
||||||
|
<Style.Setters>
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
</Style.Setters>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="ctxt|CTextBlock.Heading1">
|
||||||
|
<Style.Setters>
|
||||||
|
<Setter Property="FontSize" Value="28" />
|
||||||
|
<Setter Property="FontWeight" Value="SemiBold" />
|
||||||
|
<Setter Property="Margin" Value="0,15,0,5" />
|
||||||
|
</Style.Setters>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="ctxt|CTextBlock.Heading2">
|
||||||
|
<Style.Setters>
|
||||||
|
<Setter Property="FontSize" Value="22" />
|
||||||
|
<Setter Property="FontWeight" Value="SemiBold" />
|
||||||
|
<Setter Property="Margin" Value="0,15,0,5" />
|
||||||
|
</Style.Setters>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="ctxt|CTextBlock.Heading3">
|
||||||
|
<Style.Setters>
|
||||||
|
<Setter Property="FontSize" Value="18" />
|
||||||
|
<Setter Property="FontWeight" Value="SemiBold" />
|
||||||
|
<Setter Property="Margin" Value="0,10,0,5" />
|
||||||
|
</Style.Setters>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="ctxt|CTextBlock.Heading4">
|
||||||
|
<Style.Setters>
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="FontWeight" Value="SemiBold" />
|
||||||
|
<Setter Property="Margin" Value="0,10,0,5" />
|
||||||
|
</Style.Setters>
|
||||||
|
</Style>
|
||||||
|
</Styles>
|
||||||
Loading…
x
Reference in New Issue
Block a user