mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Plugins - Added importing
This commit is contained in:
parent
f89e7d43fe
commit
b875e3d366
1
src/.idea/.idea.Artemis/.idea/avalonia.xml
generated
1
src/.idea/.idea.Artemis/.idea/avalonia.xml
generated
@ -75,6 +75,7 @@
|
|||||||
<entry key="Artemis.UI/Screens/Root/SplashView.axaml" value="Artemis.UI.Windows/Artemis.UI.Windows.csproj" />
|
<entry key="Artemis.UI/Screens/Root/SplashView.axaml" value="Artemis.UI.Windows/Artemis.UI.Windows.csproj" />
|
||||||
<entry key="Artemis.UI/Screens/Settings/Tabs/AboutTabView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
<entry key="Artemis.UI/Screens/Settings/Tabs/AboutTabView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||||
<entry key="Artemis.UI/Screens/Settings/Tabs/GeneralTabView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
<entry key="Artemis.UI/Screens/Settings/Tabs/GeneralTabView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||||
|
<entry key="Artemis.UI/Screens/Settings/Tabs/PluginsTabView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||||
<entry key="Artemis.UI/Screens/Sidebar/ContentDialogs/SidebarCategoryEditView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
<entry key="Artemis.UI/Screens/Sidebar/ContentDialogs/SidebarCategoryEditView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||||
<entry key="Artemis.UI/Screens/Sidebar/Dialogs/ModuleActivationRequirementView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
<entry key="Artemis.UI/Screens/Sidebar/Dialogs/ModuleActivationRequirementView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||||
<entry key="Artemis.UI/Screens/Sidebar/Dialogs/ModuleActivationRequirementsView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
<entry key="Artemis.UI/Screens/Sidebar/Dialogs/ModuleActivationRequirementsView.axaml" value="Artemis.UI.Linux/Artemis.UI.Linux.csproj" />
|
||||||
|
|||||||
@ -476,6 +476,7 @@ namespace Artemis.Core.Services
|
|||||||
lock (_plugins)
|
lock (_plugins)
|
||||||
{
|
{
|
||||||
_plugins.Remove(plugin);
|
_plugins.Remove(plugin);
|
||||||
|
OnPluginUnloaded(new PluginEventArgs(plugin));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,12 +2,15 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
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:settings="clr-namespace:Artemis.UI.Screens.Settings"
|
||||||
mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Settings.PluginsTabView">
|
x:Class="Artemis.UI.Screens.Settings.PluginsTabView"
|
||||||
|
x:DataType="settings:PluginsTabViewModel">
|
||||||
<Grid RowDefinitions="Auto,*" ColumnDefinitions="*,*" Width="900">
|
<Grid RowDefinitions="Auto,*" ColumnDefinitions="*,*" Width="900">
|
||||||
<TextBox Grid.Row="0" Grid.Column="0" Text="{Binding SearchPluginInput}" Watermark="Search plugins" Margin="0 10" />
|
<TextBox Grid.Row="0" Grid.Column="0" Classes="clearButton" Text="{CompiledBinding SearchPluginInput}" Watermark="Search plugins" Margin="0 10" />
|
||||||
|
<Button Grid.Row="0" Grid.Column="1" Classes="accent" Command="{CompiledBinding ImportPlugin}" HorizontalAlignment="Right">Import plugin</Button>
|
||||||
<ScrollViewer Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
<ScrollViewer Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||||
<ItemsControl Items="{Binding Plugins}" />
|
<ItemsControl Items="{CompiledBinding Plugins}" />
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reactive;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -14,6 +15,8 @@ using Artemis.UI.Shared;
|
|||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.UI.Shared.Services.Builders;
|
using Artemis.UI.Shared.Services.Builders;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
using DynamicData;
|
||||||
|
using DynamicData.Binding;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Settings
|
namespace Artemis.UI.Screens.Settings
|
||||||
@ -35,13 +38,34 @@ namespace Artemis.UI.Screens.Settings
|
|||||||
_settingsVmFactory = settingsVmFactory;
|
_settingsVmFactory = settingsVmFactory;
|
||||||
|
|
||||||
DisplayName = "Plugins";
|
DisplayName = "Plugins";
|
||||||
Plugins = new ObservableCollection<PluginSettingsViewModel>();
|
|
||||||
|
|
||||||
this.WhenAnyValue(x => x.SearchPluginInput).Throttle(TimeSpan.FromMilliseconds(100)).Subscribe(SearchPlugins);
|
SourceList<Plugin> plugins = new();
|
||||||
this.WhenActivated((CompositeDisposable _) => GetPluginInstances());
|
IObservable<Func<Plugin, bool>> pluginFilter = this.WhenAnyValue(vm => vm.SearchPluginInput).Throttle(TimeSpan.FromMilliseconds(100)).Select(CreatePredicate);
|
||||||
|
|
||||||
|
plugins.Connect()
|
||||||
|
.Filter(pluginFilter)
|
||||||
|
.Sort(SortExpressionComparer<Plugin>.Ascending(p => p.Info.Name))
|
||||||
|
.TransformAsync(p => Dispatcher.UIThread.InvokeAsync(() => _settingsVmFactory.CreatePluginSettingsViewModel(p), DispatcherPriority.Background))
|
||||||
|
.Bind(out ReadOnlyObservableCollection<PluginSettingsViewModel> pluginViewModels)
|
||||||
|
.Subscribe();
|
||||||
|
Plugins = pluginViewModels;
|
||||||
|
|
||||||
|
this.WhenActivated(d =>
|
||||||
|
{
|
||||||
|
plugins.AddRange(_pluginManagementService.GetAllPlugins());
|
||||||
|
Observable.FromEventPattern<PluginEventArgs>(x => _pluginManagementService.PluginLoaded += x, x => _pluginManagementService.PluginLoaded -= x)
|
||||||
|
.Subscribe(a => plugins.Add(a.EventArgs.Plugin))
|
||||||
|
.DisposeWith(d);
|
||||||
|
Observable.FromEventPattern<PluginEventArgs>(x => _pluginManagementService.PluginUnloaded += x, x => _pluginManagementService.PluginUnloaded -= x)
|
||||||
|
.Subscribe(a => plugins.Remove(a.EventArgs.Plugin))
|
||||||
|
.DisposeWith(d);
|
||||||
|
Disposable.Create(() => plugins.Clear()).DisposeWith(d);
|
||||||
|
});
|
||||||
|
ImportPlugin = ReactiveCommand.CreateFromTask(ExecuteImportPlugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<PluginSettingsViewModel> Plugins { get; }
|
public ReadOnlyObservableCollection<PluginSettingsViewModel> Plugins { get; }
|
||||||
|
public ReactiveCommand<Unit, Unit> ImportPlugin { get; }
|
||||||
|
|
||||||
public string? SearchPluginInput
|
public string? SearchPluginInput
|
||||||
{
|
{
|
||||||
@ -54,71 +78,43 @@ namespace Artemis.UI.Screens.Settings
|
|||||||
Utilities.OpenUrl(url);
|
Utilities.OpenUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ImportPlugin()
|
private async Task ExecuteImportPlugin()
|
||||||
{
|
{
|
||||||
string[]? files = await _windowService.CreateOpenFileDialog().WithTitle("Import Artemis plugin").HavingFilter(f => f.WithExtension("zip").WithName("ZIP files")).ShowAsync();
|
string[]? files = await _windowService.CreateOpenFileDialog().WithTitle("Import Artemis plugin").HavingFilter(f => f.WithExtension("zip").WithName("ZIP files")).ShowAsync();
|
||||||
if (files == null)
|
if (files == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Take the actual import off of the UI thread
|
try
|
||||||
await Task.Run(() =>
|
|
||||||
{
|
{
|
||||||
Plugin plugin = _pluginManagementService.ImportPlugin(files[0]);
|
Plugin plugin = _pluginManagementService.ImportPlugin(files[0]);
|
||||||
|
|
||||||
GetPluginInstances();
|
|
||||||
SearchPluginInput = plugin.Info.Name;
|
SearchPluginInput = plugin.Info.Name;
|
||||||
|
|
||||||
|
// Wait for the VM to be created asynchronously (it would be better to respond to some event here)
|
||||||
|
await Task.Delay(200);
|
||||||
// Enable it via the VM to enable the prerequisite dialog
|
// Enable it via the VM to enable the prerequisite dialog
|
||||||
PluginSettingsViewModel? pluginViewModel = Plugins.FirstOrDefault(i => i.Plugin == plugin);
|
PluginSettingsViewModel? pluginViewModel = Plugins.FirstOrDefault(i => i.Plugin == plugin);
|
||||||
if (pluginViewModel is {IsEnabled: false})
|
if (pluginViewModel is {IsEnabled: false})
|
||||||
pluginViewModel.IsEnabled = true;
|
pluginViewModel.IsEnabled = true;
|
||||||
|
|
||||||
_notificationService.CreateNotification()
|
_notificationService.CreateNotification()
|
||||||
.WithTitle("Success")
|
.WithTitle("Plugin imported")
|
||||||
.WithMessage($"Imported plugin: {plugin.Info.Name}")
|
.WithMessage($"Added the '{plugin.Info.Name}' plugin")
|
||||||
.WithSeverity(NotificationSeverity.Success)
|
.WithSeverity(NotificationSeverity.Success)
|
||||||
.Show();
|
.Show();
|
||||||
});
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
await _windowService.ShowConfirmContentDialog("Failed to import plugin", "Make sure the selected ZIP file is a valid Artemis plugin.\r\n" + e.Message, "Close", null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetPluginInstances()
|
private Func<Plugin, bool> CreatePredicate(string? text)
|
||||||
{
|
{
|
||||||
Plugins.Clear();
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
return _ => true;
|
||||||
{
|
|
||||||
_instances = _pluginManagementService.GetAllPlugins()
|
|
||||||
.Select(p => _settingsVmFactory.CreatePluginSettingsViewModel(p))
|
|
||||||
.OrderBy(i => i.Plugin.Info.Name)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
SearchPlugins(SearchPluginInput);
|
return data => data.Info.Name.Contains(text, StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
}, DispatcherPriority.Background);
|
(data.Info.Description != null && data.Info.Description.Contains(text, StringComparison.InvariantCultureIgnoreCase));
|
||||||
}
|
|
||||||
|
|
||||||
private void SearchPlugins(string? searchPluginInput)
|
|
||||||
{
|
|
||||||
if (_instances == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
List<PluginSettingsViewModel> instances = _instances;
|
|
||||||
string? search = searchPluginInput?.ToLower();
|
|
||||||
if (!string.IsNullOrWhiteSpace(search))
|
|
||||||
instances = instances.Where(i => i.Plugin.Info.Name.ToLower().Contains(search) ||
|
|
||||||
i.Plugin.Info.Description != null && i.Plugin.Info.Description.ToLower().Contains(search)).ToList();
|
|
||||||
|
|
||||||
foreach (PluginSettingsViewModel pluginSettingsViewModel in instances)
|
|
||||||
{
|
|
||||||
if (!Plugins.Contains(pluginSettingsViewModel))
|
|
||||||
Plugins.Add(pluginSettingsViewModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (PluginSettingsViewModel pluginSettingsViewModel in Plugins.ToList())
|
|
||||||
{
|
|
||||||
if (!instances.Contains(pluginSettingsViewModel))
|
|
||||||
Plugins.Remove(pluginSettingsViewModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
Plugins.Sort(i => i.Plugin.Info.Name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user