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:
RobertBeekman authored and GitHub committed 2026-10-24 16:19:23 +02:00
1 parent 295038f338
commit 83cf6da830
20 files changed
+137 -114

No files matched your search

@@ -115,7 +115,7 @@ public class M0003SystemTextJsonTests
}
[Fact]
public void Migrate_ListDirectlyInsideAList_KeepsItsValuesWrapper()
public void Migrate_ListDirectlyInsideAList_LosesItsValuesWrapperToo()
{
JsonObject profile = OldProfileJson.Parse("""
{"Rows": {"$type": "List", "$values": [{"$type": "List", "$values": [1, 2]}]}}
@@ -123,9 +123,7 @@ public class M0003SystemTextJsonTests
_migration.Migrate(new JsonObject(), profile);
// Pinned as-is: items of a list are only searched for lists in their properties, a list that is itself an item
// keeps its "$values" wrapper. No profile entity has a list of lists, so old profiles aren't affected.
profile.ShouldBeJson("""{"Rows": [{"$values": [1, 2]}]}""");
profile.ShouldBeJson("""{"Rows": [[1, 2]]}""");
}
[Fact]