mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Profile service - Migrate profiles before importing them
This commit is contained in:
parent
39d7d8132f
commit
bfd4a436de
@ -36,6 +36,7 @@ public static class ContainerExtensions
|
|||||||
|
|
||||||
// Bind migrations
|
// Bind migrations
|
||||||
container.RegisterMany(storageAssembly, type => type.IsAssignableTo<IStorageMigration>(), Reuse.Singleton, nonPublicServiceTypes: true);
|
container.RegisterMany(storageAssembly, type => type.IsAssignableTo<IStorageMigration>(), Reuse.Singleton, nonPublicServiceTypes: true);
|
||||||
|
container.RegisterMany(coreAssembly, type => type.IsAssignableTo<IProfileMigration>(), Reuse.Singleton, nonPublicServiceTypes: true);
|
||||||
|
|
||||||
container.RegisterMany(coreAssembly, type => type.IsAssignableTo<ILayoutProvider>(), Reuse.Singleton);
|
container.RegisterMany(coreAssembly, type => type.IsAssignableTo<ILayoutProvider>(), Reuse.Singleton);
|
||||||
container.Register<IPluginSettingsFactory, PluginSettingsFactory>(Reuse.Singleton);
|
container.Register<IPluginSettingsFactory, PluginSettingsFactory>(Reuse.Singleton);
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace Artemis.Core.Services;
|
||||||
|
|
||||||
|
internal interface IProfileMigration
|
||||||
|
{
|
||||||
|
int Version { get; }
|
||||||
|
void Migrate(JObject profileJson);
|
||||||
|
}
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace Artemis.Core.Services.ProfileMigrators;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Migrates nodes to be provider-based.
|
||||||
|
/// This requires giving them a ProviderId and updating the their namespaces to match the namespace of the new plugin.
|
||||||
|
/// </summary>
|
||||||
|
internal class M0001NodeProviders : IProfileMigration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public int Version => 1;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Migrate(JObject profileJson)
|
||||||
|
{
|
||||||
|
JArray? folders = (JArray?) profileJson["Folders"]?["$values"];
|
||||||
|
JArray? layers = (JArray?) profileJson["Layers"]?["$values"];
|
||||||
|
|
||||||
|
if (folders != null)
|
||||||
|
{
|
||||||
|
foreach (JToken folder in folders)
|
||||||
|
{
|
||||||
|
MigrateProfileElement(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layers != null)
|
||||||
|
{
|
||||||
|
foreach (JToken layer in layers)
|
||||||
|
{
|
||||||
|
MigrateProfileElement(layer);
|
||||||
|
MigratePropertyGroup(layer["GeneralPropertyGroup"]);
|
||||||
|
MigratePropertyGroup(layer["TransformPropertyGroup"]);
|
||||||
|
MigratePropertyGroup(layer["LayerBrush"]?["PropertyGroup"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigrateProfileElement(JToken profileElement)
|
||||||
|
{
|
||||||
|
JArray? layerEffects = (JArray?) profileElement["LayerEffects"]?["$values"];
|
||||||
|
if (layerEffects != null)
|
||||||
|
{
|
||||||
|
foreach (JToken layerEffect in layerEffects)
|
||||||
|
MigratePropertyGroup(layerEffect["PropertyGroup"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
JToken? displayCondition = profileElement["DisplayCondition"];
|
||||||
|
if (displayCondition != null)
|
||||||
|
MigrateNodeScript(displayCondition["Script"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigratePropertyGroup(JToken? propertyGroup)
|
||||||
|
{
|
||||||
|
if (propertyGroup == null || !propertyGroup.HasValues)
|
||||||
|
return;
|
||||||
|
|
||||||
|
JArray? properties = (JArray?) propertyGroup["Properties"]?["$values"];
|
||||||
|
JArray? propertyGroups = (JArray?) propertyGroup["PropertyGroups"]?["$values"];
|
||||||
|
|
||||||
|
if (properties != null)
|
||||||
|
{
|
||||||
|
foreach (JToken property in properties)
|
||||||
|
MigrateNodeScript(property["DataBinding"]?["NodeScript"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertyGroups != null)
|
||||||
|
{
|
||||||
|
foreach (JToken childPropertyGroup in propertyGroups)
|
||||||
|
MigratePropertyGroup(childPropertyGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigrateNodeScript(JToken? nodeScript)
|
||||||
|
{
|
||||||
|
if (nodeScript == null || !nodeScript.HasValues)
|
||||||
|
return;
|
||||||
|
|
||||||
|
JArray? nodes = (JArray?) nodeScript["Nodes"]?["$values"];
|
||||||
|
if (nodes == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (JToken node in nodes)
|
||||||
|
{
|
||||||
|
node["Type"] = node["Type"]?.Value<string>()?.Replace("Artemis.VisualScripting.Nodes", "Artemis.Plugins.Nodes.General.Nodes");
|
||||||
|
node["ProviderId"] = "Artemis.Plugins.Nodes.General.GeneralNodesProvider-d9e1ee78";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,6 +10,7 @@ using Artemis.Core.Modules;
|
|||||||
using Artemis.Storage.Entities.Profile;
|
using Artemis.Storage.Entities.Profile;
|
||||||
using Artemis.Storage.Repositories.Interfaces;
|
using Artemis.Storage.Repositories.Interfaces;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
@ -24,9 +25,10 @@ internal class ProfileService : IProfileService
|
|||||||
private readonly List<ArtemisKeyboardKeyEventArgs> _pendingKeyboardEvents = new();
|
private readonly List<ArtemisKeyboardKeyEventArgs> _pendingKeyboardEvents = new();
|
||||||
private readonly List<ProfileCategory> _profileCategories;
|
private readonly List<ProfileCategory> _profileCategories;
|
||||||
private readonly IProfileRepository _profileRepository;
|
private readonly IProfileRepository _profileRepository;
|
||||||
|
private readonly List<IProfileMigration> _profileMigrators;
|
||||||
private readonly List<Exception> _renderExceptions = new();
|
private readonly List<Exception> _renderExceptions = new();
|
||||||
private readonly List<Exception> _updateExceptions = new();
|
private readonly List<Exception> _updateExceptions = new();
|
||||||
|
|
||||||
private DateTime _lastRenderExceptionLog;
|
private DateTime _lastRenderExceptionLog;
|
||||||
private DateTime _lastUpdateExceptionLog;
|
private DateTime _lastUpdateExceptionLog;
|
||||||
|
|
||||||
@ -35,13 +37,15 @@ internal class ProfileService : IProfileService
|
|||||||
IPluginManagementService pluginManagementService,
|
IPluginManagementService pluginManagementService,
|
||||||
IInputService inputService,
|
IInputService inputService,
|
||||||
IDeviceService deviceService,
|
IDeviceService deviceService,
|
||||||
IProfileRepository profileRepository)
|
IProfileRepository profileRepository,
|
||||||
|
List<IProfileMigration> profileMigrators)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_profileCategoryRepository = profileCategoryRepository;
|
_profileCategoryRepository = profileCategoryRepository;
|
||||||
_pluginManagementService = pluginManagementService;
|
_pluginManagementService = pluginManagementService;
|
||||||
_deviceService = deviceService;
|
_deviceService = deviceService;
|
||||||
_profileRepository = profileRepository;
|
_profileRepository = profileRepository;
|
||||||
|
_profileMigrators = profileMigrators;
|
||||||
_profileCategories = new List<ProfileCategory>(_profileCategoryRepository.GetAll().Select(c => new ProfileCategory(c)).OrderBy(c => c.Order));
|
_profileCategories = new List<ProfileCategory>(_profileCategoryRepository.GetAll().Select(c => new ProfileCategory(c)).OrderBy(c => c.Order));
|
||||||
|
|
||||||
_deviceService.LedsChanged += DeviceServiceOnLedsChanged;
|
_deviceService.LedsChanged += DeviceServiceOnLedsChanged;
|
||||||
@ -58,7 +62,7 @@ internal class ProfileService : IProfileService
|
|||||||
public ProfileConfiguration? FocusProfile { get; set; }
|
public ProfileConfiguration? FocusProfile { get; set; }
|
||||||
public ProfileElement? FocusProfileElement { get; set; }
|
public ProfileElement? FocusProfileElement { get; set; }
|
||||||
public bool UpdateFocusProfile { get; set; }
|
public bool UpdateFocusProfile { get; set; }
|
||||||
|
|
||||||
public bool ProfileRenderingDisabled { get; set; }
|
public bool ProfileRenderingDisabled { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -461,7 +465,12 @@ internal class ProfileService : IProfileService
|
|||||||
|
|
||||||
await using Stream profileStream = profileEntry.Open();
|
await using Stream profileStream = profileEntry.Open();
|
||||||
using StreamReader profileReader = new(profileStream);
|
using StreamReader profileReader = new(profileStream);
|
||||||
ProfileEntity? profileEntity = JsonConvert.DeserializeObject<ProfileEntity>(await profileReader.ReadToEndAsync(), IProfileService.ExportSettings);
|
JObject? profileJson = JsonConvert.DeserializeObject<JObject>(await profileReader.ReadToEndAsync(), IProfileService.ExportSettings);
|
||||||
|
|
||||||
|
// Before deserializing, apply any pending migrations
|
||||||
|
MigrateProfile(configurationEntity, profileJson);
|
||||||
|
|
||||||
|
ProfileEntity? profileEntity = profileJson?.ToObject<ProfileEntity>(JsonSerializer.Create(IProfileService.ExportSettings));
|
||||||
if (profileEntity == null)
|
if (profileEntity == null)
|
||||||
throw new ArtemisCoreException("Could not import profile, failed to deserialize profile.json");
|
throw new ArtemisCoreException("Could not import profile, failed to deserialize profile.json");
|
||||||
|
|
||||||
@ -545,6 +554,21 @@ internal class ProfileService : IProfileService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MigrateProfile(ProfileConfigurationEntity configurationEntity, JObject? profileJson)
|
||||||
|
{
|
||||||
|
if (profileJson == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (IProfileMigration profileMigrator in _profileMigrators.OrderBy(m => m.Version))
|
||||||
|
{
|
||||||
|
if (profileMigrator.Version <= configurationEntity.Version)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
profileMigrator.Migrate(profileJson);
|
||||||
|
configurationEntity.Version = profileMigrator.Version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Populates all missing LEDs on all currently active profiles
|
/// Populates all missing LEDs on all currently active profiles
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -26,4 +26,5 @@ public class ProfileConfigurationEntity
|
|||||||
public Guid ProfileId { get; set; }
|
public Guid ProfileId { get; set; }
|
||||||
|
|
||||||
public bool FadeInAndOut { get; set; }
|
public bool FadeInAndOut { get; set; }
|
||||||
|
public int Version { get; set; }
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user