diff --git a/src/settings-ui/Settings.UI.Library/AdvancedPasteCustomActions.cs b/src/settings-ui/Settings.UI.Library/AdvancedPasteCustomActions.cs index 5ab4331393..87d74bae5f 100644 --- a/src/settings-ui/Settings.UI.Library/AdvancedPasteCustomActions.cs +++ b/src/settings-ui/Settings.UI.Library/AdvancedPasteCustomActions.cs @@ -10,7 +10,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library; public sealed class AdvancedPasteCustomActions { - private static readonly JsonSerializerOptions _serializerOptions = new() + private static readonly JsonSerializerOptions _serializerOptions = new(SettingsSerializationContext.Default.Options) { WriteIndented = true, }; diff --git a/src/settings-ui/Settings.UI.Library/AdvancedPasteProperties.cs b/src/settings-ui/Settings.UI.Library/AdvancedPasteProperties.cs index e3f6081266..9e2fa7ee12 100644 --- a/src/settings-ui/Settings.UI.Library/AdvancedPasteProperties.cs +++ b/src/settings-ui/Settings.UI.Library/AdvancedPasteProperties.cs @@ -104,6 +104,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public PasteAIConfiguration PasteAIConfiguration { get; set; } public override string ToString() - => JsonSerializer.Serialize(this); + => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.AdvancedPasteProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/BasePTModuleSettings.cs b/src/settings-ui/Settings.UI.Library/BasePTModuleSettings.cs index ef99b37216..82869fd9aa 100644 --- a/src/settings-ui/Settings.UI.Library/BasePTModuleSettings.cs +++ b/src/settings-ui/Settings.UI.Library/BasePTModuleSettings.cs @@ -2,13 +2,32 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Text.Json; using System.Text.Json.Serialization; namespace Microsoft.PowerToys.Settings.UI.Library { + /// + /// Base class for all PowerToys module settings. + /// + /// + /// IMPORTANT for Native AOT compatibility: + /// When creating a new class that inherits from , + /// you MUST register it in by adding a + /// [JsonSerializable(typeof(YourNewSettingsClass))] attribute. + /// Failure to register the type will cause to throw + /// at runtime. + /// See for registration instructions. + /// public abstract class BasePTModuleSettings { + // Cached JsonSerializerOptions for Native AOT compatibility + private static readonly JsonSerializerOptions _jsonSerializerOptions = new JsonSerializerOptions + { + TypeInfoResolver = SettingsSerializationContext.Default, + }; + // Gets or sets name of the powertoy module. [JsonPropertyName("name")] public string Name { get; set; } @@ -17,11 +36,33 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("version")] public string Version { get; set; } - // converts the current to a json string. + /// + /// Converts the current settings object to a JSON string. + /// + /// JSON string representation of this settings object. + /// + /// Thrown when the runtime type is not registered in . + /// All derived types must be registered with [JsonSerializable(typeof(YourType))] attribute. + /// + /// + /// This method uses Native AOT-compatible JSON serialization. The runtime type must be + /// registered in for serialization to work. + /// public virtual string ToJsonString() { // By default JsonSerializer will only serialize the properties in the base class. This can be avoided by passing the object type (more details at https://stackoverflow.com/a/62498888) - return JsonSerializer.Serialize(this, GetType()); + var runtimeType = GetType(); + + // For Native AOT compatibility, get JsonTypeInfo from the TypeInfoResolver + var typeInfo = _jsonSerializerOptions.TypeInfoResolver?.GetTypeInfo(runtimeType, _jsonSerializerOptions); + + if (typeInfo == null) + { + throw new InvalidOperationException($"Type {runtimeType.FullName} is not registered in SettingsSerializationContext. Please add it to the [JsonSerializable] attributes."); + } + + // Use AOT-friendly serialization + return JsonSerializer.Serialize(this, typeInfo); } public override int GetHashCode() diff --git a/src/settings-ui/Settings.UI.Library/BoolProperty.cs b/src/settings-ui/Settings.UI.Library/BoolProperty.cs index 6842770a79..96b0807dd1 100644 --- a/src/settings-ui/Settings.UI.Library/BoolProperty.cs +++ b/src/settings-ui/Settings.UI.Library/BoolProperty.cs @@ -37,7 +37,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.BoolProperty); } public bool TryToCmdRepresentable(out string result) diff --git a/src/settings-ui/Settings.UI.Library/BoolPropertyJsonConverter.cs b/src/settings-ui/Settings.UI.Library/BoolPropertyJsonConverter.cs index 3cbc0b72b5..140bbffec1 100644 --- a/src/settings-ui/Settings.UI.Library/BoolPropertyJsonConverter.cs +++ b/src/settings-ui/Settings.UI.Library/BoolPropertyJsonConverter.cs @@ -12,14 +12,14 @@ namespace Microsoft.PowerToys.Settings.UI.Library { public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - var boolProperty = JsonSerializer.Deserialize(ref reader, options); + var boolProperty = JsonSerializer.Deserialize(ref reader, SettingsSerializationContext.Default.BoolProperty); return boolProperty.Value; } public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options) { var boolProperty = new BoolProperty(value); - JsonSerializer.Serialize(writer, boolProperty, options); + JsonSerializer.Serialize(writer, boolProperty, SettingsSerializationContext.Default.BoolProperty); } } } diff --git a/src/settings-ui/Settings.UI.Library/CmdPalProperties.cs b/src/settings-ui/Settings.UI.Library/CmdPalProperties.cs index 9102609b6b..c738335827 100644 --- a/src/settings-ui/Settings.UI.Library/CmdPalProperties.cs +++ b/src/settings-ui/Settings.UI.Library/CmdPalProperties.cs @@ -43,7 +43,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library if (doc.RootElement.TryGetProperty(nameof(Hotkey), out JsonElement hotkeyElement)) { - Hotkey = JsonSerializer.Deserialize(hotkeyElement.GetRawText()); + Hotkey = JsonSerializer.Deserialize(hotkeyElement.GetRawText(), SettingsSerializationContext.Default.HotkeySettings); } } catch (Exception) diff --git a/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs b/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs index c4d870cfbd..45548791b6 100644 --- a/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs +++ b/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs @@ -87,6 +87,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public bool ShowColorName { get; set; } public override string ToString() - => JsonSerializer.Serialize(this); + => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ColorPickerProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/ColorPickerPropertiesVersion1.cs b/src/settings-ui/Settings.UI.Library/ColorPickerPropertiesVersion1.cs index 24f593213b..bc9f0d9f6f 100644 --- a/src/settings-ui/Settings.UI.Library/ColorPickerPropertiesVersion1.cs +++ b/src/settings-ui/Settings.UI.Library/ColorPickerPropertiesVersion1.cs @@ -54,6 +54,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public bool ShowColorName { get; set; } public override string ToString() - => JsonSerializer.Serialize(this); + => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ColorPickerPropertiesVersion1); } } diff --git a/src/settings-ui/Settings.UI.Library/DoubleProperty.cs b/src/settings-ui/Settings.UI.Library/DoubleProperty.cs index 7854f70529..701268b3be 100644 --- a/src/settings-ui/Settings.UI.Library/DoubleProperty.cs +++ b/src/settings-ui/Settings.UI.Library/DoubleProperty.cs @@ -27,7 +27,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library // Returns a JSON version of the class settings configuration class. public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.DoubleProperty); } } } diff --git a/src/settings-ui/Settings.UI.Library/FileLocksmithLocalProperties.cs b/src/settings-ui/Settings.UI.Library/FileLocksmithLocalProperties.cs index 747baf6dff..57e3d842c4 100644 --- a/src/settings-ui/Settings.UI.Library/FileLocksmithLocalProperties.cs +++ b/src/settings-ui/Settings.UI.Library/FileLocksmithLocalProperties.cs @@ -21,7 +21,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.FileLocksmithLocalProperties); } // This function is required to implement the ISettingsConfig interface and obtain the settings configurations. diff --git a/src/settings-ui/Settings.UI.Library/FileLocksmithProperties.cs b/src/settings-ui/Settings.UI.Library/FileLocksmithProperties.cs index 3ec6e6d492..a6e37e9ba3 100644 --- a/src/settings-ui/Settings.UI.Library/FileLocksmithProperties.cs +++ b/src/settings-ui/Settings.UI.Library/FileLocksmithProperties.cs @@ -17,6 +17,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("bool_show_extended_menu")] public BoolProperty ExtendedContextMenuOnly { get; set; } - public override string ToString() => JsonSerializer.Serialize(this); + public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.FileLocksmithProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/GeneralSettings.cs b/src/settings-ui/Settings.UI.Library/GeneralSettings.cs index 0f380aca78..8bd9390df7 100644 --- a/src/settings-ui/Settings.UI.Library/GeneralSettings.cs +++ b/src/settings-ui/Settings.UI.Library/GeneralSettings.cs @@ -119,7 +119,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library // converts the current to a json string. public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.GeneralSettings); } private static string DefaultPowertoysVersion() diff --git a/src/settings-ui/Settings.UI.Library/GeneralSettingsCustomAction.cs b/src/settings-ui/Settings.UI.Library/GeneralSettingsCustomAction.cs index f180ca3186..d9cc2727e8 100644 --- a/src/settings-ui/Settings.UI.Library/GeneralSettingsCustomAction.cs +++ b/src/settings-ui/Settings.UI.Library/GeneralSettingsCustomAction.cs @@ -23,7 +23,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.GeneralSettingsCustomAction); } } } diff --git a/src/settings-ui/Settings.UI.Library/Helpers/SunTimes.cs b/src/settings-ui/Settings.UI.Library/Helpers/SunTimes.cs index 2f4f31fc57..6c24d1c557 100644 --- a/src/settings-ui/Settings.UI.Library/Helpers/SunTimes.cs +++ b/src/settings-ui/Settings.UI.Library/Helpers/SunTimes.cs @@ -12,13 +12,18 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Helpers { public struct SunTimes { - public int SunriseHour; - public int SunriseMinute; - public int SunsetHour; - public int SunsetMinute; - public string Text; + public int SunriseHour { get; set; } - public bool HasSunrise; - public bool HasSunset; + public int SunriseMinute { get; set; } + + public int SunsetHour { get; set; } + + public int SunsetMinute { get; set; } + + public string Text { get; set; } + + public bool HasSunrise { get; set; } + + public bool HasSunset { get; set; } } } diff --git a/src/settings-ui/Settings.UI.Library/ImageResizerProperties.cs b/src/settings-ui/Settings.UI.Library/ImageResizerProperties.cs index acef5a2f4d..90080d1c5a 100644 --- a/src/settings-ui/Settings.UI.Library/ImageResizerProperties.cs +++ b/src/settings-ui/Settings.UI.Library/ImageResizerProperties.cs @@ -86,7 +86,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ImageResizerProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/ImageResizerSettings.cs b/src/settings-ui/Settings.UI.Library/ImageResizerSettings.cs index 97f785d6c2..f3dffca9a0 100644 --- a/src/settings-ui/Settings.UI.Library/ImageResizerSettings.cs +++ b/src/settings-ui/Settings.UI.Library/ImageResizerSettings.cs @@ -37,8 +37,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToJsonString() { - var options = _serializerOptions; - return JsonSerializer.Serialize(this, options); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ImageResizerSettings); } public string GetModuleName() diff --git a/src/settings-ui/Settings.UI.Library/IntProperty.cs b/src/settings-ui/Settings.UI.Library/IntProperty.cs index ac6a87ad4a..63fae3e22b 100644 --- a/src/settings-ui/Settings.UI.Library/IntProperty.cs +++ b/src/settings-ui/Settings.UI.Library/IntProperty.cs @@ -42,7 +42,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library // Returns a JSON version of the class settings configuration class. public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.IntProperty); } public static implicit operator IntProperty(int v) diff --git a/src/settings-ui/Settings.UI.Library/KeyboardManagerProfile.cs b/src/settings-ui/Settings.UI.Library/KeyboardManagerProfile.cs index 983f9a1f6a..091c70eb39 100644 --- a/src/settings-ui/Settings.UI.Library/KeyboardManagerProfile.cs +++ b/src/settings-ui/Settings.UI.Library/KeyboardManagerProfile.cs @@ -34,7 +34,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.KeyboardManagerProfile); } public string GetModuleName() diff --git a/src/settings-ui/Settings.UI.Library/MeasureToolProperties.cs b/src/settings-ui/Settings.UI.Library/MeasureToolProperties.cs index 5edc9f9175..48fc544ed4 100644 --- a/src/settings-ui/Settings.UI.Library/MeasureToolProperties.cs +++ b/src/settings-ui/Settings.UI.Library/MeasureToolProperties.cs @@ -46,6 +46,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public IntProperty DefaultMeasureStyle { get; set; } - public override string ToString() => JsonSerializer.Serialize(this); + public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.MeasureToolProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs b/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs index e234ee6b2f..2970cdb654 100644 --- a/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs +++ b/src/settings-ui/Settings.UI.Library/MouseWithoutBordersProperties.cs @@ -15,8 +15,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library public struct ConnectionRequest #pragma warning restore SA1649 // File name should match first type name { - public string PCName; - public string SecurityKey; + public string PCName { get; set; } + + public string SecurityKey { get; set; } } public struct NewKeyGenerationRequest diff --git a/src/settings-ui/Settings.UI.Library/NewPlusProperties.cs b/src/settings-ui/Settings.UI.Library/NewPlusProperties.cs index ccdbeb9601..c2ad8cc328 100644 --- a/src/settings-ui/Settings.UI.Library/NewPlusProperties.cs +++ b/src/settings-ui/Settings.UI.Library/NewPlusProperties.cs @@ -33,6 +33,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("ReplaceVariables")] public BoolProperty ReplaceVariables { get; set; } - public override string ToString() => JsonSerializer.Serialize(this); + public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.NewPlusProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/OutGoingGeneralSettings.cs b/src/settings-ui/Settings.UI.Library/OutGoingGeneralSettings.cs index d040016660..dad5f02b25 100644 --- a/src/settings-ui/Settings.UI.Library/OutGoingGeneralSettings.cs +++ b/src/settings-ui/Settings.UI.Library/OutGoingGeneralSettings.cs @@ -23,7 +23,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.OutGoingGeneralSettings); } } } diff --git a/src/settings-ui/Settings.UI.Library/OutGoingLanguageSettings.cs b/src/settings-ui/Settings.UI.Library/OutGoingLanguageSettings.cs index 61a16eb778..7f2d55faf6 100644 --- a/src/settings-ui/Settings.UI.Library/OutGoingLanguageSettings.cs +++ b/src/settings-ui/Settings.UI.Library/OutGoingLanguageSettings.cs @@ -23,7 +23,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.OutGoingLanguageSettings); } } } diff --git a/src/settings-ui/Settings.UI.Library/PasteAIConfiguration.cs b/src/settings-ui/Settings.UI.Library/PasteAIConfiguration.cs index 3308ab535e..2b743c4670 100644 --- a/src/settings-ui/Settings.UI.Library/PasteAIConfiguration.cs +++ b/src/settings-ui/Settings.UI.Library/PasteAIConfiguration.cs @@ -64,7 +64,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public AIServiceType ActiveServiceTypeKind => ActiveProvider?.ServiceTypeKind ?? AIServiceType.OpenAI; public override string ToString() - => JsonSerializer.Serialize(this); + => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PasteAIConfiguration); protected bool SetProperty(ref T field, T value, [CallerMemberName] string propertyName = null) { diff --git a/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs b/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs index fa2fb3bf6c..b139076fe8 100644 --- a/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs +++ b/src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs @@ -34,7 +34,7 @@ namespace Settings.UI.Library public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, Microsoft.PowerToys.Settings.UI.Library.SettingsSerializationContext.Default.PeekPreviewSettings); } public string GetModuleName() diff --git a/src/settings-ui/Settings.UI.Library/PeekProperties.cs b/src/settings-ui/Settings.UI.Library/PeekProperties.cs index e6eea746d6..e8b8692888 100644 --- a/src/settings-ui/Settings.UI.Library/PeekProperties.cs +++ b/src/settings-ui/Settings.UI.Library/PeekProperties.cs @@ -32,6 +32,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public BoolProperty EnableSpaceToActivate { get; set; } - public override string ToString() => JsonSerializer.Serialize(this); + public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PeekProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/PowerOcrProperties.cs b/src/settings-ui/Settings.UI.Library/PowerOcrProperties.cs index 5cba3cfb3e..1570038f22 100644 --- a/src/settings-ui/Settings.UI.Library/PowerOcrProperties.cs +++ b/src/settings-ui/Settings.UI.Library/PowerOcrProperties.cs @@ -24,6 +24,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library public string PreferredLanguage { get; set; } public override string ToString() - => JsonSerializer.Serialize(this); + => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PowerOcrProperties); } } diff --git a/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs b/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs index 72113e67fc..b99b19aae7 100644 --- a/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs +++ b/src/settings-ui/Settings.UI.Library/PowerPreviewProperties.cs @@ -340,7 +340,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PowerPreviewProperties); } private static void LogTelemetryEvent(bool value, [CallerMemberName] string propertyName = null) diff --git a/src/settings-ui/Settings.UI.Library/PowerRenameLocalProperties.cs b/src/settings-ui/Settings.UI.Library/PowerRenameLocalProperties.cs index 726faf2bc0..cec4b472c7 100644 --- a/src/settings-ui/Settings.UI.Library/PowerRenameLocalProperties.cs +++ b/src/settings-ui/Settings.UI.Library/PowerRenameLocalProperties.cs @@ -54,7 +54,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public string ToJsonString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PowerRenameLocalProperties); } // This function is required to implement the ISettingsConfig interface and obtain the settings configurations. diff --git a/src/settings-ui/Settings.UI.Library/SettingsSerializationContext.cs b/src/settings-ui/Settings.UI.Library/SettingsSerializationContext.cs new file mode 100644 index 0000000000..8ffcfb2e7c --- /dev/null +++ b/src/settings-ui/Settings.UI.Library/SettingsSerializationContext.cs @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json.Serialization; +using SettingsUILibrary = Settings.UI.Library; +using SettingsUILibraryHelpers = Settings.UI.Library.Helpers; + +namespace Microsoft.PowerToys.Settings.UI.Library +{ + /// + /// JSON serialization context for Native AOT compatibility. + /// This context provides source-generated serialization for all PowerToys settings types. + /// + /// + /// ⚠️ CRITICAL REQUIREMENT FOR ALL NEW SETTINGS CLASSES ⚠️ + /// + /// When adding a new PowerToys module or any class that inherits from , + /// you MUST add a [JsonSerializable(typeof(YourNewSettingsClass))] attribute + /// to this class. This is a MANDATORY step for Native AOT compatibility. + /// + /// Steps to add a new settings class: + /// + /// Create your new settings class (e.g., MyNewModuleSettings) that inherits from + /// Add [JsonSerializable(typeof(MyNewModuleSettings))] attribute to this class + /// If you have a corresponding Properties class, also add [JsonSerializable(typeof(MyNewModuleProperties))] + /// Rebuild the project - source generator will create serialization code at compile time + /// + /// ⚠️ Failure to register types will cause runtime errors: + /// + /// If you forget to add the [JsonSerializable] attribute, calling ToJsonString() or + /// deserialization methods will throw at runtime with a clear + /// error message indicating which type is missing registration. + /// + /// + [JsonSourceGenerationOptions( + WriteIndented = false, + DefaultIgnoreCondition = JsonIgnoreCondition.Never, + IncludeFields = true)] + + // Main Settings Classes + [JsonSerializable(typeof(GeneralSettings))] + [JsonSerializable(typeof(AdvancedPasteSettings))] + [JsonSerializable(typeof(AlwaysOnTopSettings))] + [JsonSerializable(typeof(AwakeSettings))] + [JsonSerializable(typeof(CmdNotFoundSettings))] + [JsonSerializable(typeof(ColorPickerSettings))] + [JsonSerializable(typeof(ColorPickerSettingsVersion1))] + [JsonSerializable(typeof(CropAndLockSettings))] + [JsonSerializable(typeof(CursorWrapSettings))] + [JsonSerializable(typeof(EnvironmentVariablesSettings))] + [JsonSerializable(typeof(FancyZonesSettings))] + [JsonSerializable(typeof(FileLocksmithSettings))] + [JsonSerializable(typeof(FindMyMouseSettings))] + [JsonSerializable(typeof(HostsSettings))] + [JsonSerializable(typeof(ImageResizerSettings))] + [JsonSerializable(typeof(KeyboardManagerSettings))] + [JsonSerializable(typeof(SettingsUILibrary.LightSwitchSettings))] + [JsonSerializable(typeof(MeasureToolSettings))] + [JsonSerializable(typeof(MouseHighlighterSettings))] + [JsonSerializable(typeof(MouseJumpSettings))] + [JsonSerializable(typeof(MousePointerCrosshairsSettings))] + [JsonSerializable(typeof(MouseWithoutBordersSettings))] + [JsonSerializable(typeof(NewPlusSettings))] + [JsonSerializable(typeof(PeekSettings))] + [JsonSerializable(typeof(PowerAccentSettings))] + [JsonSerializable(typeof(PowerLauncherSettings))] + [JsonSerializable(typeof(PowerOcrSettings))] + [JsonSerializable(typeof(PowerPreviewSettings))] + [JsonSerializable(typeof(PowerRenameSettings))] + [JsonSerializable(typeof(RegistryPreviewSettings))] + [JsonSerializable(typeof(ShortcutGuideSettings))] + [JsonSerializable(typeof(WorkspacesSettings))] + [JsonSerializable(typeof(ZoomItSettings))] + + // Properties Classes + [JsonSerializable(typeof(AdvancedPasteProperties))] + [JsonSerializable(typeof(AlwaysOnTopProperties))] + [JsonSerializable(typeof(AwakeProperties))] + [JsonSerializable(typeof(CmdPalProperties))] + [JsonSerializable(typeof(ColorPickerProperties))] + [JsonSerializable(typeof(ColorPickerPropertiesVersion1))] + [JsonSerializable(typeof(CropAndLockProperties))] + [JsonSerializable(typeof(CursorWrapProperties))] + [JsonSerializable(typeof(EnvironmentVariablesProperties))] + [JsonSerializable(typeof(FileLocksmithProperties))] + [JsonSerializable(typeof(FileLocksmithLocalProperties))] + [JsonSerializable(typeof(FindMyMouseProperties))] + [JsonSerializable(typeof(FZConfigProperties))] + [JsonSerializable(typeof(HostsProperties))] + [JsonSerializable(typeof(ImageResizerProperties))] + [JsonSerializable(typeof(KeyboardManagerProperties))] + [JsonSerializable(typeof(KeyboardManagerProfile))] + [JsonSerializable(typeof(LightSwitchProperties))] + [JsonSerializable(typeof(MeasureToolProperties))] + [JsonSerializable(typeof(MouseHighlighterProperties))] + [JsonSerializable(typeof(MouseJumpProperties))] + [JsonSerializable(typeof(MousePointerCrosshairsProperties))] + [JsonSerializable(typeof(MouseWithoutBordersProperties))] + [JsonSerializable(typeof(NewPlusProperties))] + [JsonSerializable(typeof(PeekProperties))] + [JsonSerializable(typeof(SettingsUILibrary.PeekPreviewSettings))] + [JsonSerializable(typeof(PowerAccentProperties))] + [JsonSerializable(typeof(PowerLauncherProperties))] + [JsonSerializable(typeof(PowerOcrProperties))] + [JsonSerializable(typeof(PowerPreviewProperties))] + [JsonSerializable(typeof(PowerRenameProperties))] + [JsonSerializable(typeof(PowerRenameLocalProperties))] + [JsonSerializable(typeof(RegistryPreviewProperties))] + [JsonSerializable(typeof(ShortcutConflictProperties))] + [JsonSerializable(typeof(ShortcutGuideProperties))] + [JsonSerializable(typeof(WorkspacesProperties))] + [JsonSerializable(typeof(ZoomItProperties))] + + // Base Property Types (used throughout settings) + [JsonSerializable(typeof(BoolProperty))] + [JsonSerializable(typeof(StringProperty))] + [JsonSerializable(typeof(IntProperty))] + [JsonSerializable(typeof(DoubleProperty))] + + // Helper and Utility Types + [JsonSerializable(typeof(HotkeySettings))] + [JsonSerializable(typeof(ColorFormatModel))] + [JsonSerializable(typeof(ImageSize))] + [JsonSerializable(typeof(KeysDataModel))] + [JsonSerializable(typeof(EnabledModules))] + [JsonSerializable(typeof(GeneralSettingsCustomAction))] + [JsonSerializable(typeof(OutGoingGeneralSettings))] + [JsonSerializable(typeof(OutGoingLanguageSettings))] + [JsonSerializable(typeof(AdvancedPasteCustomActions))] + [JsonSerializable(typeof(AdvancedPasteAdditionalActions))] + [JsonSerializable(typeof(AdvancedPasteCustomAction))] + [JsonSerializable(typeof(AdvancedPasteAdditionalAction))] + [JsonSerializable(typeof(AdvancedPastePasteAsFileAction))] + [JsonSerializable(typeof(AdvancedPasteTranscodeAction))] + [JsonSerializable(typeof(PasteAIConfiguration))] + [JsonSerializable(typeof(PasteAIProviderDefinition))] + [JsonSerializable(typeof(ImageResizerSizes))] + [JsonSerializable(typeof(ImageResizerCustomSizeProperty))] + [JsonSerializable(typeof(KeyboardKeysProperty))] + [JsonSerializable(typeof(SettingsUILibraryHelpers.SearchLocation))] + + // IPC Send Message Wrapper Classes (Snd*) + [JsonSerializable(typeof(SndAwakeSettings))] + [JsonSerializable(typeof(SndCursorWrapSettings))] + [JsonSerializable(typeof(SndFindMyMouseSettings))] + [JsonSerializable(typeof(SndLightSwitchSettings))] + [JsonSerializable(typeof(SndMouseHighlighterSettings))] + [JsonSerializable(typeof(SndMouseJumpSettings))] + [JsonSerializable(typeof(SndMousePointerCrosshairsSettings))] + [JsonSerializable(typeof(SndPowerAccentSettings))] + [JsonSerializable(typeof(SndPowerPreviewSettings))] + [JsonSerializable(typeof(SndPowerRenameSettings))] + [JsonSerializable(typeof(SndShortcutGuideSettings))] + + // IPC Message Generic Wrapper Types (SndModuleSettings) + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + [JsonSerializable(typeof(SndModuleSettings))] + + public partial class SettingsSerializationContext : JsonSerializerContext + { + } +} diff --git a/src/settings-ui/Settings.UI.Library/SettingsUtils.cs b/src/settings-ui/Settings.UI.Library/SettingsUtils.cs index ea466f7077..6109df0646 100644 --- a/src/settings-ui/Settings.UI.Library/SettingsUtils.cs +++ b/src/settings-ui/Settings.UI.Library/SettingsUtils.cs @@ -2,6 +2,8 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable + using System; using System.IO; using System.IO.Abstractions; @@ -18,27 +20,28 @@ namespace Microsoft.PowerToys.Settings.UI.Library private const string DefaultModuleName = ""; private readonly IFile _file; private readonly ISettingsPath _settingsPath; - - private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions - { - MaxDepth = 0, - IncludeFields = true, - }; + private readonly JsonSerializerOptions _serializerOptions; public SettingsUtils() : this(new FileSystem()) { } - public SettingsUtils(IFileSystem fileSystem) - : this(fileSystem?.File, new SettingPath(fileSystem?.Directory, fileSystem?.Path)) + public SettingsUtils(IFileSystem? fileSystem, JsonSerializerOptions? serializerOptions = null) + : this(fileSystem?.File!, new SettingPath(fileSystem?.Directory, fileSystem?.Path), serializerOptions) { } - public SettingsUtils(IFile file, ISettingsPath settingPath) + public SettingsUtils(IFile file, ISettingsPath settingPath, JsonSerializerOptions? serializerOptions = null) { _file = file ?? throw new ArgumentNullException(nameof(file)); _settingsPath = settingPath; + _serializerOptions = serializerOptions ?? new JsonSerializerOptions + { + MaxDepth = 0, + IncludeFields = true, + TypeInfoResolver = SettingsSerializationContext.Default, + }; } public bool SettingsExists(string powertoy = DefaultModuleName, string fileName = DefaultFileName) @@ -108,7 +111,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library /// This function creates a file in the powertoy folder if it does not exist and returns an object with default properties. /// /// Deserialized json settings object. - public T GetSettingsOrDefault(string powertoy = DefaultModuleName, string fileName = DefaultFileName, Func settingsUpgrader = null) + public T GetSettingsOrDefault(string powertoy = DefaultModuleName, string fileName = DefaultFileName, Func? settingsUpgrader = null) where T : ISettingsConfig, new() where T2 : ISettingsConfig, new() { @@ -128,7 +131,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library try { T2 oldSettings = GetSettings(powertoy, fileName); - T newSettings = (T)settingsUpgrader(oldSettings); + T newSettings = (T)settingsUpgrader!(oldSettings); Logger.LogInfo($"Settings file {fileName} for {powertoy} was read successfully in the old format."); // If the file needs to be modified, to save the new configurations accordingly. @@ -156,7 +159,22 @@ namespace Microsoft.PowerToys.Settings.UI.Library return newSettingsItem; } - // Given the powerToy folder name and filename to be accessed, this function deserializes and returns the file. + /// + /// Deserializes settings from a JSON file. + /// + /// The settings type to deserialize. Must be registered in . + /// The PowerToy module folder name. + /// The settings file name. + /// Deserialized settings object of type T. + /// + /// Thrown when type T is not registered in . + /// All settings types must be registered with [JsonSerializable(typeof(T))] attribute + /// for Native AOT compatibility. + /// + /// + /// This method uses Native AOT-compatible JSON deserialization. Type T must be registered + /// in before calling this method. + /// private T GetFile(string powertoyFolderName = DefaultModuleName, string fileName = DefaultFileName) { // Adding Trim('\0') to overcome possible NTFS file corruption. @@ -165,8 +183,16 @@ namespace Microsoft.PowerToys.Settings.UI.Library // The file itself did write the content correctly but something is off with the actual end of the file, hence the 0x00 bug var jsonSettingsString = _file.ReadAllText(_settingsPath.GetSettingsPath(powertoyFolderName, fileName)).Trim('\0'); - var options = _serializerOptions; - return JsonSerializer.Deserialize(jsonSettingsString, options); + // For Native AOT compatibility, get JsonTypeInfo from the TypeInfoResolver + var typeInfo = _serializerOptions.TypeInfoResolver?.GetTypeInfo(typeof(T), _serializerOptions); + + if (typeInfo == null) + { + throw new InvalidOperationException($"Type {typeof(T).FullName} is not registered in SettingsSerializationContext. Please add it to the [JsonSerializable] attributes."); + } + + // Use AOT-friendly deserialization + return (T)JsonSerializer.Deserialize(jsonSettingsString, typeInfo)!; } // Save settings to a json file. diff --git a/src/settings-ui/Settings.UI.Library/StringProperty.cs b/src/settings-ui/Settings.UI.Library/StringProperty.cs index 8b0d86b177..5d521189dc 100644 --- a/src/settings-ui/Settings.UI.Library/StringProperty.cs +++ b/src/settings-ui/Settings.UI.Library/StringProperty.cs @@ -27,7 +27,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library // Returns a JSON version of the class settings configuration class. public override string ToString() { - return JsonSerializer.Serialize(this); + return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.StringProperty); } public static StringProperty ToStringProperty(string v) diff --git a/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsSerializationTests.cs b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsSerializationTests.cs new file mode 100644 index 0000000000..29fe1d0508 --- /dev/null +++ b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsSerializationTests.cs @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Linq; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Library; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace CommonLibTest +{ + [TestClass] + public class BasePTModuleSettingsSerializationTests + { + /// + /// Test to verify that all classes derived from BasePTModuleSettings are registered + /// in the SettingsSerializationContext for Native AOT compatibility. + /// + [TestMethod] + public void AllBasePTModuleSettingsClasses_ShouldBeRegisteredInSerializationContext() + { + // Arrange + var assembly = typeof(BasePTModuleSettings).Assembly; + var settingsClasses = assembly.GetTypes() + .Where(t => typeof(BasePTModuleSettings).IsAssignableFrom(t) && !t.IsAbstract && t != typeof(BasePTModuleSettings)) + .OrderBy(t => t.Name) + .ToList(); + + Assert.IsTrue(settingsClasses.Count > 0, "No BasePTModuleSettings derived classes found. This test may be broken."); + + var jsonSerializerOptions = new JsonSerializerOptions + { + TypeInfoResolver = SettingsSerializationContext.Default, + }; + + var unregisteredTypes = new System.Collections.Generic.List(); + + // Act & Assert + foreach (var settingsType in settingsClasses) + { + var typeInfo = jsonSerializerOptions.TypeInfoResolver?.GetTypeInfo(settingsType, jsonSerializerOptions); + + if (typeInfo == null) + { + unregisteredTypes.Add(settingsType.FullName ?? settingsType.Name); + } + } + + // Assert + if (unregisteredTypes.Count > 0) + { + var errorMessage = $"The following {unregisteredTypes.Count} settings class(es) are NOT registered in SettingsSerializationContext:\n" + + $"{string.Join("\n", unregisteredTypes.Select(t => $" - {t}"))}\n\n" + + $"Please add [JsonSerializable(typeof(ClassName))] attribute to SettingsSerializationContext.cs for each missing type."; + Assert.Fail(errorMessage); + } + + // Print success message with count + Console.WriteLine($"✓ All {settingsClasses.Count} BasePTModuleSettings derived classes are properly registered in SettingsSerializationContext."); + } + + /// + /// Test to verify that calling ToJsonString() on an unregistered type throws InvalidOperationException + /// with a helpful error message. + /// + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void ToJsonString_UnregisteredType_ShouldThrowInvalidOperationException() + { + // Arrange + var unregisteredSettings = new UnregisteredTestSettings + { + Name = "UnregisteredModule", + Version = "1.0.0", + }; + + // Act - This should throw InvalidOperationException + var jsonString = unregisteredSettings.ToJsonString(); + + // Assert - Exception should be thrown, so this line should never be reached + Assert.Fail("Expected InvalidOperationException was not thrown."); + } + + /// + /// Test to verify that the error message for unregistered types is helpful and contains + /// necessary information for developers. + /// + [TestMethod] + public void ToJsonString_UnregisteredType_ShouldHaveHelpfulErrorMessage() + { + // Arrange + var unregisteredSettings = new UnregisteredTestSettings + { + Name = "UnregisteredModule", + Version = "1.0.0", + }; + + // Act & Assert + try + { + var jsonString = unregisteredSettings.ToJsonString(); + Assert.Fail("Expected InvalidOperationException was not thrown."); + } + catch (InvalidOperationException ex) + { + // Verify the error message contains helpful information + Assert.IsTrue(ex.Message.Contains("UnregisteredTestSettings"), "Error message should contain the type name."); + Assert.IsTrue(ex.Message.Contains("SettingsSerializationContext"), "Error message should mention SettingsSerializationContext."); + Assert.IsTrue(ex.Message.Contains("JsonSerializable"), "Error message should mention JsonSerializable attribute."); + + Console.WriteLine($"✓ Error message is helpful: {ex.Message}"); + } + } + + /// + /// Test class that is intentionally NOT registered in SettingsSerializationContext + /// to verify error handling for unregistered types. + /// + private sealed class UnregisteredTestSettings : BasePTModuleSettings + { + // Intentionally empty - this class should NOT be registered in SettingsSerializationContext + } + } +} diff --git a/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs index 8d73d2a6ee..c4e92fb322 100644 --- a/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs +++ b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs @@ -2,8 +2,10 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library.Interfaces; +using Microsoft.PowerToys.Settings.UI.UnitTests; namespace Microsoft.PowerToys.Settings.UnitTest { @@ -24,5 +26,11 @@ namespace Microsoft.PowerToys.Settings.UnitTest { return false; } + + // Override ToJsonString to use test-specific serialization context + public override string ToJsonString() + { + return JsonSerializer.Serialize(this, TestSettingsSerializationContext.Default.BasePTSettingsTest); + } } } diff --git a/src/settings-ui/Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs index 9b75925cb8..37dfcee4d8 100644 --- a/src/settings-ui/Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs +++ b/src/settings-ui/Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs @@ -9,6 +9,7 @@ using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library.Interfaces; +using Microsoft.PowerToys.Settings.UI.UnitTests; using Microsoft.PowerToys.Settings.UnitTest; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -22,7 +23,13 @@ namespace CommonLibTest { // Arrange var mockFileSystem = new MockFileSystem(); - var settingsUtils = new SettingsUtils(mockFileSystem); + var testSerializerOptions = new JsonSerializerOptions + { + MaxDepth = 0, + IncludeFields = true, + TypeInfoResolver = TestSettingsSerializationContext.Default, + }; + var settingsUtils = new SettingsUtils(mockFileSystem, testSerializerOptions); string file_name = "\\test"; string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}"; @@ -42,7 +49,13 @@ namespace CommonLibTest { // Arrange var mockFileSystem = new MockFileSystem(); - var settingsUtils = new SettingsUtils(mockFileSystem); + var testSerializerOptions = new JsonSerializerOptions + { + MaxDepth = 0, + IncludeFields = true, + TypeInfoResolver = TestSettingsSerializationContext.Default, + }; + var settingsUtils = new SettingsUtils(mockFileSystem, testSerializerOptions); string file_name = "test\\Test Folder"; string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}"; diff --git a/src/settings-ui/Settings.UI.UnitTests/TestSettingsSerializationContext.cs b/src/settings-ui/Settings.UI.UnitTests/TestSettingsSerializationContext.cs new file mode 100644 index 0000000000..bf38245105 --- /dev/null +++ b/src/settings-ui/Settings.UI.UnitTests/TestSettingsSerializationContext.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UnitTest; + +namespace Microsoft.PowerToys.Settings.UI.UnitTests +{ + /// + /// JSON serialization context for unit tests. + /// This context provides source-generated serialization for test-specific types. + /// + [JsonSourceGenerationOptions( + WriteIndented = false, + DefaultIgnoreCondition = JsonIgnoreCondition.Never, + IncludeFields = true)] + [JsonSerializable(typeof(BasePTSettingsTest))] + public partial class TestSettingsSerializationContext : JsonSerializerContext + { + } +} diff --git a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs index ef230bde0a..de6421785b 100644 --- a/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs +++ b/src/settings-ui/Settings.UI.UnitTests/ViewModelTests/FancyZones.cs @@ -6,6 +6,7 @@ using System; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Library; +using Microsoft.PowerToys.Settings.UI.Library.Interfaces; using Microsoft.PowerToys.Settings.UI.UnitTests.BackwardsCompatibility; using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.PowerToys.Settings.UI.ViewModels; @@ -100,6 +101,22 @@ namespace ViewModelTests mockFancyZonesSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); } + [TestCleanup] + public void CleanUp() + { + // Reset singleton instances to prevent state pollution between tests + ResetSettingsRepository(); + ResetSettingsRepository(); + } + + private void ResetSettingsRepository() + where T : class, ISettingsConfig, new() + { + var repositoryType = typeof(SettingsRepository); + var field = repositoryType.GetField("settingsRepository", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); + field?.SetValue(null, null); + } + [TestMethod] public void IsEnabledShouldDisableModuleWhenSuccessful() { diff --git a/src/settings-ui/Settings.UI/SerializationContext/SourceGenerationContextContext.cs b/src/settings-ui/Settings.UI/SerializationContext/SourceGenerationContextContext.cs index 838149a04e..dafd6d828b 100644 --- a/src/settings-ui/Settings.UI/SerializationContext/SourceGenerationContextContext.cs +++ b/src/settings-ui/Settings.UI/SerializationContext/SourceGenerationContextContext.cs @@ -10,7 +10,7 @@ using System.Text.Json.Serialization; using System.Threading.Tasks; using Microsoft.PowerToys.Settings.UI.Helpers; using Microsoft.PowerToys.Settings.UI.Library; -using Settings.UI.Library; +using SettingsUILibrary = Settings.UI.Library; namespace Microsoft.PowerToys.Settings.UI.SerializationContext; @@ -23,7 +23,7 @@ namespace Microsoft.PowerToys.Settings.UI.SerializationContext; [JsonSerializable(typeof(FileLocksmithSettings))] [JsonSerializable(typeof(FindMyMouseSettings))] [JsonSerializable(typeof(IList))] -[JsonSerializable(typeof(LightSwitchSettings))] +[JsonSerializable(typeof(SettingsUILibrary.LightSwitchSettings))] [JsonSerializable(typeof(MeasureToolSettings))] [JsonSerializable(typeof(MouseHighlighterSettings))] [JsonSerializable(typeof(MouseJumpSettings))]