mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Workshop - Implemented workshop installation, layout selection and removal
This commit is contained in:
parent
dad6a56238
commit
28edabae89
@ -1,31 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Artemis.Core;
|
|
||||||
|
|
||||||
internal static class DirectoryInfoExtensions
|
|
||||||
{
|
|
||||||
public static void CopyFilesRecursively(this DirectoryInfo source, DirectoryInfo target)
|
|
||||||
{
|
|
||||||
foreach (DirectoryInfo dir in source.GetDirectories())
|
|
||||||
CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
|
|
||||||
foreach (FileInfo file in source.GetFiles())
|
|
||||||
file.CopyTo(Path.Combine(target.FullName, file.Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void DeleteRecursively(this DirectoryInfo baseDir)
|
|
||||||
{
|
|
||||||
if (!baseDir.Exists)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (DirectoryInfo dir in baseDir.EnumerateDirectories())
|
|
||||||
DeleteRecursively(dir);
|
|
||||||
FileInfo[] files = baseDir.GetFiles();
|
|
||||||
foreach (FileInfo file in files)
|
|
||||||
{
|
|
||||||
file.IsReadOnly = false;
|
|
||||||
file.Delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
baseDir.Delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -398,14 +398,6 @@ public class ArtemisDevice : CorePropertyChanged
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the <see cref="DeviceUpdated" /> event
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void OnDeviceUpdated()
|
|
||||||
{
|
|
||||||
DeviceUpdated?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies the provided layout to the device
|
/// Applies the provided layout to the device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -418,7 +410,7 @@ public class ArtemisDevice : CorePropertyChanged
|
|||||||
/// A boolean indicating whether to remove excess LEDs present in the device but missing
|
/// A boolean indicating whether to remove excess LEDs present in the device but missing
|
||||||
/// in the layout
|
/// in the layout
|
||||||
/// </param>
|
/// </param>
|
||||||
internal void ApplyLayout(ArtemisLayout? layout, bool createMissingLeds, bool removeExcessiveLeds)
|
public void ApplyLayout(ArtemisLayout? layout, bool createMissingLeds, bool removeExcessiveLeds)
|
||||||
{
|
{
|
||||||
if (layout != null && layout.IsValid && createMissingLeds && !DeviceProvider.CreateMissingLedsSupported)
|
if (layout != null && layout.IsValid && createMissingLeds && !DeviceProvider.CreateMissingLedsSupported)
|
||||||
throw new ArtemisCoreException($"Cannot apply layout with {nameof(createMissingLeds)} set to true because the device provider does not support it");
|
throw new ArtemisCoreException($"Cannot apply layout with {nameof(createMissingLeds)} set to true because the device provider does not support it");
|
||||||
@ -445,6 +437,14 @@ public class ArtemisDevice : CorePropertyChanged
|
|||||||
CalculateRenderProperties();
|
CalculateRenderProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="DeviceUpdated" /> event
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnDeviceUpdated()
|
||||||
|
{
|
||||||
|
DeviceUpdated?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
private void ClearLayout()
|
private void ClearLayout()
|
||||||
{
|
{
|
||||||
if (Layout == null)
|
if (Layout == null)
|
||||||
|
|||||||
@ -1,17 +1,8 @@
|
|||||||
using Artemis.Core.Services;
|
namespace Artemis.Core.Providers;
|
||||||
using RGB.NET.Layout;
|
|
||||||
|
|
||||||
namespace Artemis.Core.Providers;
|
|
||||||
|
|
||||||
public class CustomPathLayoutProvider : ILayoutProvider
|
public class CustomPathLayoutProvider : ILayoutProvider
|
||||||
{
|
{
|
||||||
public static string LayoutType = "CustomPath";
|
public static string LayoutType = "CustomPath";
|
||||||
private readonly IDeviceService _deviceService;
|
|
||||||
|
|
||||||
public CustomPathLayoutProvider(IDeviceService deviceService)
|
|
||||||
{
|
|
||||||
_deviceService = deviceService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
||||||
@ -42,7 +33,5 @@ public class CustomPathLayoutProvider : ILayoutProvider
|
|||||||
{
|
{
|
||||||
device.LayoutSelection.Type = LayoutType;
|
device.LayoutSelection.Type = LayoutType;
|
||||||
device.LayoutSelection.Parameter = path;
|
device.LayoutSelection.Parameter = path;
|
||||||
_deviceService.SaveDevice(device);
|
|
||||||
_deviceService.LoadDeviceLayout(device);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,16 +1,8 @@
|
|||||||
using Artemis.Core.Services;
|
namespace Artemis.Core.Providers;
|
||||||
|
|
||||||
namespace Artemis.Core.Providers;
|
|
||||||
|
|
||||||
public class DefaultLayoutProvider : ILayoutProvider
|
public class DefaultLayoutProvider : ILayoutProvider
|
||||||
{
|
{
|
||||||
public static string LayoutType = "Default";
|
public static string LayoutType = "Default";
|
||||||
private readonly IDeviceService _deviceService;
|
|
||||||
|
|
||||||
public DefaultLayoutProvider(IDeviceService deviceService)
|
|
||||||
{
|
|
||||||
_deviceService = deviceService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
||||||
@ -45,7 +37,5 @@ public class DefaultLayoutProvider : ILayoutProvider
|
|||||||
{
|
{
|
||||||
device.LayoutSelection.Type = LayoutType;
|
device.LayoutSelection.Type = LayoutType;
|
||||||
device.LayoutSelection.Parameter = null;
|
device.LayoutSelection.Parameter = null;
|
||||||
_deviceService.SaveDevice(device);
|
|
||||||
_deviceService.LoadDeviceLayout(device);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9,7 +9,7 @@ public interface ILayoutProvider
|
|||||||
/// If available, loads an Artemis layout for the provided device.
|
/// If available, loads an Artemis layout for the provided device.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="device">The device to load the layout for.</param>
|
/// <param name="device">The device to load the layout for.</param>
|
||||||
/// <returns>The resulting layout if one was available; otherwise <see langword="null"/>.</returns>
|
/// <returns>The resulting layout if one was available; otherwise <see langword="null" />.</returns>
|
||||||
ArtemisLayout? GetDeviceLayout(ArtemisDevice device);
|
ArtemisLayout? GetDeviceLayout(ArtemisDevice device);
|
||||||
|
|
||||||
void ApplyLayout(ArtemisDevice device, ArtemisLayout layout);
|
void ApplyLayout(ArtemisDevice device, ArtemisLayout layout);
|
||||||
|
|||||||
@ -1,17 +1,9 @@
|
|||||||
using Artemis.Core.Services;
|
namespace Artemis.Core.Providers;
|
||||||
|
|
||||||
namespace Artemis.Core.Providers;
|
|
||||||
|
|
||||||
public class NoneLayoutProvider : ILayoutProvider
|
public class NoneLayoutProvider : ILayoutProvider
|
||||||
{
|
{
|
||||||
private readonly IDeviceService _deviceService;
|
|
||||||
public static string LayoutType = "None";
|
public static string LayoutType = "None";
|
||||||
|
|
||||||
public NoneLayoutProvider(IDeviceService deviceService)
|
|
||||||
{
|
|
||||||
_deviceService = deviceService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
@ -38,7 +30,5 @@ public class NoneLayoutProvider : ILayoutProvider
|
|||||||
{
|
{
|
||||||
device.LayoutSelection.Type = LayoutType;
|
device.LayoutSelection.Type = LayoutType;
|
||||||
device.LayoutSelection.Parameter = null;
|
device.LayoutSelection.Parameter = null;
|
||||||
_deviceService.SaveDevice(device);
|
|
||||||
_deviceService.LoadDeviceLayout(device);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ internal class DeviceService : IDeviceService
|
|||||||
private readonly IPluginManagementService _pluginManagementService;
|
private readonly IPluginManagementService _pluginManagementService;
|
||||||
private readonly IDeviceRepository _deviceRepository;
|
private readonly IDeviceRepository _deviceRepository;
|
||||||
private readonly Lazy<IRenderService> _renderService;
|
private readonly Lazy<IRenderService> _renderService;
|
||||||
private readonly LazyEnumerable<ILayoutProvider> _layoutProviders;
|
private readonly Func<List<ILayoutProvider>> _getLayoutProviders;
|
||||||
private readonly List<ArtemisDevice> _enabledDevices = new();
|
private readonly List<ArtemisDevice> _enabledDevices = new();
|
||||||
private readonly List<ArtemisDevice> _devices = new();
|
private readonly List<ArtemisDevice> _devices = new();
|
||||||
|
|
||||||
@ -28,13 +28,13 @@ internal class DeviceService : IDeviceService
|
|||||||
IPluginManagementService pluginManagementService,
|
IPluginManagementService pluginManagementService,
|
||||||
IDeviceRepository deviceRepository,
|
IDeviceRepository deviceRepository,
|
||||||
Lazy<IRenderService> renderService,
|
Lazy<IRenderService> renderService,
|
||||||
LazyEnumerable<ILayoutProvider> layoutProviders)
|
Func<List<ILayoutProvider>> getLayoutProviders)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_pluginManagementService = pluginManagementService;
|
_pluginManagementService = pluginManagementService;
|
||||||
_deviceRepository = deviceRepository;
|
_deviceRepository = deviceRepository;
|
||||||
_renderService = renderService;
|
_renderService = renderService;
|
||||||
_layoutProviders = layoutProviders;
|
_getLayoutProviders = getLayoutProviders;
|
||||||
|
|
||||||
EnabledDevices = new ReadOnlyCollection<ArtemisDevice>(_enabledDevices);
|
EnabledDevices = new ReadOnlyCollection<ArtemisDevice>(_enabledDevices);
|
||||||
Devices = new ReadOnlyCollection<ArtemisDevice>(_devices);
|
Devices = new ReadOnlyCollection<ArtemisDevice>(_devices);
|
||||||
@ -167,7 +167,7 @@ internal class DeviceService : IDeviceService
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void LoadDeviceLayout(ArtemisDevice device)
|
public void LoadDeviceLayout(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
ILayoutProvider? provider = _layoutProviders.FirstOrDefault(p => p.IsMatch(device));
|
ILayoutProvider? provider = _getLayoutProviders().FirstOrDefault(p => p.IsMatch(device));
|
||||||
if (provider == null)
|
if (provider == null)
|
||||||
_logger.Warning("Could not find a layout provider for type {LayoutType} of device {Device}", device.LayoutSelection.Type, device);
|
_logger.Warning("Could not find a layout provider for type {LayoutType} of device {Device}", device.LayoutSelection.Type, device);
|
||||||
|
|
||||||
|
|||||||
@ -57,7 +57,7 @@ internal class PluginManagementService : IPluginManagementService
|
|||||||
|
|
||||||
// Remove the old directory if it exists
|
// Remove the old directory if it exists
|
||||||
if (Directory.Exists(pluginDirectory.FullName))
|
if (Directory.Exists(pluginDirectory.FullName))
|
||||||
pluginDirectory.DeleteRecursively();
|
pluginDirectory.Delete(true);
|
||||||
|
|
||||||
// Extract everything in the same archive directory to the unique plugin directory
|
// Extract everything in the same archive directory to the unique plugin directory
|
||||||
Utilities.CreateAccessibleDirectory(pluginDirectory.FullName);
|
Utilities.CreateAccessibleDirectory(pluginDirectory.FullName);
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Providers;
|
using Artemis.Core.Providers;
|
||||||
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Shared;
|
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;
|
||||||
@ -11,11 +12,12 @@ public class CustomLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
|||||||
{
|
{
|
||||||
private readonly CustomPathLayoutProvider _layoutProvider;
|
private readonly CustomPathLayoutProvider _layoutProvider;
|
||||||
|
|
||||||
public CustomLayoutViewModel(IWindowService windowService, INotificationService notificationService, CustomPathLayoutProvider layoutProvider)
|
public CustomLayoutViewModel(IWindowService windowService, INotificationService notificationService, IDeviceService deviceService, CustomPathLayoutProvider layoutProvider)
|
||||||
{
|
{
|
||||||
_layoutProvider = layoutProvider;
|
_layoutProvider = layoutProvider;
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
_notificationService = notificationService;
|
_notificationService = notificationService;
|
||||||
|
_deviceService = deviceService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -32,10 +34,12 @@ public class CustomLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
|||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
|
|
||||||
private readonly INotificationService _notificationService;
|
private readonly INotificationService _notificationService;
|
||||||
|
private readonly IDeviceService _deviceService;
|
||||||
|
|
||||||
public void ClearCustomLayout()
|
public void ClearCustomLayout()
|
||||||
{
|
{
|
||||||
_layoutProvider.ConfigureDevice(Device, null);
|
_layoutProvider.ConfigureDevice(Device, null);
|
||||||
|
Save();
|
||||||
|
|
||||||
_notificationService.CreateNotification()
|
_notificationService.CreateNotification()
|
||||||
.WithMessage("Cleared imported layout.")
|
.WithMessage("Cleared imported layout.")
|
||||||
@ -52,6 +56,7 @@ public class CustomLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
|||||||
if (files?.Length > 0)
|
if (files?.Length > 0)
|
||||||
{
|
{
|
||||||
_layoutProvider.ConfigureDevice(Device, files[0]);
|
_layoutProvider.ConfigureDevice(Device, files[0]);
|
||||||
|
Save();
|
||||||
|
|
||||||
_notificationService.CreateNotification()
|
_notificationService.CreateNotification()
|
||||||
.WithTitle("Imported layout")
|
.WithTitle("Imported layout")
|
||||||
@ -64,5 +69,12 @@ public class CustomLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
|||||||
public void Apply()
|
public void Apply()
|
||||||
{
|
{
|
||||||
_layoutProvider.ConfigureDevice(Device, null);
|
_layoutProvider.ConfigureDevice(Device, null);
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Save()
|
||||||
|
{
|
||||||
|
_deviceService.SaveDevice(Device);
|
||||||
|
_deviceService.LoadDeviceLayout(Device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Providers;
|
using Artemis.Core.Providers;
|
||||||
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
||||||
@ -7,10 +8,12 @@ namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
|||||||
public class DefaultLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
public class DefaultLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
||||||
{
|
{
|
||||||
private readonly DefaultLayoutProvider _layoutProvider;
|
private readonly DefaultLayoutProvider _layoutProvider;
|
||||||
|
private readonly IDeviceService _deviceService;
|
||||||
|
|
||||||
public DefaultLayoutViewModel(DefaultLayoutProvider layoutProvider)
|
public DefaultLayoutViewModel(DefaultLayoutProvider layoutProvider, IDeviceService deviceService)
|
||||||
{
|
{
|
||||||
_layoutProvider = layoutProvider;
|
_layoutProvider = layoutProvider;
|
||||||
|
_deviceService = deviceService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -28,5 +31,12 @@ public class DefaultLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
|||||||
public void Apply()
|
public void Apply()
|
||||||
{
|
{
|
||||||
_layoutProvider.ConfigureDevice(Device);
|
_layoutProvider.ConfigureDevice(Device);
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Save()
|
||||||
|
{
|
||||||
|
_deviceService.SaveDevice(Device);
|
||||||
|
_deviceService.LoadDeviceLayout(Device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Providers;
|
using Artemis.Core.Providers;
|
||||||
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
||||||
@ -7,10 +8,12 @@ namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
|||||||
public class NoneLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
public class NoneLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
||||||
{
|
{
|
||||||
private readonly NoneLayoutProvider _layoutProvider;
|
private readonly NoneLayoutProvider _layoutProvider;
|
||||||
|
private readonly IDeviceService _deviceService;
|
||||||
|
|
||||||
public NoneLayoutViewModel(NoneLayoutProvider layoutProvider)
|
public NoneLayoutViewModel(NoneLayoutProvider layoutProvider, IDeviceService deviceService)
|
||||||
{
|
{
|
||||||
_layoutProvider = layoutProvider;
|
_layoutProvider = layoutProvider;
|
||||||
|
_deviceService = deviceService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -28,5 +31,12 @@ public class NoneLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
|||||||
public void Apply()
|
public void Apply()
|
||||||
{
|
{
|
||||||
_layoutProvider.ConfigureDevice(Device);
|
_layoutProvider.ConfigureDevice(Device);
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Save()
|
||||||
|
{
|
||||||
|
_deviceService.SaveDevice(Device);
|
||||||
|
_deviceService.LoadDeviceLayout(Device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,13 +2,45 @@
|
|||||||
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:services="clr-namespace:Artemis.WebClient.Workshop.Services;assembly=Artemis.WebClient.Workshop"
|
||||||
|
xmlns:layoutProviders="clr-namespace:Artemis.UI.Screens.Device.Layout.LayoutProviders"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Device.Layout.LayoutProviders.WorkshopLayoutView">
|
x:Class="Artemis.UI.Screens.Device.Layout.LayoutProviders.WorkshopLayoutView"
|
||||||
|
x:DataType="layoutProviders:WorkshopLayoutViewModel">
|
||||||
<StackPanel ClipToBounds="False">
|
<StackPanel ClipToBounds="False">
|
||||||
<Border Classes="card-separator" />
|
<Border Classes="card-separator" />
|
||||||
<StackPanel>
|
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||||
<TextBlock Text="Current layout" />
|
<TextBlock Text="Current layout" />
|
||||||
<TextBlock Classes="subtitle" FontSize="12" Text="Loading the layout from a workshop entry" TextWrapping="Wrap" />
|
<TextBlock Classes="subtitle" FontSize="12" Text="Loading the layout from a workshop entry" TextWrapping="Wrap" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center">
|
||||||
|
<StackPanel.Styles>
|
||||||
|
<Style Selector="ComboBox.layoutProvider /template/ ContentControl#ContentPresenter">
|
||||||
|
<Setter Property="ContentTemplate">
|
||||||
|
<Setter.Value>
|
||||||
|
<DataTemplate x:DataType="services:InstalledEntry">
|
||||||
|
<TextBlock Text="{CompiledBinding Name}" TextWrapping="Wrap" MaxWidth="350" />
|
||||||
|
</DataTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</StackPanel.Styles>
|
||||||
|
<ComboBox Classes="layoutProvider"
|
||||||
|
Width="350"
|
||||||
|
SelectedItem="{CompiledBinding SelectedEntry}"
|
||||||
|
ItemsSource="{CompiledBinding Entries}"
|
||||||
|
PlaceholderText="Select an installed layout">
|
||||||
|
<ComboBox.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="services:InstalledEntry">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="{CompiledBinding Name}" TextWrapping="Wrap" MaxWidth="350" />
|
||||||
|
<TextBlock Classes="subtitle" Text="{CompiledBinding Author}" TextWrapping="Wrap" MaxWidth="350" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ComboBox.ItemTemplate>
|
||||||
|
</ComboBox>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,8 +1,9 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
||||||
|
|
||||||
public partial class WorkshopLayoutView : UserControl
|
public partial class WorkshopLayoutView : ReactiveUserControl<WorkshopLayoutViewModel>
|
||||||
{
|
{
|
||||||
public WorkshopLayoutView()
|
public WorkshopLayoutView()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,17 +1,33 @@
|
|||||||
using Artemis.Core;
|
using System.Collections.ObjectModel;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
|
using Artemis.Core;
|
||||||
using Artemis.Core.Providers;
|
using Artemis.Core.Providers;
|
||||||
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.WebClient.Workshop;
|
||||||
using Artemis.WebClient.Workshop.Providers;
|
using Artemis.WebClient.Workshop.Providers;
|
||||||
|
using Artemis.WebClient.Workshop.Services;
|
||||||
|
using PropertyChanged.SourceGenerator;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
||||||
|
|
||||||
public class WorkshopLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
public partial class WorkshopLayoutViewModel : ActivatableViewModelBase, ILayoutProviderViewModel
|
||||||
{
|
{
|
||||||
|
[Notify] private InstalledEntry? _selectedEntry;
|
||||||
private readonly WorkshopLayoutProvider _layoutProvider;
|
private readonly WorkshopLayoutProvider _layoutProvider;
|
||||||
|
private readonly IDeviceService _deviceService;
|
||||||
|
|
||||||
public WorkshopLayoutViewModel(WorkshopLayoutProvider layoutProvider)
|
public WorkshopLayoutViewModel(WorkshopLayoutProvider layoutProvider, IWorkshopService workshopService, IDeviceService deviceService)
|
||||||
{
|
{
|
||||||
_layoutProvider = layoutProvider;
|
_layoutProvider = layoutProvider;
|
||||||
|
_deviceService = deviceService;
|
||||||
|
Entries = new ObservableCollection<InstalledEntry>(workshopService.GetInstalledEntries().Where(e => e.EntryType == EntryType.Layout));
|
||||||
|
|
||||||
|
this.WhenAnyValue(vm => vm.SelectedEntry).Subscribe(ApplyEntry);
|
||||||
|
this.WhenActivated((CompositeDisposable _) => SelectedEntry = Entries.FirstOrDefault(e => e.EntryId.ToString() == Device.LayoutSelection.Parameter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -19,6 +35,8 @@ public class WorkshopLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
|||||||
|
|
||||||
public ArtemisDevice Device { get; set; } = null!;
|
public ArtemisDevice Device { get; set; } = null!;
|
||||||
|
|
||||||
|
public ObservableCollection<InstalledEntry> Entries { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string Name => "Workshop";
|
public string Name => "Workshop";
|
||||||
|
|
||||||
@ -28,6 +46,21 @@ public class WorkshopLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Apply()
|
public void Apply()
|
||||||
{
|
{
|
||||||
_layoutProvider.ConfigureDevice(Device);
|
_layoutProvider.ConfigureDevice(Device, null);
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyEntry(InstalledEntry? entry)
|
||||||
|
{
|
||||||
|
if (entry == null || Device.LayoutSelection.Parameter == entry.EntryId.ToString())
|
||||||
|
return;
|
||||||
|
_layoutProvider.ConfigureDevice(Device, entry);
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Save()
|
||||||
|
{
|
||||||
|
_deviceService.SaveDevice(Device);
|
||||||
|
_deviceService.LoadDeviceLayout(Device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ public class EntryReleasesViewModel : ViewModelBase
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
IEntryInstallationHandler installationHandler = _factory.CreateHandler(Entry.EntryType);
|
IEntryInstallationHandler installationHandler = _factory.CreateHandler(Entry.EntryType);
|
||||||
EntryInstallResult result = await installationHandler.InstallAsync(Entry, Entry.LatestRelease.Id, new Progress<StreamProgress>(), cancellationToken);
|
EntryInstallResult result = await installationHandler.InstallAsync(Entry, Entry.LatestRelease, new Progress<StreamProgress>(), cancellationToken);
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
_notificationService.CreateNotification().WithTitle($"{Entry.EntryType.Humanize(LetterCasing.Sentence)} installed").WithSeverity(NotificationSeverity.Success).Show();
|
_notificationService.CreateNotification().WithTitle($"{Entry.EntryType.Humanize(LetterCasing.Sentence)} installed").WithSeverity(NotificationSeverity.Success).Show();
|
||||||
else
|
else
|
||||||
|
|||||||
@ -5,6 +5,6 @@ namespace Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
|
|||||||
|
|
||||||
public interface IEntryInstallationHandler
|
public interface IEntryInstallationHandler
|
||||||
{
|
{
|
||||||
Task<EntryInstallResult> InstallAsync(IGetEntryById_Entry entry, long releaseId, Progress<StreamProgress> progress, CancellationToken cancellationToken);
|
Task<EntryInstallResult> InstallAsync(IEntryDetails entry, IRelease release, Progress<StreamProgress> progress, CancellationToken cancellationToken);
|
||||||
Task<EntryUninstallResult> UninstallAsync(InstalledEntry installedEntry, CancellationToken cancellationToken);
|
Task<EntryUninstallResult> UninstallAsync(InstalledEntry installedEntry, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
@ -1,10 +1,10 @@
|
|||||||
using System.Data;
|
using System.IO.Compression;
|
||||||
using System.IO.Compression;
|
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Providers;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Shared.Extensions;
|
using Artemis.UI.Shared.Extensions;
|
||||||
using Artemis.UI.Shared.Services;
|
|
||||||
using Artemis.UI.Shared.Utilities;
|
using Artemis.UI.Shared.Utilities;
|
||||||
|
using Artemis.WebClient.Workshop.Providers;
|
||||||
using Artemis.WebClient.Workshop.Services;
|
using Artemis.WebClient.Workshop.Services;
|
||||||
|
|
||||||
namespace Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
|
namespace Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
|
||||||
@ -14,15 +14,17 @@ public class LayoutEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
private readonly IHttpClientFactory _httpClientFactory;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IWorkshopService _workshopService;
|
private readonly IWorkshopService _workshopService;
|
||||||
private readonly IDeviceService _deviceService;
|
private readonly IDeviceService _deviceService;
|
||||||
|
private readonly DefaultLayoutProvider _defaultLayoutProvider;
|
||||||
|
|
||||||
public LayoutEntryInstallationHandler(IHttpClientFactory httpClientFactory, IWorkshopService workshopService, IDeviceService deviceService)
|
public LayoutEntryInstallationHandler(IHttpClientFactory httpClientFactory, IWorkshopService workshopService, IDeviceService deviceService, DefaultLayoutProvider defaultLayoutProvider)
|
||||||
{
|
{
|
||||||
_httpClientFactory = httpClientFactory;
|
_httpClientFactory = httpClientFactory;
|
||||||
_workshopService = workshopService;
|
_workshopService = workshopService;
|
||||||
_deviceService = deviceService;
|
_deviceService = deviceService;
|
||||||
|
_defaultLayoutProvider = defaultLayoutProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<EntryInstallResult> InstallAsync(IGetEntryById_Entry entry, long releaseId, Progress<StreamProgress> progress, CancellationToken cancellationToken)
|
public async Task<EntryInstallResult> InstallAsync(IEntryDetails entry, IRelease release, Progress<StreamProgress> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
using MemoryStream stream = new();
|
using MemoryStream stream = new();
|
||||||
|
|
||||||
@ -30,7 +32,7 @@ public class LayoutEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
HttpClient client = _httpClientFactory.CreateClient(WorkshopConstants.WORKSHOP_CLIENT_NAME);
|
HttpClient client = _httpClientFactory.CreateClient(WorkshopConstants.WORKSHOP_CLIENT_NAME);
|
||||||
await client.DownloadDataAsync($"releases/download/{releaseId}", stream, progress, cancellationToken);
|
await client.DownloadDataAsync($"releases/download/{release.Id}", stream, progress, cancellationToken);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -38,8 +40,8 @@ public class LayoutEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure there is an installed entry
|
// Ensure there is an installed entry
|
||||||
InstalledEntry installedEntry = _workshopService.GetInstalledEntry(entry) ?? _workshopService.CreateInstalledEntry(entry);
|
InstalledEntry installedEntry = _workshopService.GetInstalledEntry(entry) ?? new InstalledEntry(entry, release);
|
||||||
DirectoryInfo entryDirectory = installedEntry.GetDirectory();
|
DirectoryInfo entryDirectory = installedEntry.GetReleaseDirectory(release);
|
||||||
|
|
||||||
// If the folder already exists, remove it so that if the layout now contains less files, old things dont stick around
|
// If the folder already exists, remove it so that if the layout now contains less files, old things dont stick around
|
||||||
if (entryDirectory.Exists)
|
if (entryDirectory.Exists)
|
||||||
@ -53,7 +55,11 @@ public class LayoutEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
|
|
||||||
ArtemisLayout layout = new(Path.Combine(entryDirectory.FullName, "layout.xml"));
|
ArtemisLayout layout = new(Path.Combine(entryDirectory.FullName, "layout.xml"));
|
||||||
if (layout.IsValid)
|
if (layout.IsValid)
|
||||||
|
{
|
||||||
|
installedEntry.ApplyRelease(release);
|
||||||
|
_workshopService.SaveInstalledEntry(installedEntry);
|
||||||
return EntryInstallResult.FromSuccess(layout);
|
return EntryInstallResult.FromSuccess(layout);
|
||||||
|
}
|
||||||
|
|
||||||
// If the layout ended up being invalid yoink it out again, shoooo
|
// If the layout ended up being invalid yoink it out again, shoooo
|
||||||
entryDirectory.Delete(true);
|
entryDirectory.Delete(true);
|
||||||
@ -61,21 +67,26 @@ public class LayoutEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
return EntryInstallResult.FromFailure("Layout failed to load because it is invalid");
|
return EntryInstallResult.FromFailure("Layout failed to load because it is invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<EntryUninstallResult> UninstallAsync(InstalledEntry installedEntry, CancellationToken cancellationToken)
|
public Task<EntryUninstallResult> UninstallAsync(InstalledEntry installedEntry, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// Remove the layout from any devices currently using it
|
// Remove the layout from any devices currently using it
|
||||||
foreach (ArtemisDevice device in _deviceService.Devices)
|
foreach (ArtemisDevice device in _deviceService.Devices)
|
||||||
{
|
{
|
||||||
|
if (device.LayoutSelection.Type == WorkshopLayoutProvider.LayoutType && device.LayoutSelection.Parameter == installedEntry.EntryId.ToString())
|
||||||
|
{
|
||||||
|
_defaultLayoutProvider.ConfigureDevice(device);
|
||||||
|
_deviceService.SaveDevice(device);
|
||||||
|
_deviceService.LoadDeviceLayout(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from filesystem
|
// Remove from filesystem
|
||||||
DirectoryInfo directory = installedEntry.GetDirectory(true);
|
DirectoryInfo directory = installedEntry.GetDirectory();
|
||||||
if (directory.Exists)
|
if (directory.Exists)
|
||||||
directory.Delete();
|
directory.Delete(true);
|
||||||
|
|
||||||
// Remove entry
|
// Remove entry
|
||||||
_workshopService.RemoveInstalledEntry(installedEntry);
|
_workshopService.RemoveInstalledEntry(installedEntry);
|
||||||
|
return Task.FromResult(EntryUninstallResult.FromSuccess());
|
||||||
return EntryUninstallResult.FromSuccess();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19,7 +19,7 @@ public class ProfileEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
_workshopService = workshopService;
|
_workshopService = workshopService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<EntryInstallResult> InstallAsync(IGetEntryById_Entry entry, long releaseId, Progress<StreamProgress> progress, CancellationToken cancellationToken)
|
public async Task<EntryInstallResult> InstallAsync(IEntryDetails entry, IRelease release, Progress<StreamProgress> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
using MemoryStream stream = new();
|
using MemoryStream stream = new();
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ public class ProfileEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
HttpClient client = _httpClientFactory.CreateClient(WorkshopConstants.WORKSHOP_CLIENT_NAME);
|
HttpClient client = _httpClientFactory.CreateClient(WorkshopConstants.WORKSHOP_CLIENT_NAME);
|
||||||
await client.DownloadDataAsync($"releases/download/{releaseId}", stream, progress, cancellationToken);
|
await client.DownloadDataAsync($"releases/download/{release}", stream, progress, cancellationToken);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -45,13 +45,13 @@ public class ProfileEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
installedEntry.SetMetadata("ProfileId", overwritten.ProfileId);
|
installedEntry.SetMetadata("ProfileId", overwritten.ProfileId);
|
||||||
|
|
||||||
// Update the release and return the profile configuration
|
// Update the release and return the profile configuration
|
||||||
UpdateRelease(releaseId, installedEntry);
|
UpdateRelease(installedEntry, release);
|
||||||
return EntryInstallResult.FromSuccess(overwritten);
|
return EntryInstallResult.FromSuccess(overwritten);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure there is an installed entry
|
// Ensure there is an installed entry
|
||||||
installedEntry ??= _workshopService.CreateInstalledEntry(entry);
|
installedEntry ??= new InstalledEntry(entry, release);
|
||||||
|
|
||||||
// Add the profile as a fresh import
|
// Add the profile as a fresh import
|
||||||
ProfileCategory category = _profileService.ProfileCategories.FirstOrDefault(c => c.Name == "Workshop") ?? _profileService.CreateProfileCategory("Workshop", true);
|
ProfileCategory category = _profileService.ProfileCategories.FirstOrDefault(c => c.Name == "Workshop") ?? _profileService.CreateProfileCategory("Workshop", true);
|
||||||
@ -59,7 +59,7 @@ public class ProfileEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
installedEntry.SetMetadata("ProfileId", imported.ProfileId);
|
installedEntry.SetMetadata("ProfileId", imported.ProfileId);
|
||||||
|
|
||||||
// Update the release and return the profile configuration
|
// Update the release and return the profile configuration
|
||||||
UpdateRelease(releaseId, installedEntry);
|
UpdateRelease(installedEntry, release);
|
||||||
return EntryInstallResult.FromSuccess(imported);
|
return EntryInstallResult.FromSuccess(imported);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,11 +89,9 @@ public class ProfileEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
}, cancellationToken);
|
}, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateRelease(long releaseId, InstalledEntry installedEntry)
|
private void UpdateRelease(InstalledEntry installedEntry, IRelease release)
|
||||||
{
|
{
|
||||||
installedEntry.ReleaseId = releaseId;
|
installedEntry.ApplyRelease(release);
|
||||||
installedEntry.ReleaseVersion = "TODO";
|
|
||||||
installedEntry.InstalledAt = DateTimeOffset.UtcNow;
|
|
||||||
_workshopService.SaveInstalledEntry(installedEntry);
|
_workshopService.SaveInstalledEntry(installedEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Providers;
|
using Artemis.Core.Providers;
|
||||||
using Artemis.Core.Services;
|
|
||||||
using Artemis.WebClient.Workshop.Services;
|
using Artemis.WebClient.Workshop.Services;
|
||||||
|
|
||||||
namespace Artemis.WebClient.Workshop.Providers;
|
namespace Artemis.WebClient.Workshop.Providers;
|
||||||
@ -8,24 +7,21 @@ namespace Artemis.WebClient.Workshop.Providers;
|
|||||||
public class WorkshopLayoutProvider : ILayoutProvider
|
public class WorkshopLayoutProvider : ILayoutProvider
|
||||||
{
|
{
|
||||||
public static string LayoutType = "Workshop";
|
public static string LayoutType = "Workshop";
|
||||||
|
|
||||||
private readonly IDeviceService _deviceService;
|
|
||||||
private readonly IWorkshopService _workshopService;
|
private readonly IWorkshopService _workshopService;
|
||||||
|
|
||||||
public WorkshopLayoutProvider(IDeviceService deviceService, IWorkshopService workshopService)
|
public WorkshopLayoutProvider(IWorkshopService workshopService)
|
||||||
{
|
{
|
||||||
_deviceService = deviceService;
|
|
||||||
_workshopService = workshopService;
|
_workshopService = workshopService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
InstalledEntry? layoutEntry = _workshopService.GetInstalledEntries().FirstOrDefault(e => e.EntryType == EntryType.Layout && MatchesDevice(e, device));
|
InstalledEntry? layoutEntry = _workshopService.GetInstalledEntries().FirstOrDefault(e => e.EntryId.ToString() == device.LayoutSelection.Parameter);
|
||||||
if (layoutEntry == null)
|
if (layoutEntry == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
string layoutPath = Path.Combine(Constants.WorkshopFolder, layoutEntry.EntryId.ToString(), "layout.xml");
|
string layoutPath = Path.Combine(layoutEntry.GetReleaseDirectory().FullName, "layout.xml");
|
||||||
if (!File.Exists(layoutPath))
|
if (!File.Exists(layoutPath))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -35,7 +31,7 @@ public class WorkshopLayoutProvider : ILayoutProvider
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void ApplyLayout(ArtemisDevice device, ArtemisLayout layout)
|
public void ApplyLayout(ArtemisDevice device, ArtemisLayout layout)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
device.ApplyLayout(layout, device.DeviceProvider.CreateMissingLedsSupported, device.DeviceProvider.RemoveExcessiveLedsSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -44,20 +40,17 @@ public class WorkshopLayoutProvider : ILayoutProvider
|
|||||||
return device.LayoutSelection.Type == LayoutType;
|
return device.LayoutSelection.Type == LayoutType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool MatchesDevice(InstalledEntry entry, ArtemisDevice device)
|
|
||||||
{
|
|
||||||
return entry.TryGetMetadata("DeviceId", out HashSet<string>? deviceIds) && deviceIds.Contains(device.Identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Configures the provided device to use this layout provider.
|
/// Configures the provided device to use this layout provider.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="device">The device to apply the provider to.</param>
|
/// <param name="device">The device to apply the provider to.</param>
|
||||||
public void ConfigureDevice(ArtemisDevice device)
|
/// <param name="entry">The workshop entry to use as a layout.</param>
|
||||||
|
public void ConfigureDevice(ArtemisDevice device, InstalledEntry? entry)
|
||||||
{
|
{
|
||||||
|
if (entry != null && entry.EntryType != EntryType.Layout)
|
||||||
|
throw new InvalidOperationException($"Cannot use a workshop entry of type {entry.EntryType} as a layout");
|
||||||
|
|
||||||
device.LayoutSelection.Type = LayoutType;
|
device.LayoutSelection.Type = LayoutType;
|
||||||
device.LayoutSelection.Parameter = null;
|
device.LayoutSelection.Parameter = entry?.EntryId.ToString();
|
||||||
_deviceService.SaveDevice(device);
|
|
||||||
_deviceService.LoadDeviceLayout(device);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,13 +41,17 @@ fragment entryDetails on Entry {
|
|||||||
...category
|
...category
|
||||||
}
|
}
|
||||||
latestRelease {
|
latestRelease {
|
||||||
id
|
...release
|
||||||
version
|
|
||||||
downloadSize
|
|
||||||
md5Hash
|
|
||||||
createdAt
|
|
||||||
}
|
}
|
||||||
images {
|
images {
|
||||||
...image
|
...image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fragment release on Release {
|
||||||
|
id
|
||||||
|
version
|
||||||
|
downloadSize
|
||||||
|
md5Hash
|
||||||
|
createdAt
|
||||||
|
}
|
||||||
@ -14,7 +14,7 @@ public class InstalledEntry
|
|||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public InstalledEntry(IGetEntryById_Entry entry)
|
public InstalledEntry(IEntryDetails entry, IRelease release)
|
||||||
{
|
{
|
||||||
Entity = new EntryEntity();
|
Entity = new EntryEntity();
|
||||||
|
|
||||||
@ -23,6 +23,9 @@ public class InstalledEntry
|
|||||||
|
|
||||||
Author = entry.Author;
|
Author = entry.Author;
|
||||||
Name = entry.Name;
|
Name = entry.Name;
|
||||||
|
InstalledAt = DateTimeOffset.Now;
|
||||||
|
ReleaseId = release.Id;
|
||||||
|
ReleaseVersion = release.Version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long EntryId { get; set; }
|
public long EntryId { get; set; }
|
||||||
@ -110,14 +113,30 @@ public class InstalledEntry
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the directory info of the entry, where any files would be stored if applicable.
|
/// Returns the directory info of the entry, where any files would be stored if applicable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rootDirectory">A value indicating whether or not to return the root directory of the entry, and not the version.</param>
|
/// <returns>The directory info of the directory.</returns>
|
||||||
/// <returns>The directory info of the entry, where any files would be stored if applicable.</returns>
|
public DirectoryInfo GetDirectory()
|
||||||
public DirectoryInfo GetDirectory(bool rootDirectory = false)
|
|
||||||
{
|
{
|
||||||
if (rootDirectory)
|
return new DirectoryInfo(Path.Combine(Constants.WorkshopFolder, $"{EntryId}-{StringUtilities.UrlFriendly(Name)}"));
|
||||||
return new DirectoryInfo(Path.Combine(Constants.WorkshopFolder, EntryId.ToString()));
|
}
|
||||||
|
|
||||||
string safeVersion = Path.GetInvalidFileNameChars().Aggregate(ReleaseVersion, (current, c) => current.Replace(c, '-'));
|
/// <summary>
|
||||||
return new DirectoryInfo(Path.Combine(Constants.WorkshopFolder, EntryId.ToString(), safeVersion));
|
/// Returns the directory info of a release of this entry, where any files would be stored if applicable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="release">The release to use, if none provided the current release is used.</param>
|
||||||
|
/// <returns>The directory info of the directory.</returns>
|
||||||
|
public DirectoryInfo GetReleaseDirectory(IRelease? release = null)
|
||||||
|
{
|
||||||
|
return new DirectoryInfo(Path.Combine(GetDirectory().FullName, StringUtilities.UrlFriendly(release?.Version ?? ReleaseVersion)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies the provided release to the installed entry.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="release">The release to apply.</param>
|
||||||
|
public void ApplyRelease(IRelease release)
|
||||||
|
{
|
||||||
|
ReleaseId = release.Id;
|
||||||
|
ReleaseVersion = release.Version;
|
||||||
|
InstalledAt = DateTimeOffset.UtcNow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,3 @@
|
|||||||
using Artemis.UI.Shared.Utilities;
|
|
||||||
using Artemis.WebClient.Workshop.Handlers.UploadHandlers;
|
using Artemis.WebClient.Workshop.Handlers.UploadHandlers;
|
||||||
|
|
||||||
namespace Artemis.WebClient.Workshop.Services;
|
namespace Artemis.WebClient.Workshop.Services;
|
||||||
@ -13,11 +12,9 @@ public interface IWorkshopService
|
|||||||
Task NavigateToEntry(long entryId, EntryType entryType);
|
Task NavigateToEntry(long entryId, EntryType entryType);
|
||||||
|
|
||||||
List<InstalledEntry> GetInstalledEntries();
|
List<InstalledEntry> GetInstalledEntries();
|
||||||
InstalledEntry? GetInstalledEntry(IGetEntryById_Entry entry);
|
InstalledEntry? GetInstalledEntry(IEntryDetails entry);
|
||||||
InstalledEntry CreateInstalledEntry(IGetEntryById_Entry entry);
|
|
||||||
void RemoveInstalledEntry(InstalledEntry installedEntry);
|
void RemoveInstalledEntry(InstalledEntry installedEntry);
|
||||||
void SaveInstalledEntry(InstalledEntry entry);
|
void SaveInstalledEntry(InstalledEntry entry);
|
||||||
|
|
||||||
|
|
||||||
public record WorkshopStatus(bool IsReachable, string Message);
|
public record WorkshopStatus(bool IsReachable, string Message);
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ public class WorkshopService : IWorkshopService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public InstalledEntry? GetInstalledEntry(IGetEntryById_Entry entry)
|
public InstalledEntry? GetInstalledEntry(IEntryDetails entry)
|
||||||
{
|
{
|
||||||
EntryEntity? entity = _entryRepository.GetByEntryId(entry.Id);
|
EntryEntity? entity = _entryRepository.GetByEntryId(entry.Id);
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
@ -143,9 +143,9 @@ public class WorkshopService : IWorkshopService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public InstalledEntry CreateInstalledEntry(IGetEntryById_Entry entry)
|
public void AddOrUpdateInstalledEntry(InstalledEntry entry, IRelease release)
|
||||||
{
|
{
|
||||||
return new InstalledEntry(entry);
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user