Workshop - Added installed entries and update profiles when reinstalling them

This commit is contained in:
Robert committed 2023-09-06 20:39:43 +02:00
1 parent fcde1d4ecc
commit c69be2836e
17 files changed
+327 -58

No files matched your search

@@ -2,6 +2,6 @@
namespace Artemis.WebClient.Workshop.DownloadHandlers;
public interface IEntryDownloadHandler
public interface IEntryInstallationHandler
{
}
@@ -1,36 +0,0 @@
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Shared.Extensions;
using Artemis.UI.Shared.Utilities;
namespace Artemis.WebClient.Workshop.DownloadHandlers.Implementations;
public class ProfileEntryDownloadHandler : IEntryDownloadHandler
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly IProfileService _profileService;
public ProfileEntryDownloadHandler(IHttpClientFactory httpClientFactory, IProfileService profileService)
{
_httpClientFactory = httpClientFactory;
_profileService = profileService;
}
public async Task<EntryInstallResult<ProfileConfiguration>> InstallProfileAsync(Guid releaseId, Progress<StreamProgress> progress, CancellationToken cancellationToken)
{
try
{
HttpClient client = _httpClientFactory.CreateClient(WorkshopConstants.WORKSHOP_CLIENT_NAME);
using MemoryStream stream = new();
await client.DownloadDataAsync($"releases/download/{releaseId}", stream, progress, cancellationToken);
ProfileCategory category = _profileService.ProfileCategories.FirstOrDefault(c => c.Name == "Workshop") ?? _profileService.CreateProfileCategory("Workshop", true);
ProfileConfiguration profileConfiguration = await _profileService.ImportProfile(stream, category, true, true, null);
return EntryInstallResult<ProfileConfiguration>.FromSuccess(profileConfiguration);
}
catch (Exception e)
{
return EntryInstallResult<ProfileConfiguration>.FromFailure(e.Message);
}
}
}
@@ -0,0 +1,73 @@
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Shared.Extensions;
using Artemis.UI.Shared.Utilities;
using Artemis.WebClient.Workshop.Services;
namespace Artemis.WebClient.Workshop.DownloadHandlers.Implementations;
public class ProfileEntryInstallationHandler : IEntryInstallationHandler
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly IProfileService _profileService;
private readonly IWorkshopService _workshopService;
public ProfileEntryInstallationHandler(IHttpClientFactory httpClientFactory, IProfileService profileService, IWorkshopService workshopService)
{
_httpClientFactory = httpClientFactory;
_profileService = profileService;
_workshopService = workshopService;
}
public async Task<EntryInstallResult<ProfileConfiguration>> InstallProfileAsync(IGetEntryById_Entry entry, Guid releaseId, Progress<StreamProgress> progress, CancellationToken cancellationToken)
{
using MemoryStream stream = new();
// Download the provided release
try
{
HttpClient client = _httpClientFactory.CreateClient(WorkshopConstants.WORKSHOP_CLIENT_NAME);
await client.DownloadDataAsync($"releases/download/{releaseId}", stream, progress, cancellationToken);
}
catch (Exception e)
{
return EntryInstallResult<ProfileConfiguration>.FromFailure(e.Message);
}
// Find existing installation to potentially replace the profile
InstalledEntry? installedEntry = _workshopService.GetInstalledEntry(entry);
if (installedEntry != null && Guid.TryParse(installedEntry.LocalReference, out Guid profileId))
{
ProfileConfiguration? existing = _profileService.ProfileCategories.SelectMany(c => c.ProfileConfigurations).FirstOrDefault(c => c.ProfileId == profileId);
if (existing != null)
{
ProfileConfiguration overwritten = await _profileService.OverwriteProfile(stream, existing);
installedEntry.LocalReference = overwritten.ProfileId.ToString();
// Update the release and return the profile configuration
UpdateRelease(releaseId, installedEntry);
return EntryInstallResult<ProfileConfiguration>.FromSuccess(overwritten);
}
}
// Ensure there is an installed entry
installedEntry ??= _workshopService.CreateInstalledEntry(entry);
// Add the profile as a fresh import
ProfileCategory category = _profileService.ProfileCategories.FirstOrDefault(c => c.Name == "Workshop") ?? _profileService.CreateProfileCategory("Workshop", true);
ProfileConfiguration imported = await _profileService.ImportProfile(stream, category, true, true, null);
installedEntry.LocalReference = imported.ProfileId.ToString();
// Update the release and return the profile configuration
UpdateRelease(releaseId, installedEntry);
return EntryInstallResult<ProfileConfiguration>.FromSuccess(imported);
}
private void UpdateRelease(Guid releaseId, InstalledEntry installedEntry)
{
installedEntry.ReleaseId = releaseId;
installedEntry.ReleaseVersion = "TODO";
installedEntry.InstalledAt = DateTimeOffset.UtcNow;
_workshopService.SaveInstalledEntry(installedEntry);
}
}
@@ -49,6 +49,6 @@ public static class ContainerExtensions
container.Register<EntryUploadHandlerFactory>(Reuse.Transient);
container.RegisterMany(workshopAssembly, type => type.IsAssignableTo<IEntryUploadHandler>(), Reuse.Transient);
container.RegisterMany(workshopAssembly, type => type.IsAssignableTo<IEntryDownloadHandler>(), Reuse.Transient);
container.RegisterMany(workshopAssembly, type => type.IsAssignableTo<IEntryInstallationHandler>(), Reuse.Transient);
}
}
@@ -0,0 +1,72 @@
using Artemis.Storage.Entities.Workshop;
namespace Artemis.WebClient.Workshop.Services;
public class InstalledEntry
{
internal InstalledEntry(EntryEntity entity)
{
Entity = entity;
Load();
}
public InstalledEntry(IGetEntryById_Entry entry)
{
Entity = new EntryEntity();
EntryId = entry.Id;
EntryType = entry.EntryType;
Author = entry.Author;
Name = entry.Name;
Summary = entry.Summary;
}
public Guid EntryId { get; set; }
public EntryType EntryType { get; set; }
public string Author { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string Summary { get; set; } = string.Empty;
public Guid ReleaseId { get; set; }
public string ReleaseVersion { get; set; } = string.Empty;
public DateTimeOffset InstalledAt { get; set; }
public string? LocalReference { get; set; }
internal EntryEntity Entity { get; }
internal void Load()
{
EntryId = Entity.EntryId;
EntryType = (EntryType) Entity.EntryType;
Author = Entity.Author;
Name = Entity.Name;
Summary = Entity.Summary;
ReleaseId = Entity.ReleaseId;
ReleaseVersion = Entity.ReleaseVersion;
InstalledAt = Entity.InstalledAt;
LocalReference = Entity.LocalReference;
}
internal void Save()
{
Entity.EntryId = EntryId;
Entity.EntryType = (int) EntryType;
Entity.Author = Author;
Entity.Name = Name;
Entity.Summary = Summary;
Entity.ReleaseId = ReleaseId;
Entity.ReleaseVersion = ReleaseVersion;
Entity.InstalledAt = InstalledAt;
Entity.LocalReference = LocalReference;
}
}
@@ -0,0 +1,18 @@
using Artemis.UI.Shared.Utilities;
using Artemis.WebClient.Workshop.UploadHandlers;
namespace Artemis.WebClient.Workshop.Services;
public interface IWorkshopService
{
Task<Stream?> GetEntryIcon(Guid entryId, CancellationToken cancellationToken);
Task<ImageUploadResult> SetEntryIcon(Guid entryId, Progress<StreamProgress> progress, Stream icon, CancellationToken cancellationToken);
Task<WorkshopStatus> GetWorkshopStatus(CancellationToken cancellationToken);
Task<bool> ValidateWorkshopStatus(CancellationToken cancellationToken);
Task NavigateToEntry(Guid entryId, EntryType entryType);
InstalledEntry? GetInstalledEntry(IGetEntryById_Entry entry);
InstalledEntry CreateInstalledEntry(IGetEntryById_Entry entry);
void SaveInstalledEntry(InstalledEntry entry);
public record WorkshopStatus(bool IsReachable, string Message);
}
@@ -1,4 +1,6 @@
using System.Net.Http.Headers;
using Artemis.Storage.Entities.Workshop;
using Artemis.Storage.Repositories.Interfaces;
using Artemis.UI.Shared.Routing;
using Artemis.UI.Shared.Utilities;
using Artemis.WebClient.Workshop.UploadHandlers;
@@ -9,11 +11,13 @@ public class WorkshopService : IWorkshopService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly IRouter _router;
private readonly IEntryRepository _entryRepository;
public WorkshopService(IHttpClientFactory httpClientFactory, IRouter router)
public WorkshopService(IHttpClientFactory httpClientFactory, IRouter router, IEntryRepository entryRepository)
{
_httpClientFactory = httpClientFactory;
_router = router;
_entryRepository = entryRepository;
}
public async Task<Stream?> GetEntryIcon(Guid entryId, CancellationToken cancellationToken)
@@ -98,15 +102,27 @@ public class WorkshopService : IWorkshopService
throw new ArgumentOutOfRangeException(nameof(entryType));
}
}
}
public interface IWorkshopService
{
Task<Stream?> GetEntryIcon(Guid entryId, CancellationToken cancellationToken);
Task<ImageUploadResult> SetEntryIcon(Guid entryId, Progress<StreamProgress> progress, Stream icon, CancellationToken cancellationToken);
Task<WorkshopStatus> GetWorkshopStatus(CancellationToken cancellationToken);
Task<bool> ValidateWorkshopStatus(CancellationToken cancellationToken);
Task NavigateToEntry(Guid entryId, EntryType entryType);
/// <inheritdoc />
public InstalledEntry? GetInstalledEntry(IGetEntryById_Entry entry)
{
EntryEntity? entity = _entryRepository.GetByEntryId(entry.Id);
if (entity == null)
return null;
public record WorkshopStatus(bool IsReachable, string Message);
return new InstalledEntry(entity);
}
/// <inheritdoc />
public InstalledEntry CreateInstalledEntry(IGetEntryById_Entry entry)
{
return new InstalledEntry(entry);
}
/// <inheritdoc />
public void SaveInstalledEntry(InstalledEntry entry)
{
entry.Save();
_entryRepository.Save(entry.Entity);
}
}