Added layout archive generation

This commit is contained in:
RobertBeekman committed 2023-11-02 22:29:42 +01:00
1 parent 59fe1df40f
commit 6b4e84c95a
18 files changed
+224 -68

No files matched your search

@@ -53,4 +53,10 @@
<ItemGroup>
<Folder Include="Handlers\" />
</ItemGroup>
<ItemGroup>
<Reference Include="RGB.NET.Layout">
<HintPath>..\..\..\RGB.NET\bin\net7.0\RGB.NET.Layout.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
@@ -0,0 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=handlers_005Cinstallationhandlers_005Cimplementations/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=handlers_005Cuploadhandlers_005Cimplementations/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cinterfaces/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
@@ -1,5 +1,4 @@
using Artemis.WebClient.Workshop.Handlers.InstallationHandlers.Implementations;
using DryIoc;
using DryIoc;
namespace Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
@@ -4,7 +4,7 @@ using Artemis.UI.Shared.Extensions;
using Artemis.UI.Shared.Utilities;
using Artemis.WebClient.Workshop.Services;
namespace Artemis.WebClient.Workshop.Handlers.InstallationHandlers.Implementations;
namespace Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
public class ProfileEntryInstallationHandler : IEntryInstallationHandler
{
@@ -1,5 +1,7 @@
using System.Xml.Serialization;
using System.IO.Compression;
using Artemis.Core;
using Artemis.UI.Shared.Utilities;
using Artemis.WebClient.Workshop.Exceptions;
using RGB.NET.Layout;
namespace Artemis.WebClient.Workshop.Handlers.UploadHandlers;
@@ -11,15 +13,56 @@ public class LayoutEntryUploadHandler : IEntryUploadHandler
{
if (entrySource is not LayoutEntrySource source)
throw new InvalidOperationException("Can only create releases for layouts");
// Create a copy of the layout, image paths are about to be rewritten
XmlSerializer serializer = new(typeof(DeviceLayout));
using MemoryStream ms = new();
await using StreamWriter writer = new(ms);
serializer.Serialize(writer, source.Layout.RgbLayout);
await writer.FlushAsync();
ms.Seek(0, SeekOrigin.Begin);
using MemoryStream archiveStream = new();
using MemoryStream layoutStream = new();
source.Layout.RgbLayout.Save(layoutStream);
layoutStream.Seek(0, SeekOrigin.Begin);
// Create an archive
string? layoutPath = Path.GetDirectoryName(source.Layout.FilePath);
if (layoutPath == null)
throw new ArtemisWorkshopException($"Could not determine directory of {source.Layout.FilePath}");
using (ZipArchive archive = new(archiveStream, ZipArchiveMode.Create, true))
{
// Add the layout to the archive
ZipArchiveEntry archiveEntry = archive.CreateEntry("layout.xml");
await using (Stream layoutArchiveStream = archiveEntry.Open())
await layoutStream.CopyToAsync(layoutArchiveStream, cancellationToken);
// Add the layout image to the archive
CopyImage(layoutPath, source.Layout.LayoutCustomDeviceData.DeviceImage, archive);
// Add the LED images to the archive
foreach (ArtemisLedLayout ledLayout in source.Layout.Leds)
{
if (ledLayout.LayoutCustomLedData.LogicalLayouts == null)
continue;
foreach (LayoutCustomLedDataLogicalLayout customData in ledLayout.LayoutCustomLedData.LogicalLayouts)
CopyImage(layoutPath, customData.Image, archive);
}
}
archiveStream.Seek(0, SeekOrigin.Begin);
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string filePath = Path.Combine(desktopPath, "layout-test.zip");
await using (FileStream fileStream = new(filePath, FileMode.Create, FileAccess.Write))
{
archiveStream.WriteTo(fileStream);
}
return new EntryUploadResult();
}
private static void CopyImage(string layoutPath, string? imagePath, ZipArchive archive)
{
if (imagePath == null)
return;
string fullPath = Path.Combine(layoutPath, imagePath);
archive.CreateEntryFromFile(fullPath, imagePath);
}
}
@@ -7,6 +7,7 @@ public interface IWorkshopService
{
Task<Stream?> GetEntryIcon(long entryId, CancellationToken cancellationToken);
Task<ImageUploadResult> SetEntryIcon(long entryId, Progress<StreamProgress> progress, Stream icon, CancellationToken cancellationToken);
Task<ImageUploadResult> UploadEntryImage(long entryId, Progress<StreamProgress> progress, Stream image, CancellationToken cancellationToken);
Task<WorkshopStatus> GetWorkshopStatus(CancellationToken cancellationToken);
Task<bool> ValidateWorkshopStatus(CancellationToken cancellationToken);
Task NavigateToEntry(long entryId, EntryType entryType);
@@ -56,6 +56,27 @@ public class WorkshopService : IWorkshopService
return ImageUploadResult.FromSuccess();
}
/// <inheritdoc />
public async Task<ImageUploadResult> UploadEntryImage(long entryId, Progress<StreamProgress> progress, Stream image, CancellationToken cancellationToken)
{
image.Seek(0, SeekOrigin.Begin);
// Submit the archive
HttpClient client = _httpClientFactory.CreateClient(WorkshopConstants.WORKSHOP_CLIENT_NAME);
// Construct the request
MultipartFormDataContent content = new();
ProgressableStreamContent streamContent = new(image, progress);
streamContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");
content.Add(streamContent, "file", "file.png");
// Submit
HttpResponseMessage response = await client.PostAsync($"entries/{entryId}/image", content, cancellationToken);
if (!response.IsSuccessStatusCode)
return ImageUploadResult.FromFailure($"{response.StatusCode} - {await response.Content.ReadAsStringAsync(cancellationToken)}");
return ImageUploadResult.FromSuccess();
}
/// <inheritdoc />
public async Task<IWorkshopService.WorkshopStatus> GetWorkshopStatus(CancellationToken cancellationToken)
{