mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 11:26:27 +00:00
Core - Fix profile service, storage and device bugs found by the tests (#912)
* Core - Fix default headset layouts and the z-index of devices placed by the auto-arrange fallback - Headsets with 2 or 4 LEDs get their default layout, the files are named "... LEDs headset.xml" - Devices placed by the auto-arrange fallback get the z-index of their type * Core - Fall back to the default value passed to GetSetting when a stored setting can't be read * Core - Fix storing, cloning and migrating profiles - New profiles are stored at the current migration version, so they're no longer migrated on every start and can be duplicated right away - A category created at the top is listed first right away, so its profiles render on top - CloneProfileConfiguration makes a copy of the stored data, saving a clone stores its profile through the original - Importing a profile raises ProfileAdded - A profile configuration that isn't valid JSON is logged and skipped instead of stopping all migrations - A stored profile without a version is migrated from version 0, like an imported one - ProfileCategoryRepository.IsUnique returns true when the name is free - M0001 and M0004 leave a missing node type or storage out instead of writing null - M0003 also unwraps a list that is an item of another list
This commit is contained in:
1 parent
295038f338
commit
83cf6da830
20 files changed
+137
-114
No files matched your search
@@ -164,8 +164,8 @@ public class ArtemisLayout
|
||||
if (device.Leds.Count == 1)
|
||||
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Headset", "Artemis 1 LED headset.xml"));
|
||||
if (device.Leds.Count == 2)
|
||||
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Headset", "Artemis 2 LED headset.xml"));
|
||||
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Headset", "Artemis 4 LED headset.xml"));
|
||||
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Headset", "Artemis 2 LEDs headset.xml"));
|
||||
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Headset", "Artemis 4 LEDs headset.xml"));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -15,7 +15,7 @@ public class PluginSetting<T> : CorePropertyChanged, IPluginSetting
|
||||
private readonly PluginSettingEntity _pluginSettingEntity;
|
||||
private T _value;
|
||||
|
||||
internal PluginSetting(IPluginRepository pluginRepository, PluginSettingEntity pluginSettingEntity)
|
||||
internal PluginSetting(IPluginRepository pluginRepository, PluginSettingEntity pluginSettingEntity, T? defaultValue = default)
|
||||
{
|
||||
_pluginRepository = pluginRepository;
|
||||
_pluginSettingEntity = pluginSettingEntity;
|
||||
@@ -27,7 +27,7 @@ public class PluginSetting<T> : CorePropertyChanged, IPluginSetting
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
_value = default!;
|
||||
_value = defaultValue!;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public class PluginSettings
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the setting, can be any serializable type</typeparam>
|
||||
/// <param name="name">The name of the setting, may not be longer than 128 characters</param>
|
||||
/// <param name="defaultValue">The default value to use if the setting does not exist yet</param>
|
||||
/// <param name="defaultValue">The default value to use if the setting does not exist yet, or can't be read as <typeparamref name="T" /></param>
|
||||
public PluginSetting<T> GetSetting<T>(string name, T? defaultValue = default)
|
||||
{
|
||||
if (name.Length > 128)
|
||||
@@ -57,7 +57,7 @@ public class PluginSettings
|
||||
_pluginRepository.SaveSetting(settingEntity);
|
||||
}
|
||||
|
||||
PluginSetting<T> pluginSetting = new(_pluginRepository, settingEntity);
|
||||
PluginSetting<T> pluginSetting = new(_pluginRepository, settingEntity, defaultValue);
|
||||
|
||||
// This overrides null with the default value, I'm not sure if that's desirable because you
|
||||
// might expect something to go null and you might not
|
||||
|
||||
@@ -54,6 +54,8 @@ internal class SurfaceArrangementType
|
||||
) {SurfaceArrangement = SurfaceArrangement};
|
||||
fallback.Apply(devicesToArrange, devices);
|
||||
AppliedConfiguration = fallback;
|
||||
foreach (ArtemisDevice artemisDevice in devicesToArrange)
|
||||
artemisDevice.ZIndex = ZIndex;
|
||||
}
|
||||
|
||||
public Point GetEdge(HorizontalArrangementPosition horizontalPosition, VerticalArrangementPosition verticalPosition)
|
||||
|
||||
@@ -161,7 +161,16 @@ internal class ProfileService : IProfileService
|
||||
/// <inheritdoc />
|
||||
public ProfileConfiguration CloneProfileConfiguration(ProfileConfiguration profileConfiguration)
|
||||
{
|
||||
return new ProfileConfiguration(profileConfiguration.Category, profileConfiguration.Entity);
|
||||
ProfileContainerEntity original = profileConfiguration.Entity;
|
||||
ProfileContainerEntity copy = new()
|
||||
{
|
||||
Id = original.Id,
|
||||
Icon = original.Icon.ToArray(),
|
||||
ProfileCategory = original.ProfileCategory,
|
||||
ProfileConfiguration = CopyEntity(original.ProfileConfiguration),
|
||||
Profile = CopyEntity(original.Profile)
|
||||
};
|
||||
return new ProfileConfiguration(profileConfiguration.Category, copy);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -234,7 +243,7 @@ internal class ProfileService : IProfileService
|
||||
}
|
||||
|
||||
_profileCategoryRepository.Add(profileCategory.Entity);
|
||||
ProfileCategories = new ReadOnlyCollection<ProfileCategory>([..ProfileCategories, profileCategory]);
|
||||
ProfileCategories = new ReadOnlyCollection<ProfileCategory>(ProfileCategories.Append(profileCategory).OrderBy(c => c.Order).ToList());
|
||||
|
||||
OnProfileCategoryAdded(new ProfileCategoryEventArgs(profileCategory));
|
||||
return profileCategory;
|
||||
@@ -259,6 +268,8 @@ internal class ProfileService : IProfileService
|
||||
|
||||
category.AddProfileConfiguration(configuration, category.ProfileConfigurations.FirstOrDefault());
|
||||
SaveProfileCategory(category);
|
||||
// The profile is in the current format, saving it stores the current migration version with it
|
||||
_profileRepository.Save(configuration.Entity);
|
||||
|
||||
OnProfileAdded(new ProfileConfigurationEventArgs(configuration));
|
||||
return configuration;
|
||||
@@ -303,7 +314,18 @@ internal class ProfileService : IProfileService
|
||||
profile.IsFreshImport = false;
|
||||
profile.ProfileEntity.IsFreshImport = false;
|
||||
|
||||
_profileRepository.Save(profile.Configuration.Entity);
|
||||
// A copy made by CloneProfileConfiguration has its own stored data, save it into that of the original
|
||||
ProfileContainerEntity entity = profile.Configuration.Entity;
|
||||
ProfileConfiguration? original = ProfileCategories
|
||||
.SelectMany(c => c.ProfileConfigurations)
|
||||
.FirstOrDefault(c => c.Entity != entity && c.Entity.Id == entity.Id);
|
||||
if (original != null)
|
||||
{
|
||||
original.Entity.Profile = CopyEntity(entity.Profile);
|
||||
entity = original.Entity;
|
||||
}
|
||||
|
||||
_profileRepository.Save(entity);
|
||||
|
||||
// If the provided profile is external (cloned or from the workshop?) but it is loaded locally too, reload the local instance
|
||||
// A bit dodge but it ensures local instances always represent the latest stored version
|
||||
@@ -429,6 +451,7 @@ internal class ProfileService : IProfileService
|
||||
profileConfiguration.LoadModules(modules);
|
||||
SaveProfileCategory(category);
|
||||
|
||||
OnProfileAdded(new ProfileConfigurationEventArgs(profileConfiguration));
|
||||
return profileConfiguration;
|
||||
}
|
||||
|
||||
@@ -448,6 +471,11 @@ internal class ProfileService : IProfileService
|
||||
SaveProfileCategory(profile.Configuration.Category);
|
||||
}
|
||||
|
||||
private static T CopyEntity<T>(T entity)
|
||||
{
|
||||
return CoreJson.Deserialize<T>(CoreJson.Serialize(entity))!;
|
||||
}
|
||||
|
||||
private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e)
|
||||
{
|
||||
_pendingKeyboardEvents.Add(e);
|
||||
|
||||
Reference in new issue
Block a user