Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ 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,
TypeInfoResolver = SettingsSerializationContext.Default,
};

[JsonPropertyName("value")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,6 @@ public Dictionary<string, JsonElement> ExtensionData
public PasteAIConfiguration PasteAIConfiguration { get; set; }

public override string ToString()
=> JsonSerializer.Serialize(this);
=> JsonSerializer.Serialize(this, SettingsSerializationContext.Default.AdvancedPasteProperties);
}
}
46 changes: 44 additions & 2 deletions src/settings-ui/Settings.UI.Library/BasePTModuleSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,33 @@
// 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.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Microsoft.PowerToys.Settings.UI.Library
{
/// <summary>
/// Base class for all PowerToys module settings.
/// </summary>
/// <remarks>
/// <para><strong>IMPORTANT for Native AOT compatibility:</strong></para>
/// <para>When creating a new class that inherits from <see cref="BasePTModuleSettings"/>,
/// you MUST register it in <see cref="SettingsSerializationContext"/> by adding a
/// <c>[JsonSerializable(typeof(YourNewSettingsClass))]</c> attribute.</para>
/// <para>Failure to register the type will cause <see cref="ToJsonString"/> to throw
/// <see cref="InvalidOperationException"/> at runtime.</para>
/// <para>See <see cref="SettingsSerializationContext"/> for registration instructions.</para>
/// </remarks>
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; }
Expand All @@ -17,11 +37,33 @@ public abstract class BasePTModuleSettings
[JsonPropertyName("version")]
public string Version { get; set; }

// converts the current to a json string.
/// <summary>
/// Converts the current settings object to a JSON string.
/// </summary>
/// <returns>JSON string representation of this settings object.</returns>
/// <exception cref="InvalidOperationException">
/// Thrown when the runtime type is not registered in <see cref="SettingsSerializationContext"/>.
/// All derived types must be registered with <c>[JsonSerializable(typeof(YourType))]</c> attribute.
/// </exception>
/// <remarks>
/// This method uses Native AOT-compatible JSON serialization. The runtime type must be
/// registered in <see cref="SettingsSerializationContext"/> for serialization to work.
/// </remarks>
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()
Expand Down
2 changes: 1 addition & 1 deletion src/settings-ui/Settings.UI.Library/BoolProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static bool TryParseFromCmd(string cmd, out object result)

public override string ToString()
{
return JsonSerializer.Serialize(this);
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.BoolProperty);
}

public bool TryToCmdRepresentable(out string result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ public class BoolPropertyJsonConverter : JsonConverter<bool>
{
public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var boolProperty = JsonSerializer.Deserialize<BoolProperty>(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);
}
}
}
2 changes: 1 addition & 1 deletion src/settings-ui/Settings.UI.Library/CmdPalProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void InitializeHotkey()

if (doc.RootElement.TryGetProperty(nameof(Hotkey), out JsonElement hotkeyElement))
{
Hotkey = JsonSerializer.Deserialize<HotkeySettings>(hotkeyElement.GetRawText());
Hotkey = JsonSerializer.Deserialize(hotkeyElement.GetRawText(), SettingsSerializationContext.Default.HotkeySettings);
}
}
catch (Exception)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,6 @@ public ColorPickerProperties()
public bool ShowColorName { get; set; }

public override string ToString()
=> JsonSerializer.Serialize(this);
=> JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ColorPickerProperties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ public ColorPickerPropertiesVersion1()
public bool ShowColorName { get; set; }

public override string ToString()
=> JsonSerializer.Serialize(this);
=> JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ColorPickerPropertiesVersion1);
}
}
2 changes: 1 addition & 1 deletion src/settings-ui/Settings.UI.Library/DoubleProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public DoubleProperty(double value)
// 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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public FileLocksmithLocalProperties()

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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ public FileLocksmithProperties()
[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);
}
}
2 changes: 1 addition & 1 deletion src/settings-ui/Settings.UI.Library/GeneralSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public GeneralSettings()
// 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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public GeneralSettingsCustomAction(OutGoingGeneralSettings action)

public override string ToString()
{
return JsonSerializer.Serialize(this);
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.GeneralSettingsCustomAction);
}
}
}
21 changes: 13 additions & 8 deletions src/settings-ui/Settings.UI.Library/Helpers/SunTimes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 bool HasSunrise;
public bool HasSunset;
public int SunriseHour { get; set; }

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; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public ImageResizerProperties(Func<string, string> resourceLoader)

public string ToJsonString()
{
return JsonSerializer.Serialize(this);
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ImageResizerProperties);
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/settings-ui/Settings.UI.Library/ImageResizerSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ public ImageResizerSettings(Func<string, string> resourceLoader)

public override string ToJsonString()
{
var options = _serializerOptions;
return JsonSerializer.Serialize(this, options);
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.ImageResizerSettings);
}

public string GetModuleName()
Expand Down
2 changes: 1 addition & 1 deletion src/settings-ui/Settings.UI.Library/IntProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static bool TryParseFromCmd(string cmd, out object result)
// 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public KeyboardManagerProfile()

public string ToJsonString()
{
return JsonSerializer.Serialize(this);
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.KeyboardManagerProfile);
}

public string GetModuleName()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ public MeasureToolProperties()

public IntProperty DefaultMeasureStyle { get; set; }

public override string ToString() => JsonSerializer.Serialize(this);
public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.MeasureToolProperties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/settings-ui/Settings.UI.Library/NewPlusProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public NewPlusProperties()
[JsonPropertyName("ReplaceVariables")]
public BoolProperty ReplaceVariables { get; set; }

public override string ToString() => JsonSerializer.Serialize(this);
public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.NewPlusProperties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public OutGoingGeneralSettings(GeneralSettings generalSettings)

public override string ToString()
{
return JsonSerializer.Serialize(this);
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.OutGoingGeneralSettings);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public OutGoingLanguageSettings(string language)

public override string ToString()
{
return JsonSerializer.Serialize(this);
return JsonSerializer.Serialize(this, SettingsSerializationContext.Default.OutGoingLanguageSettings);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public PasteAIProviderDefinition ActiveProvider
public AIServiceType ActiveServiceTypeKind => ActiveProvider?.ServiceTypeKind ?? AIServiceType.OpenAI;

public override string ToString()
=> JsonSerializer.Serialize(this);
=> JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PasteAIConfiguration);

protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
Expand Down
2 changes: 1 addition & 1 deletion src/settings-ui/Settings.UI.Library/PeekPreviewSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public PeekPreviewSettings()

public string ToJsonString()
{
return JsonSerializer.Serialize(this);
return JsonSerializer.Serialize(this, Microsoft.PowerToys.Settings.UI.Library.SettingsSerializationContext.Default.PeekPreviewSettings);
}

public string GetModuleName()
Expand Down
2 changes: 1 addition & 1 deletion src/settings-ui/Settings.UI.Library/PeekProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ public PeekProperties()

public BoolProperty EnableSpaceToActivate { get; set; }

public override string ToString() => JsonSerializer.Serialize(this);
public override string ToString() => JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PeekProperties);
}
}
2 changes: 1 addition & 1 deletion src/settings-ui/Settings.UI.Library/PowerOcrProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public PowerOcrProperties()
public string PreferredLanguage { get; set; }

public override string ToString()
=> JsonSerializer.Serialize(this);
=> JsonSerializer.Serialize(this, SettingsSerializationContext.Default.PowerOcrProperties);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ public PowerPreviewProperties()

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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public int MaxMRUSize

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.
Expand Down
Loading
Loading