MudBlazor / ThemeManager

ThemeManager built to showcase MudBlazor theming.
MIT License
209 stars 60 forks source link

Save theme #3

Open IngoManthey opened 3 years ago

IngoManthey commented 3 years ago

When I have created a theme with the ThemeManager, how can I save it to? add it as a MudTheme in my project?

best regards Ingo

Garderoben commented 3 years ago

Currently not possible, but its a feature i plan to add, but i am prioritizing the main library atm.

TheR00st3r commented 2 years ago

It would be nice if the Theme could be JSON Serializeable. At the moment I get following Exception for 'MudBlazor.Utilities.MudColor'

 Unhandled exception rendering component: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'MudBlazor.Utilities.MudColor'. Path: $.Theme.Palette.Black | LineNumber: 0 | BytePositionInLine: 30.
System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'MudBlazor.Utilities.MudColor'. Path: $.Theme.Palette.Black | LineNumber: 0 | BytePositionInLine: 30.
 ---> System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'MudBlazor.Utilities.MudColor'.
   --- End of inner exception stack trace ---
Logi-Fy-Pravin commented 2 years ago

It would be nice if the Theme could be JSON Serializeable. At the moment I get following Exception for 'MudBlazor.Utilities.MudColor'

 Unhandled exception rendering component: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'MudBlazor.Utilities.MudColor'. Path: $.Theme.Palette.Black | LineNumber: 0 | BytePositionInLine: 30.
System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'MudBlazor.Utilities.MudColor'. Path: $.Theme.Palette.Black | LineNumber: 0 | BytePositionInLine: 30.
 ---> System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'MudBlazor.Utilities.MudColor'.
   --- End of inner exception stack trace ---

You can use Newtonsoft.Json to deserialize the same as I was also getting same error while deserializing with System.Text.Json

echannelsolutions commented 1 year ago

With Newtonsoft we are able serialize the ThemeManagerTheme object but not with System.Text.JSON. So for this particular case we used Newtonsoft to save the object,

` ThemesPropertyEntity themeProperties = new ThemesPropertyEntity();
themeProperties.PropertyValue = Newtonsoft.Json.JsonConvert.SerializeObject(value);
themeProperties.PropertyID = uThemesProperty.PropertyID;
themeProperties.PropertyName = uThemesProperty.PropertyName;
themeProperties.PropertyType = value.GetType().ToString();
themeProperties.ThemeID = id;
 await themepropertyservice.AddThemesProperty(themeProperties);
  _themeManager = value;
   await InvokeAsync(StateHasChanged);`
PhilippRoessner commented 11 months ago

I'd like to add the request to also load a deserialized json into the mudblazor ThemeProvider. I couldn't figure out any way to accomplish that

ScarletKuro commented 11 months ago

I'd like to add the request to also load a deserialized json into the mudblazor ThemeProvider. I couldn't figure out any way to accomplish that

Theoretically you can write custom JsonConverter and it should work. For example a custom MudColor converter for System.Text.Json that is working.

public class MudColorSerializer : JsonConverter<MudColor>
{
    public override MudColor Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartObject)
        {
            throw new JsonException("Expected StartObject token");
        }

        byte R = 0, G = 0, B = 0, A = 0;

        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndObject)
            {
                return new MudColor(R, G, B, A);
            }
            if (reader.TokenType != JsonTokenType.PropertyName)
            {
                throw new JsonException("Expected PropertyName token");
            }

            string propName = reader.GetString();
            reader.Read();

            switch (propName)
            {
                case "r": R = reader.GetByte(); break;
                case "g": G = reader.GetByte(); break;
                case "b": B = reader.GetByte(); break;
                case "a": A = reader.GetByte(); break;
            }
        }

        throw new JsonException("Expected EndObject token");
    }

    public override void Write(Utf8JsonWriter writer, MudColor value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WriteNumber("r", value.R);
        writer.WriteNumber("g", value.G);
        writer.WriteNumber("b", value.B);
        writer.WriteNumber("a", value.A);
        writer.WriteEndObject();
    }
}

You just need to add it to the JsonSerializerOptions.Converters

PhilippRoessner commented 11 months ago

I'd like to add the request to also load a deserialized json into the mudblazor ThemeProvider. I couldn't figure out any way to accomplish that

Theoretically you can write custom JsonConverter and it should work. For example a custom MudColor converter for System.Text.Json that is working.

public class MudColorSerializer : JsonConverter<MudColor>
{
    public override MudColor Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartObject)
        {
            throw new JsonException("Expected StartObject token");
        }

        byte R = 0, G = 0, B = 0, A = 0;

        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndObject)
            {
                return new MudColor(R, G, B, A);
            }
            if (reader.TokenType != JsonTokenType.PropertyName)
            {
                throw new JsonException("Expected PropertyName token");
            }

            string propName = reader.GetString();
            reader.Read();

            switch (propName)
            {
                case "r": R = reader.GetByte(); break;
                case "g": G = reader.GetByte(); break;
                case "b": B = reader.GetByte(); break;
                case "a": A = reader.GetByte(); break;
            }
        }

        throw new JsonException("Expected EndObject token");
    }

    public override void Write(Utf8JsonWriter writer, MudColor value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WriteNumber("r", value.R);
        writer.WriteNumber("g", value.G);
        writer.WriteNumber("b", value.B);
        writer.WriteNumber("a", value.A);
        writer.WriteEndObject();
    }
}

You just need to add it to the JsonSerializerOptions.Converters

Thanks! It works perfectly. I had to change this:

string propName = reader.GetString();

because my json exported with capital letters

string propName = reader.GetString().ToLower();

For Anyone who needs a copy/paste of using this:

  string jsonString = "{ \"Palette\": {      \"PrimaryDarken\": \"rgb(62,44,221)\", \"Black\":  { \"Value\": \"#ffffffff\", \"R\": 255, \"G\": 255, \"B\": 255, \"A\": 255, \"APercentage\": 1, \"H\": 0, \"L\": 1, \"S\": 0 } , \"White\": { \"Value\": \"#ffffffff\", \"R\": 255, \"G\": 255, \"B\": 255, \"A\": 255, \"APercentage\": 1, \"H\": 0, \"L\": 1, \"S\": 0 } } }";
  var options = new JsonSerializerOptions();
  options.WriteIndented = true;
  options.Converters.Add(new MudColorSerializer());
  var theme = JsonSerializer.Deserialize<MudTheme>(jsonString, options)!;
vanthomiy commented 2 months ago

Is opening and saving a theme is now supported from the theme manager itself? There is the option to load a preset but it's saying "Not Implemented". Is it planned to work soon?

ScarletKuro commented 2 months ago

By the way, the MudColorSerializer should no longer be necessary if you are using MudBlazor v7. In MudBlazor v7, I have implemented native support for System.Text.Json and Newtonsoft. You can find more information at https://github.com/MudBlazor/MudBlazor/pull/8579.

Is opening and saving a theme is now supported from the theme manager itself? There is the option to load a preset but it's saying "Not Implemented". Is it planned to work soon?

There are no current plans for this. This repository has a very low priority and is in maintenance mode, with only myself handling it when it breaks with new versions of MudBlazor. However, you can submit a pull request with this feature, and I would gladly review and accept it.