mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Added dialog VMs
This commit is contained in:
parent
93cfc0e001
commit
8a7f8cff96
@ -6,8 +6,12 @@
|
|||||||
<ApplicationIcon />
|
<ApplicationIcon />
|
||||||
<StartupObject />
|
<StartupObject />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DocumentationFile>C:\Repos\Artemis\src\Artemis.UI.Avalonia.Shared\Artemis.UI.Avalonia.Shared.xml</DocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="0.10.10" />
|
<PackageReference Include="Avalonia" Version="0.10.10" />
|
||||||
|
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.10" />
|
||||||
<PackageReference Include="Avalonia.Svg.Skia" Version="0.10.8.3" />
|
<PackageReference Include="Avalonia.Svg.Skia" Version="0.10.8.3" />
|
||||||
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.10" />
|
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.10" />
|
||||||
<PackageReference Include="Avalonia.Xaml.Interactions" Version="0.10.10" />
|
<PackageReference Include="Avalonia.Xaml.Interactions" Version="0.10.10" />
|
||||||
|
|||||||
85
src/Artemis.UI.Avalonia.Shared/ViewModelBase.cs
Normal file
85
src/Artemis.UI.Avalonia.Shared/ViewModelBase.cs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reactive;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Avalonia.Shared
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the base class for Artemis view models
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ViewModelBase : ReactiveObject
|
||||||
|
{
|
||||||
|
private string? _displayName;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the display name of the view model
|
||||||
|
/// </summary>
|
||||||
|
public string? DisplayName
|
||||||
|
{
|
||||||
|
get => _displayName;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _displayName, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the base class for Artemis view models that are interested in the activated event
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ActivatableViewModelBase : ViewModelBase, IActivatableViewModel, IDisposable
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected ActivatableViewModelBase()
|
||||||
|
{
|
||||||
|
this.WhenActivated(disposables => Disposable.Create(Dispose).DisposeWith(disposables));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">
|
||||||
|
/// <see langword="true" /> to release both managed and unmanaged resources;
|
||||||
|
/// <see langword="false" /> to release only unmanaged resources.
|
||||||
|
/// </param>
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ViewModelActivator Activator { get; } = new();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the base class for Artemis view models used to drive dialogs
|
||||||
|
/// </summary>
|
||||||
|
public abstract class DialogViewModelBase<TResult> : ActivatableViewModelBase
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected DialogViewModelBase()
|
||||||
|
{
|
||||||
|
Close = ReactiveCommand.Create<TResult, TResult>(t => t);
|
||||||
|
Cancel = ReactiveCommand.Create(() => { });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the dialog with a given result
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveCommand<TResult, TResult> Close { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes the dialog without a result
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveCommand<Unit, Unit> Cancel { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,6 +17,17 @@
|
|||||||
"System.ValueTuple": "4.5.0"
|
"System.ValueTuple": "4.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Avalonia.ReactiveUI": {
|
||||||
|
"type": "Direct",
|
||||||
|
"requested": "[0.10.10, )",
|
||||||
|
"resolved": "0.10.10",
|
||||||
|
"contentHash": "hDMPhusehGxsHpwaFQwGOgEmAuFLp9VVnFDrX6Le1+8idpfxgHYWyzqo4uVYUiEO1OC2ab0Ik9Un/utLZcvh7w==",
|
||||||
|
"dependencies": {
|
||||||
|
"Avalonia": "0.10.10",
|
||||||
|
"ReactiveUI": "13.2.10",
|
||||||
|
"System.Reactive": "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"Avalonia.Svg.Skia": {
|
"Avalonia.Svg.Skia": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[0.10.8.3, )",
|
"requested": "[0.10.8.3, )",
|
||||||
@ -191,6 +202,14 @@
|
|||||||
"System.Xml.XmlDocument": "4.3.0"
|
"System.Xml.XmlDocument": "4.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"DynamicData": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "7.1.1",
|
||||||
|
"contentHash": "Pc6J5bFnSxEa64PV2V67FMcLlDdpv6m+zTBKSnRN3aLon/WtWWy8kuDpHFbJlgXHtqc6Nxloj9ItuvDlvKC/8w==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Reactive": "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"EmbedIO": {
|
"EmbedIO": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "3.4.3",
|
"resolved": "3.4.3",
|
||||||
@ -457,6 +476,17 @@
|
|||||||
"Ninject": "3.3.3"
|
"Ninject": "3.3.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ReactiveUI": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "13.2.10",
|
||||||
|
"contentHash": "fOCbEZ+RsO2Jhv6vB8VX+ZEvczYJaC95atcSG7oXohJeL/sEwbbqvv9k+tbj2l4bRSj2j5CQvhwA3HNLaxlCAg==",
|
||||||
|
"dependencies": {
|
||||||
|
"DynamicData": "7.1.1",
|
||||||
|
"Splat": "10.0.1",
|
||||||
|
"System.Reactive": "5.0.0",
|
||||||
|
"System.Runtime.Serialization.Primitives": "4.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
|
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "4.3.0",
|
"resolved": "4.3.0",
|
||||||
@ -623,6 +653,11 @@
|
|||||||
"SkiaSharp": "2.80.2"
|
"SkiaSharp": "2.80.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Splat": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "10.0.1",
|
||||||
|
"contentHash": "N8BMGVuUBnVLAHSVbna/st8XiLd8ulF3BfkKUSGCPqYpDCis3ELvM+aFaZQLBUIBEcweCYVLq3HFEBqHkCKFyA=="
|
||||||
|
},
|
||||||
"Svg.Custom": {
|
"Svg.Custom": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "0.5.8.3",
|
"resolved": "0.5.8.3",
|
||||||
@ -1264,6 +1299,15 @@
|
|||||||
"System.Runtime.Extensions": "4.3.0"
|
"System.Runtime.Extensions": "4.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"System.Runtime.Serialization.Primitives": {
|
||||||
|
"type": "Transitive",
|
||||||
|
"resolved": "4.3.0",
|
||||||
|
"contentHash": "Wz+0KOukJGAlXjtKr+5Xpuxf8+c8739RI1C+A2BoQZT+wMCCoMDDdO8/4IRHfaVINqL78GO8dW8G2lW/e45Mcw==",
|
||||||
|
"dependencies": {
|
||||||
|
"System.Resources.ResourceManager": "4.3.0",
|
||||||
|
"System.Runtime": "4.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"System.Security.AccessControl": {
|
"System.Security.AccessControl": {
|
||||||
"type": "Transitive",
|
"type": "Transitive",
|
||||||
"resolved": "5.0.0",
|
"resolved": "5.0.0",
|
||||||
|
|||||||
@ -4,6 +4,9 @@
|
|||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DocumentationFile></DocumentationFile>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Models\" />
|
<Folder Include="Models\" />
|
||||||
<AvaloniaResource Include="Assets\**" />
|
<AvaloniaResource Include="Assets\**" />
|
||||||
@ -11,9 +14,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Assets\Images\home-banner.png" />
|
<None Remove="Assets\Images\home-banner.png" />
|
||||||
<None Remove="Screens\Settings\Tabs\Plugins\Views\PluginFeatureView.xaml" />
|
|
||||||
<None Remove="Screens\Settings\Tabs\Plugins\Views\PluginSettingsView.xaml" />
|
|
||||||
<None Remove="Screens\Settings\Tabs\Plugins\Views\PluginSettingsWindowView.xaml" />
|
|
||||||
<None Remove="Screens\SurfaceEditor\Views\ListDeviceView.xaml" />
|
<None Remove="Screens\SurfaceEditor\Views\ListDeviceView.xaml" />
|
||||||
<None Remove="Screens\SurfaceEditor\Views\SurfaceDeviceView.xaml" />
|
<None Remove="Screens\SurfaceEditor\Views\SurfaceDeviceView.xaml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -50,6 +50,15 @@
|
|||||||
<Compile Update="Screens\Device\Tabs\Views\InputMappingsTabView.axaml.cs">
|
<Compile Update="Screens\Device\Tabs\Views\InputMappingsTabView.axaml.cs">
|
||||||
<DependentUpon>%(Filename)</DependentUpon>
|
<DependentUpon>%(Filename)</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="Screens\Plugins\Views\PluginFeatureView.axaml.cs">
|
||||||
|
<DependentUpon>%(Filename)</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Screens\Plugins\Views\PluginSettingsView.axaml.cs">
|
||||||
|
<DependentUpon>%(Filename)</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Screens\Plugins\Views\PluginSettingsWindowView.axaml.cs">
|
||||||
|
<DependentUpon>%(Filename)</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Update="Screens\Root\Views\SidebarCategoryView.axaml.cs">
|
<Compile Update="Screens\Root\Views\SidebarCategoryView.axaml.cs">
|
||||||
<DependentUpon>%(Filename)</DependentUpon>
|
<DependentUpon>%(Filename)</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -62,7 +71,7 @@
|
|||||||
<Compile Update="Screens\Root\Views\SidebarView.axaml.cs">
|
<Compile Update="Screens\Root\Views\SidebarView.axaml.cs">
|
||||||
<DependentUpon>%(Filename)</DependentUpon>
|
<DependentUpon>%(Filename)</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Update="Screens\Settings\Tabs\Plugins\Views\PluginsTabView.axaml.cs">
|
<Compile Update="Screens\Settings\Tabs\Views\PluginsTabView.axaml.cs">
|
||||||
<DependentUpon>%(Filename)</DependentUpon>
|
<DependentUpon>%(Filename)</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Update="Screens\Sidebar\Views\SidebarView.axaml.cs">
|
<Compile Update="Screens\Sidebar\Views\SidebarView.axaml.cs">
|
||||||
@ -83,18 +92,6 @@
|
|||||||
<Content Include="Assets\Images\Logo\bow.ico" />
|
<Content Include="Assets\Images\Logo\bow.ico" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Include="Screens\Settings\Tabs\Plugins\Views\PluginFeatureView.xaml">
|
|
||||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="Screens\Settings\Tabs\Plugins\Views\PluginSettingsView.xaml">
|
|
||||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="Screens\Settings\Tabs\Plugins\Views\PluginSettingsWindowView.xaml">
|
|
||||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="Screens\SurfaceEditor\Views\ListDeviceView.xaml">
|
<Page Include="Screens\SurfaceEditor\Views\ListDeviceView.xaml">
|
||||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.UI.Avalonia;
|
||||||
|
using Artemis.UI.Avalonia.Shared;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Plugins
|
||||||
|
{
|
||||||
|
public class PluginPrerequisiteActionViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public PluginPrerequisiteActionViewModel(PluginPrerequisiteAction action)
|
||||||
|
{
|
||||||
|
Action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginPrerequisiteAction Action { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,133 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Plugins
|
||||||
|
{
|
||||||
|
public class PluginPrerequisiteViewModel : Conductor<PluginPrerequisiteActionViewModel>.Collection.OneActive
|
||||||
|
{
|
||||||
|
private readonly bool _uninstall;
|
||||||
|
private bool _installing;
|
||||||
|
private bool _uninstalling;
|
||||||
|
private bool _isMet;
|
||||||
|
|
||||||
|
public PluginPrerequisiteViewModel(PluginPrerequisite pluginPrerequisite, bool uninstall)
|
||||||
|
{
|
||||||
|
_uninstall = uninstall;
|
||||||
|
PluginPrerequisite = pluginPrerequisite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginPrerequisite PluginPrerequisite { get; }
|
||||||
|
|
||||||
|
public bool Installing
|
||||||
|
{
|
||||||
|
get => _installing;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetAndNotify(ref _installing, value);
|
||||||
|
NotifyOfPropertyChange(nameof(Busy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Uninstalling
|
||||||
|
{
|
||||||
|
get => _uninstalling;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetAndNotify(ref _uninstalling, value);
|
||||||
|
NotifyOfPropertyChange(nameof(Busy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsMet
|
||||||
|
{
|
||||||
|
get => _isMet;
|
||||||
|
set => SetAndNotify(ref _isMet, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Busy => Installing || Uninstalling;
|
||||||
|
public int ActiveStemNumber => Items.IndexOf(ActiveItem) + 1;
|
||||||
|
public bool HasMultipleActions => Items.Count > 1;
|
||||||
|
|
||||||
|
public async Task Install(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (Busy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Installing = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await PluginPrerequisite.Install(cancellationToken);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Installing = false;
|
||||||
|
IsMet = PluginPrerequisite.IsMet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Uninstall(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (Busy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Uninstalling = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await PluginPrerequisite.Uninstall(cancellationToken);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Uninstalling = false;
|
||||||
|
IsMet = PluginPrerequisite.IsMet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PluginPrerequisiteOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.PropertyName == nameof(PluginPrerequisite.CurrentAction))
|
||||||
|
ActivateCurrentAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ActivateCurrentAction()
|
||||||
|
{
|
||||||
|
PluginPrerequisiteActionViewModel newActiveItem = Items.FirstOrDefault(i => i.Action == PluginPrerequisite.CurrentAction);
|
||||||
|
if (newActiveItem == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ActiveItem = newActiveItem;
|
||||||
|
NotifyOfPropertyChange(nameof(ActiveStemNumber));
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of Screen
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnClose()
|
||||||
|
{
|
||||||
|
PluginPrerequisite.PropertyChanged -= PluginPrerequisiteOnPropertyChanged;
|
||||||
|
base.OnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnInitialActivate()
|
||||||
|
{
|
||||||
|
PluginPrerequisite.PropertyChanged += PluginPrerequisiteOnPropertyChanged;
|
||||||
|
// Could be slow so take it off of the UI thread
|
||||||
|
Task.Run(() => IsMet = PluginPrerequisite.IsMet());
|
||||||
|
|
||||||
|
Items.AddRange(!_uninstall
|
||||||
|
? PluginPrerequisite.InstallActions.Select(a => new PluginPrerequisiteActionViewModel(a))
|
||||||
|
: PluginPrerequisite.UninstallActions.Select(a => new PluginPrerequisiteActionViewModel(a)));
|
||||||
|
|
||||||
|
base.OnInitialActivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,153 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.UI.Avalonia.Shared;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Plugins
|
||||||
|
{
|
||||||
|
public class PluginPrerequisitesInstallDialogViewModel : DialogViewModelBase<bool>
|
||||||
|
{
|
||||||
|
private PluginPrerequisiteViewModel _activePrerequisite;
|
||||||
|
private bool _canInstall;
|
||||||
|
private bool _showFailed;
|
||||||
|
private bool _showInstall = true;
|
||||||
|
private bool _showIntro = true;
|
||||||
|
private bool _showProgress;
|
||||||
|
private CancellationTokenSource? _tokenSource;
|
||||||
|
|
||||||
|
public PluginPrerequisitesInstallDialogViewModel(List<IPrerequisitesSubject> subjects, IPrerequisitesVmFactory prerequisitesVmFactory, IDialogService dialogService)
|
||||||
|
{
|
||||||
|
Prerequisites = new ObservableCollection<PluginPrerequisiteViewModel>();
|
||||||
|
foreach (IPrerequisitesSubject prerequisitesSubject in subjects)
|
||||||
|
Prerequisites.AddRange(prerequisitesSubject.Prerequisites.Select(p => prerequisitesVmFactory.PluginPrerequisiteViewModel(p, false)));
|
||||||
|
|
||||||
|
foreach (PluginPrerequisiteViewModel pluginPrerequisiteViewModel in Prerequisites)
|
||||||
|
pluginPrerequisiteViewModel.ConductWith(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableCollection<PluginPrerequisiteViewModel> Prerequisites { get; }
|
||||||
|
|
||||||
|
public PluginPrerequisiteViewModel ActivePrerequisite
|
||||||
|
{
|
||||||
|
get => _activePrerequisite;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _activePrerequisite, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShowProgress
|
||||||
|
{
|
||||||
|
get => _showProgress;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _showProgress, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShowIntro
|
||||||
|
{
|
||||||
|
get => _showIntro;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _showIntro, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShowFailed
|
||||||
|
{
|
||||||
|
get => _showFailed;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _showFailed, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShowInstall
|
||||||
|
{
|
||||||
|
get => _showInstall;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _showInstall, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanInstall
|
||||||
|
{
|
||||||
|
get => _canInstall;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _canInstall, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void Install()
|
||||||
|
{
|
||||||
|
CanInstall = false;
|
||||||
|
ShowFailed = false;
|
||||||
|
ShowIntro = false;
|
||||||
|
ShowProgress = true;
|
||||||
|
|
||||||
|
_tokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (PluginPrerequisiteViewModel pluginPrerequisiteViewModel in Prerequisites)
|
||||||
|
{
|
||||||
|
pluginPrerequisiteViewModel.IsMet = pluginPrerequisiteViewModel.PluginPrerequisite.IsMet();
|
||||||
|
if (pluginPrerequisiteViewModel.IsMet)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ActivePrerequisite = pluginPrerequisiteViewModel;
|
||||||
|
await ActivePrerequisite.Install(_tokenSource.Token);
|
||||||
|
|
||||||
|
if (!ActivePrerequisite.IsMet)
|
||||||
|
{
|
||||||
|
CanInstall = true;
|
||||||
|
ShowFailed = true;
|
||||||
|
ShowProgress = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait after the task finished for the user to process what happened
|
||||||
|
if (pluginPrerequisiteViewModel != Prerequisites.Last())
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowInstall = false;
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_tokenSource.Dispose();
|
||||||
|
_tokenSource = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Accept()
|
||||||
|
{
|
||||||
|
Result = true;
|
||||||
|
Close.Execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task<object> Show(IDialogService dialogService, List<IPrerequisitesSubject> subjects)
|
||||||
|
{
|
||||||
|
return dialogService.ShowDialog<PluginPrerequisitesInstallDialogViewModel>(new Dictionary<string, object> {{"subjects", subjects}});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_tokenSource?.Cancel();
|
||||||
|
_tokenSource?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of Screen
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnInitialActivate()
|
||||||
|
{
|
||||||
|
CanInstall = false;
|
||||||
|
Task.Run(() => CanInstall = Prerequisites.Any(p => !p.PluginPrerequisite.IsMet()));
|
||||||
|
|
||||||
|
base.OnInitialActivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,172 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Ninject.Factories;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using MaterialDesignThemes.Wpf;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Plugins
|
||||||
|
{
|
||||||
|
public class PluginPrerequisitesUninstallDialogViewModel : DialogViewModelBase
|
||||||
|
{
|
||||||
|
private readonly IDialogService _dialogService;
|
||||||
|
private readonly IPluginManagementService _pluginManagementService;
|
||||||
|
private readonly List<IPrerequisitesSubject> _subjects;
|
||||||
|
private PluginPrerequisiteViewModel _activePrerequisite;
|
||||||
|
private bool _canUninstall;
|
||||||
|
private bool _isFinished;
|
||||||
|
private CancellationTokenSource _tokenSource;
|
||||||
|
|
||||||
|
public PluginPrerequisitesUninstallDialogViewModel(List<IPrerequisitesSubject> subjects, string cancelLabel, IPrerequisitesVmFactory prerequisitesVmFactory,
|
||||||
|
IDialogService dialogService, IPluginManagementService pluginManagementService)
|
||||||
|
{
|
||||||
|
_subjects = subjects;
|
||||||
|
_dialogService = dialogService;
|
||||||
|
_pluginManagementService = pluginManagementService;
|
||||||
|
|
||||||
|
CancelLabel = cancelLabel;
|
||||||
|
Prerequisites = new BindableCollection<PluginPrerequisiteViewModel>();
|
||||||
|
foreach (IPrerequisitesSubject prerequisitesSubject in subjects)
|
||||||
|
Prerequisites.AddRange(prerequisitesSubject.Prerequisites.Select(p => prerequisitesVmFactory.PluginPrerequisiteViewModel(p, true)));
|
||||||
|
|
||||||
|
foreach (PluginPrerequisiteViewModel pluginPrerequisiteViewModel in Prerequisites)
|
||||||
|
pluginPrerequisiteViewModel.ConductWith(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CancelLabel { get; }
|
||||||
|
public BindableCollection<PluginPrerequisiteViewModel> Prerequisites { get; }
|
||||||
|
|
||||||
|
public PluginPrerequisiteViewModel ActivePrerequisite
|
||||||
|
{
|
||||||
|
get => _activePrerequisite;
|
||||||
|
set => SetAndNotify(ref _activePrerequisite, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanUninstall
|
||||||
|
{
|
||||||
|
get => _canUninstall;
|
||||||
|
set => SetAndNotify(ref _canUninstall, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsFinished
|
||||||
|
{
|
||||||
|
get => _isFinished;
|
||||||
|
set => SetAndNotify(ref _isFinished, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of DialogViewModelBase
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnDialogClosed(object sender, DialogClosingEventArgs e)
|
||||||
|
{
|
||||||
|
_tokenSource?.Cancel();
|
||||||
|
base.OnDialogClosed(sender, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public async void Uninstall()
|
||||||
|
{
|
||||||
|
CanUninstall = false;
|
||||||
|
|
||||||
|
// Disable all subjects that are plugins, this will disable their features too
|
||||||
|
foreach (IPrerequisitesSubject prerequisitesSubject in _subjects)
|
||||||
|
{
|
||||||
|
if (prerequisitesSubject is PluginInfo pluginInfo)
|
||||||
|
_pluginManagementService.DisablePlugin(pluginInfo.Plugin, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable all subjects that are features if still required
|
||||||
|
foreach (IPrerequisitesSubject prerequisitesSubject in _subjects)
|
||||||
|
{
|
||||||
|
if (prerequisitesSubject is not PluginFeatureInfo featureInfo)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Disable the parent plugin if the feature is AlwaysEnabled
|
||||||
|
if (featureInfo.AlwaysEnabled)
|
||||||
|
_pluginManagementService.DisablePlugin(featureInfo.Plugin, true);
|
||||||
|
else if (featureInfo.Instance != null)
|
||||||
|
_pluginManagementService.DisablePluginFeature(featureInfo.Instance, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_tokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (PluginPrerequisiteViewModel pluginPrerequisiteViewModel in Prerequisites)
|
||||||
|
{
|
||||||
|
pluginPrerequisiteViewModel.IsMet = pluginPrerequisiteViewModel.PluginPrerequisite.IsMet();
|
||||||
|
if (!pluginPrerequisiteViewModel.IsMet)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ActivePrerequisite = pluginPrerequisiteViewModel;
|
||||||
|
await ActivePrerequisite.Uninstall(_tokenSource.Token);
|
||||||
|
|
||||||
|
// Wait after the task finished for the user to process what happened
|
||||||
|
if (pluginPrerequisiteViewModel != Prerequisites.Last())
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Prerequisites.All(p => !p.IsMet))
|
||||||
|
{
|
||||||
|
IsFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This shouldn't be happening and the experience isn't very nice for the user (too lazy to make a nice UI for such an edge case)
|
||||||
|
// but at least give some feedback
|
||||||
|
Session?.Close(false);
|
||||||
|
await _dialogService.ShowConfirmDialog(
|
||||||
|
"Plugin prerequisites",
|
||||||
|
"The plugin was not able to fully remove all prerequisites. \r\nPlease try again or contact the plugin creator.",
|
||||||
|
"Confirm",
|
||||||
|
""
|
||||||
|
);
|
||||||
|
await Show(_dialogService, _subjects);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
CanUninstall = true;
|
||||||
|
_tokenSource.Dispose();
|
||||||
|
_tokenSource = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Accept()
|
||||||
|
{
|
||||||
|
Session?.Close(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task<object> Show(IDialogService dialogService, List<IPrerequisitesSubject> subjects, string cancelLabel = "CANCEL")
|
||||||
|
{
|
||||||
|
return dialogService.ShowDialog<PluginPrerequisitesUninstallDialogViewModel>(new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{"subjects", subjects},
|
||||||
|
{"cancelLabel", cancelLabel},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of Screen
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnInitialActivate()
|
||||||
|
{
|
||||||
|
CanUninstall = false;
|
||||||
|
// Could be slow so take it off of the UI thread
|
||||||
|
Task.Run(() => CanUninstall = Prerequisites.Any(p => p.PluginPrerequisite.IsMet()));
|
||||||
|
|
||||||
|
base.OnInitialActivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,106 +0,0 @@
|
|||||||
<UserControl x:Class="Artemis.UI.Screens.Settings.Tabs.Plugins.PluginFeatureView"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.Settings.Tabs.Plugins"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
|
||||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:viewModels="clr-namespace:Artemis.UI.Avalonia.Screens.Settings.Tabs.Plugins.ViewModels"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
|
||||||
d:DataContext="{d:DesignInstance viewModels:PluginFeatureViewModel}">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary
|
|
||||||
Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.PopupBox.xaml" />
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
|
||||||
</ResourceDictionary>
|
|
||||||
</UserControl.Resources>
|
|
||||||
<Grid Margin="-3 -8">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="30" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<!-- Icon column -->
|
|
||||||
<shared:ArtemisIcon Grid.Column="0"
|
|
||||||
Icon="{Binding FeatureInfo.ResolvedIcon}"
|
|
||||||
Width="20"
|
|
||||||
Height="20"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
Visibility="{Binding LoadException, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted, FallbackValue=Collapsed}" />
|
|
||||||
|
|
||||||
<Button Grid.Column="0"
|
|
||||||
Margin="-8"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
Visibility="{Binding LoadException, Converter={StaticResource NullToVisibilityConverter}, FallbackValue=Collapsed}"
|
|
||||||
Style="{StaticResource MaterialDesignIconButton}"
|
|
||||||
Foreground="#E74C4C"
|
|
||||||
ToolTip="An exception occurred while enabling this feature, click to view"
|
|
||||||
Command="{s:Action ViewLoadException}">
|
|
||||||
<materialDesign:PackIcon Kind="AlertCircle" />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<!-- Display name column -->
|
|
||||||
<TextBlock Grid.Column="1"
|
|
||||||
Text="{Binding FeatureInfo.Name}"
|
|
||||||
Style="{StaticResource MaterialDesignTextBlock}"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
ToolTip="{Binding FeatureInfo.Description}" />
|
|
||||||
|
|
||||||
<!-- Enable toggle column -->
|
|
||||||
<StackPanel Grid.Column="2"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
Margin="8"
|
|
||||||
Visibility="{Binding Enabling, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay, FallbackValue=Collapsed}"
|
|
||||||
Orientation="Horizontal"
|
|
||||||
VerticalAlignment="Top"
|
|
||||||
ToolTip="This feature cannot be disabled without disabling the whole plugin"
|
|
||||||
ToolTipService.IsEnabled="{Binding FeatureInfo.AlwaysEnabled}">
|
|
||||||
<materialDesign:PackIcon Kind="ShieldHalfFull"
|
|
||||||
ToolTip="Plugin requires admin rights"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Margin="0 0 5 0"
|
|
||||||
Visibility="{Binding ShowShield, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
|
|
||||||
<CheckBox Style="{StaticResource MaterialDesignCheckBox}"
|
|
||||||
IsChecked="{Binding IsEnabled}"
|
|
||||||
IsEnabled="{Binding CanToggleEnabled}">
|
|
||||||
Feature enabled
|
|
||||||
</CheckBox>
|
|
||||||
|
|
||||||
<materialDesign:PopupBox Style="{StaticResource MaterialDesignToolPopupBox}"
|
|
||||||
Margin="0 -4 -10 -4"
|
|
||||||
Foreground="{StaticResource MaterialDesignBody}"
|
|
||||||
IsEnabled="{Binding IsPopupEnabled}">
|
|
||||||
<StackPanel>
|
|
||||||
<Button Command="{s:Action InstallPrerequisites}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="CheckAll" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
|
||||||
<TextBlock VerticalAlignment="Center">Install prerequisites</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
<Button Command="{s:Action RemovePrerequisites}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="Delete" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
|
||||||
<TextBlock VerticalAlignment="Center">Remove prerequisites</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
</StackPanel>
|
|
||||||
</materialDesign:PopupBox>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="7"
|
|
||||||
Visibility="{Binding Enabling, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay, FallbackValue=Collapsed}">
|
|
||||||
<ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}" Value="0" IsIndeterminate="True" />
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
</Grid>
|
|
||||||
</UserControl>
|
|
||||||
@ -1,209 +0,0 @@
|
|||||||
<UserControl x:Class="Artemis.UI.Screens.Settings.Tabs.Plugins.PluginSettingsView"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
|
||||||
xmlns:devices="clr-namespace:Artemis.UI.Screens.Settings.Tabs.Plugins"
|
|
||||||
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
|
|
||||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
|
||||||
xmlns:behaviors="clr-namespace:Artemis.UI.Behaviors"
|
|
||||||
d:DataContext="{d:DesignInstance devices:PluginSettingsViewModel}"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.PopupBox.xaml" />
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
|
||||||
</ResourceDictionary>
|
|
||||||
</UserControl.Resources>
|
|
||||||
<materialDesign:Card Width="900">
|
|
||||||
<Grid Margin="8">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="4*" />
|
|
||||||
<ColumnDefinition Width="5*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<Grid Grid.Row="0" Margin="0 10">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="80" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<shared:ArtemisIcon Icon="{Binding Plugin.Info.ResolvedIcon}"
|
|
||||||
Width="48"
|
|
||||||
Height="48"
|
|
||||||
Margin="0 5 0 0"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.RowSpan="3"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
VerticalAlignment="Top" />
|
|
||||||
|
|
||||||
<TextBlock Grid.Column="1" Grid.Row="0" Style="{StaticResource MaterialDesignBody2TextBlock}"
|
|
||||||
behaviors:HighlightTermBehavior.TermToBeHighlighted="{Binding Parent.SearchPluginInput}"
|
|
||||||
behaviors:HighlightTermBehavior.Text="{Binding Plugin.Info.Name}"
|
|
||||||
behaviors:HighlightTermBehavior.HighlightForeground="{StaticResource Primary600Foreground}"
|
|
||||||
behaviors:HighlightTermBehavior.HighlightBackground="{StaticResource Primary600}" />
|
|
||||||
|
|
||||||
<TextBlock Grid.Column="1"
|
|
||||||
Grid.Row="1"
|
|
||||||
Style="{StaticResource MaterialDesignBody2TextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
|
|
||||||
Text="{Binding Plugin.Info.Author}"
|
|
||||||
Visibility="{Binding Plugin.Info.Author, Converter={StaticResource NullToVisibilityConverter}, Mode=OneWay}" />
|
|
||||||
|
|
||||||
<TextBlock Grid.Column="1"
|
|
||||||
Grid.Row="2"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
behaviors:HighlightTermBehavior.TermToBeHighlighted="{Binding Parent.SearchPluginInput}"
|
|
||||||
behaviors:HighlightTermBehavior.Text="{Binding Plugin.Info.Description}"
|
|
||||||
behaviors:HighlightTermBehavior.HighlightForeground="{StaticResource Primary600Foreground}"
|
|
||||||
behaviors:HighlightTermBehavior.HighlightBackground="{StaticResource Primary600}"
|
|
||||||
Style="{StaticResource MaterialDesignTextBlock}"
|
|
||||||
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" />
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid Grid.Row="1" Grid.Column="0">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<StackPanel VerticalAlignment="Bottom" Orientation="Horizontal">
|
|
||||||
<Button VerticalAlignment="Bottom"
|
|
||||||
Style="{StaticResource MaterialDesignRaisedButton}"
|
|
||||||
ToolTip="Open the plugins settings window"
|
|
||||||
Margin="4"
|
|
||||||
Command="{s:Action OpenSettings}">
|
|
||||||
SETTINGS
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<materialDesign:PopupBox Style="{StaticResource MaterialDesignToolPopupBox}"
|
|
||||||
Padding="2 0 2 0"
|
|
||||||
Foreground="{StaticResource MaterialDesignBody}"
|
|
||||||
IsPopupOpen="{Binding IsSettingsPopupOpen, Mode=TwoWay}">
|
|
||||||
<StackPanel>
|
|
||||||
<Button Command="{s:Action OpenPluginDirectory}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="FolderOpen" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
|
||||||
<TextBlock VerticalAlignment="Center">Open plugin directory</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
<Button Command="{s:Action Reload}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="Reload" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
|
||||||
<TextBlock VerticalAlignment="Center">Reload plugin</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
<Separator />
|
|
||||||
<Button Command="{s:Action InstallPrerequisites}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="CheckAll" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
|
||||||
<TextBlock VerticalAlignment="Center">Install prerequisites</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
<Button Command="{s:Action RemovePrerequisites}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="Delete" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
|
||||||
<TextBlock VerticalAlignment="Center">Remove prerequisites</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
<Separator />
|
|
||||||
<Button Command="{s:Action RemoveSettings}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="DatabaseRemove" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
|
||||||
<TextBlock VerticalAlignment="Center">Clear plugin settings</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
<Button Command="{s:Action Remove}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="DeleteForever" Margin="0 0 10 0 " VerticalAlignment="Center" />
|
|
||||||
<TextBlock VerticalAlignment="Center">Remove plugin</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
</StackPanel>
|
|
||||||
</materialDesign:PopupBox>
|
|
||||||
|
|
||||||
<Button Height="40"
|
|
||||||
Width="40"
|
|
||||||
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
|
||||||
ToolTip="{Binding Plugin.Info.Website}"
|
|
||||||
Visibility="{Binding Plugin.Info.Website, Converter={StaticResource NullToVisibilityConverter}, Mode=OneWay}"
|
|
||||||
Command="{s:Action OpenUri}"
|
|
||||||
CommandParameter="{Binding Plugin.Info.Website}">
|
|
||||||
<materialDesign:PackIcon Kind="Web" Width="20" Height="20" />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button Height="40"
|
|
||||||
Width="40"
|
|
||||||
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
|
||||||
ToolTip="{Binding Plugin.Info.Repository}"
|
|
||||||
Visibility="{Binding Plugin.Info.Repository, Converter={StaticResource NullToVisibilityConverter}, Mode=OneWay}"
|
|
||||||
Command="{s:Action OpenUri}"
|
|
||||||
CommandParameter="{Binding Plugin.Info.Repository}">
|
|
||||||
<materialDesign:PackIcon Kind="Git" Width="20" Height="20" />
|
|
||||||
</Button>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<CheckBox Grid.Row="0"
|
|
||||||
Grid.Column="1"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
VerticalAlignment="Bottom"
|
|
||||||
Margin="8"
|
|
||||||
Visibility="{Binding Enabling, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}"
|
|
||||||
Style="{StaticResource MaterialDesignAccentCheckBox}" IsChecked="{Binding IsEnabled}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<TextBlock>Plugin enabled</TextBlock>
|
|
||||||
<materialDesign:PackIcon Kind="ShieldHalfFull"
|
|
||||||
Margin="5 0 0 0"
|
|
||||||
ToolTip="Plugin requires admin rights"
|
|
||||||
Visibility="{Binding Plugin.Info.RequiresAdmin, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
|
|
||||||
</StackPanel>
|
|
||||||
</CheckBox>
|
|
||||||
|
|
||||||
<ProgressBar Grid.Row="0"
|
|
||||||
Grid.Column="1"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
VerticalAlignment="Bottom"
|
|
||||||
Margin="8"
|
|
||||||
Visibility="{Binding Enabling, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}"
|
|
||||||
Style="{StaticResource MaterialDesignCircularProgressBar}" Value="0"
|
|
||||||
IsIndeterminate="True" />
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Border Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" BorderBrush="{StaticResource MaterialDesignDivider}" BorderThickness="1 0 0 0" Margin="10 0 0 0" Padding="10 0 0 0">
|
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<TextBlock Margin="10 10 0 5" Style="{StaticResource MaterialDesignBody2TextBlock}">Plugin features</TextBlock>
|
|
||||||
<ListBox Grid.Row="1"
|
|
||||||
MaxHeight="135"
|
|
||||||
ItemsSource="{Binding Items}"
|
|
||||||
HorizontalContentAlignment="Stretch"
|
|
||||||
VirtualizingPanel.ScrollUnit="Pixel">
|
|
||||||
<b:Interaction.Behaviors>
|
|
||||||
<shared:ScrollParentWhenAtMax />
|
|
||||||
</b:Interaction.Behaviors>
|
|
||||||
<ListBox.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<ContentControl s:View.Model="{Binding IsAsync=True}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
|
|
||||||
</DataTemplate>
|
|
||||||
</ListBox.ItemTemplate>
|
|
||||||
</ListBox>
|
|
||||||
</Grid>
|
|
||||||
</Border>
|
|
||||||
</Grid>
|
|
||||||
</materialDesign:Card>
|
|
||||||
</UserControl>
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
<controls:MaterialWindow x:Class="Artemis.UI.Screens.Settings.Tabs.Plugins.PluginSettingsWindowView"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
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:local="clr-namespace:Artemis.UI.Screens.Settings.Tabs.Plugins"
|
|
||||||
xmlns:controls="clr-namespace:MaterialDesignExtensions.Controls;assembly=MaterialDesignExtensions"
|
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
|
||||||
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
Title="Plugin Configuration | Artemis"
|
|
||||||
Background="{DynamicResource MaterialDesignPaper}"
|
|
||||||
FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
|
|
||||||
UseLayoutRounding="True"
|
|
||||||
Width="800"
|
|
||||||
Height="800"
|
|
||||||
d:DesignHeight="800"
|
|
||||||
d:DesignWidth="800"
|
|
||||||
d:DataContext="{d:DesignInstance local:PluginSettingsWindowViewModel}"
|
|
||||||
Icon="/Resources/Images/Logo/bow.ico">
|
|
||||||
<materialDesign:DialogHost IsTabStop="False"
|
|
||||||
Focusable="False"
|
|
||||||
Identifier="PluginSettingsDialog"
|
|
||||||
DialogTheme="Inherit">
|
|
||||||
<DockPanel>
|
|
||||||
<controls:AppBar Type="Dense" Title="{Binding ActiveItem.Plugin.Info.Name}" DockPanel.Dock="Top" Margin="-18 0 0 0" ShowShadow="False">
|
|
||||||
<controls:AppBar.AppIcon>
|
|
||||||
<shared:ArtemisIcon Icon="{Binding Plugin.Info.ResolvedIcon}"
|
|
||||||
Margin="0 5 0 0"
|
|
||||||
Width="20"
|
|
||||||
Height="20"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.RowSpan="3"
|
|
||||||
HorizontalAlignment="Center"
|
|
||||||
VerticalAlignment="Top" />
|
|
||||||
</controls:AppBar.AppIcon>
|
|
||||||
</controls:AppBar>
|
|
||||||
|
|
||||||
<ContentControl s:View.Model="{Binding ActiveItem}" />
|
|
||||||
</DockPanel>
|
|
||||||
</materialDesign:DialogHost>
|
|
||||||
</controls:MaterialWindow>
|
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Artemis.UI.Avalonia.Shared;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
|
|
||||||
|
|||||||
@ -1,49 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Reactive.Disposables;
|
|
||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Avalonia
|
|
||||||
{
|
|
||||||
public abstract class ViewModelBase : ReactiveObject
|
|
||||||
{
|
|
||||||
private string? _displayName;
|
|
||||||
|
|
||||||
public string? DisplayName
|
|
||||||
{
|
|
||||||
get => _displayName;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _displayName, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class ActivatableViewModelBase : ViewModelBase, IActivatableViewModel, IDisposable
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected ActivatableViewModelBase()
|
|
||||||
{
|
|
||||||
this.WhenActivated(disposables =>
|
|
||||||
{
|
|
||||||
Disposable.Create(Dispose).DisposeWith(disposables);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#region IDisposable
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public ViewModelActivator Activator { get; } = new();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1695,6 +1695,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Artemis.Core": "1.0.0",
|
"Artemis.Core": "1.0.0",
|
||||||
"Avalonia": "0.10.10",
|
"Avalonia": "0.10.10",
|
||||||
|
"Avalonia.ReactiveUI": "0.10.10",
|
||||||
"Avalonia.Svg.Skia": "0.10.8.3",
|
"Avalonia.Svg.Skia": "0.10.8.3",
|
||||||
"Avalonia.Xaml.Behaviors": "0.10.10",
|
"Avalonia.Xaml.Behaviors": "0.10.10",
|
||||||
"Avalonia.Xaml.Interactions": "0.10.10",
|
"Avalonia.Xaml.Interactions": "0.10.10",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user