Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User/shalinijoshi19/1.2.4 #3561

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion custom.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<VersionMajor>1</VersionMajor>
<VersionMinor>2</VersionMinor>
<!-- The nuget package version should be incremented when we produce QFEs -->
<NuGetPackVersion>1.2.3</NuGetPackVersion>
<NuGetPackVersion>1.2.4</NuGetPackVersion>
<VersionInfoProductName>AdaptiveCards</VersionInfoProductName>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -60,83 +60,87 @@ public static FrameworkElement Render(AdaptiveColumnSet columnSet, AdaptiveRende

FrameworkElement uiContainer = context.Render(column);

TagContent tag = null;

// Add vertical Separator
if (uiColumnSet.ColumnDefinitions.Count > 0 && (column.Separator || column.Spacing != AdaptiveSpacing.None))
// If the column couldn't be rendered and the fallback is 'drop'
if (uiContainer != null)
{
var uiSep = new Grid();
uiSep.Style = context.GetStyle($"Adaptive.VerticalSeparator");
TagContent tag = null;

uiSep.VerticalAlignment = VerticalAlignment.Stretch;
// Add vertical Separator
if (uiColumnSet.ColumnDefinitions.Count > 0 && (column.Separator || column.Spacing != AdaptiveSpacing.None))
{
var uiSep = new Grid();
uiSep.Style = context.GetStyle($"Adaptive.VerticalSeparator");

int spacing = context.Config.GetSpacing(column.Spacing);
uiSep.Margin = new Thickness(spacing / 2.0, 0, spacing / 2.0, 0);
uiSep.VerticalAlignment = VerticalAlignment.Stretch;

uiSep.Width = context.Config.Separator.LineThickness;
if (column.Separator && context.Config.Separator.LineColor != null)
{
uiSep.Background = context.GetColorBrush(context.Config.Separator.LineColor);
}
int spacing = context.Config.GetSpacing(column.Spacing);
uiSep.Margin = new Thickness(spacing / 2.0, 0, spacing / 2.0, 0);

tag = new TagContent(uiSep, uiColumnSet);
uiSep.Width = context.Config.Separator.LineThickness;
if (column.Separator && context.Config.Separator.LineColor != null)
{
uiSep.Background = context.GetColorBrush(context.Config.Separator.LineColor);
}

uiColumnSet.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
Grid.SetColumn(uiSep, uiColumnSet.ColumnDefinitions.Count - 1);
uiColumnSet.Children.Add(uiSep);
}
else
{
tag = new TagContent(null, uiColumnSet);
}
tag = new TagContent(uiSep, uiColumnSet);

uiColumnSet.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
Grid.SetColumn(uiSep, uiColumnSet.ColumnDefinitions.Count - 1);
uiColumnSet.Children.Add(uiSep);
}
else
{
tag = new TagContent(null, uiColumnSet);
}

// do some sizing magic using the magic GridUnitType.Star
var width = column.Width?.ToLower();
if (string.IsNullOrEmpty(width))
// do some sizing magic using the magic GridUnitType.Star
var width = column.Width?.ToLower();
if (string.IsNullOrEmpty(width))
#pragma warning disable CS0618 // Type or member is obsolete
width = column.Size?.ToLower();
width = column.Size?.ToLower();
#pragma warning restore CS0618 // Type or member is obsolete

ColumnDefinition columnDefinition = null;
ColumnDefinition columnDefinition = null;

if (width == null || width == AdaptiveColumnWidth.Stretch.ToLower())
{
columnDefinition = new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) };
}
else if (width == AdaptiveColumnWidth.Auto.ToLower())
{
columnDefinition = new ColumnDefinition() { Width = GridLength.Auto };
}
else
{
if (double.TryParse(width, out double val) && val >= 0)
if (width == null || width == AdaptiveColumnWidth.Stretch.ToLower())
{
// Weighted proportion (number only)
columnDefinition = new ColumnDefinition() { Width = new GridLength(val, GridUnitType.Star) };
columnDefinition = new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) };
}
else if (width.EndsWith("px") && double.TryParse(width.Substring(0, width.Length - 2), out double pxVal) && pxVal >= 0)
else if (width == AdaptiveColumnWidth.Auto.ToLower())
{
// Exact pixel (number followed by "px")
columnDefinition = new ColumnDefinition() { Width = new GridLength((int)pxVal, GridUnitType.Pixel) };
columnDefinition = new ColumnDefinition() { Width = GridLength.Auto };
}
else
{
columnDefinition = new ColumnDefinition() { Width = GridLength.Auto };
if (double.TryParse(width, out double val) && val >= 0)
{
// Weighted proportion (number only)
columnDefinition = new ColumnDefinition() { Width = new GridLength(val, GridUnitType.Star) };
}
else if (width.EndsWith("px") && double.TryParse(width.Substring(0, width.Length - 2), out double pxVal) && pxVal >= 0)
{
// Exact pixel (number followed by "px")
columnDefinition = new ColumnDefinition() { Width = new GridLength((int)pxVal, GridUnitType.Pixel) };
}
else
{
columnDefinition = new ColumnDefinition() { Width = GridLength.Auto };
}
}
}

// Store the column definition in the tag so we can toggle the visibility later
tag.ColumnDefinition = columnDefinition;
tag.ViewIndex = uiColumnSet.ColumnDefinitions.Count;
// Store the column definition in the tag so we can toggle the visibility later
tag.ColumnDefinition = columnDefinition;
tag.ViewIndex = uiColumnSet.ColumnDefinitions.Count;

uiColumnSet.ColumnDefinitions.Add(columnDefinition);
uiColumnSet.ColumnDefinitions.Add(columnDefinition);

uiContainer.Tag = tag;

Grid.SetColumn(uiContainer, uiColumnSet.ColumnDefinitions.Count - 1);
uiColumnSet.Children.Add(uiContainer);
uiContainer.Tag = tag;

context.SetVisibility(uiContainer, column.IsVisible, tag);
Grid.SetColumn(uiContainer, uiColumnSet.ColumnDefinitions.Count - 1);
uiColumnSet.Children.Add(uiContainer);

context.SetVisibility(uiContainer, column.IsVisible, tag);
}
}

context.ResetSeparatorVisibilityInsideContainer(uiColumnSet);
Expand Down
2 changes: 1 addition & 1 deletion source/dotnet/Library/AdaptiveCards/AdaptiveCard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public static AdaptiveCardParseResult FromJson(string json)
{
parseResult.Card = JsonConvert.DeserializeObject<AdaptiveCard>(json, new JsonSerializerSettings
{
ContractResolver = new WarningLoggingContractResolver(parseResult),
ContractResolver = new WarningLoggingContractResolver(parseResult, new ParseContext()),
Converters = { new StrictIntConverter() }
});
}
Expand Down
13 changes: 9 additions & 4 deletions source/dotnet/Library/AdaptiveCards/AdaptiveCardConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace AdaptiveCards
{
public class AdaptiveCardConverter : JsonConverter, ILogWarnings
public class AdaptiveCardConverter : AdaptiveTypedBaseElementConverter, ILogWarnings
{
public List<AdaptiveWarning> Warnings { get; set; } = new List<AdaptiveWarning>();

Expand Down Expand Up @@ -62,16 +62,21 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist

if (reader.Depth == 0)
{
// Needed for ID collision detection after fallback was introduced
ParseContext.Initialize();

ValidateJsonVersion(ref jObject);

if (new AdaptiveSchemaVersion(jObject.Value<string>("version")) > AdaptiveCard.KnownSchemaVersion)
{
return MakeFallbackTextCard(jObject);
}
}

/// this is needed when client calls JsonConvert.Deserializer method, we need this contract resolver,
/// so we can pass ParseContext
if (!(serializer.ContractResolver is WarningLoggingContractResolver))
{
serializer.ContractResolver = new WarningLoggingContractResolver(new AdaptiveCardParseResult(), new ParseContext());
}

var typedElementConverter = serializer.ContractResolver.ResolveContract(typeof(AdaptiveTypedElement)).Converter;

var card = (AdaptiveCard)typedElementConverter.ReadJson(jObject.CreateReader(), objectType, existingValue, serializer);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;

namespace AdaptiveCards
{
public class AdaptiveFallbackConverter : JsonConverter, ILogWarnings
public class AdaptiveFallbackConverter : AdaptiveTypedBaseElementConverter, ILogWarnings
{
public List<AdaptiveWarning> Warnings { get; set; } = new List<AdaptiveWarning>();

Expand Down Expand Up @@ -103,7 +105,7 @@ public override bool CanConvert(Type objectType)
return result;
}

public static AdaptiveFallbackElement ParseFallback(JToken fallbackJSON, JsonSerializer serializer, string objectId, AdaptiveInternalID internalId)
public AdaptiveFallbackElement ParseFallback(JToken fallbackJSON, JsonSerializer serializer, string objectId, AdaptiveInternalID internalId)
{
// Handle fallback as a string ("drop")
if (fallbackJSON.Type == JTokenType.String)
Expand Down
1 change: 1 addition & 0 deletions source/dotnet/Library/AdaptiveCards/AdaptiveImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public AdaptiveImage(Uri url)
#if !NETSTANDARD1_3
[XmlIgnore]
#endif
[JsonProperty(Required = Required.Default)]
public override string Type { get; set; } = TypeName;

/// <summary>
Expand Down
14 changes: 12 additions & 2 deletions source/dotnet/Library/AdaptiveCards/AdaptiveInlinesConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace AdaptiveCards
{
class AdaptiveInlinesConverter : JsonConverter
class AdaptiveInlinesConverter : AdaptiveTypedBaseElementConverter
{
public override bool CanRead => true;

Expand All @@ -24,6 +24,11 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
var array = JArray.Load(reader);
List<object> list = array.ToObject<List<object>>();
List<AdaptiveInline> arrayList = new List<AdaptiveInline>();
var serializerSettigns = new JsonSerializerSettings
{
ContractResolver = new WarningLoggingContractResolver(new AdaptiveCardParseResult(), ParseContext),
Converters = { new StrictIntConverter() }
};

// We only support text runs for now, which can be specified as either a string or an object
foreach (object obj in list)
Expand All @@ -35,7 +40,12 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
else
{
JObject jobj = (JObject)obj;
arrayList.Add((AdaptiveInline)jobj.ToObject(typeof(AdaptiveTextRun)));
if (jobj.Value<string>("type") != AdaptiveTextRun.TypeName)
{
throw new AdaptiveSerializationException($"Property 'type' must be '{AdaptiveTextRun.TypeName}'");
}

arrayList.Add(JsonConvert.DeserializeObject<AdaptiveTextRun>(jobj.ToString(), serializerSettigns));
}
}
return arrayList;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Newtonsoft.Json;

namespace AdaptiveCards
{
/// <summary>
/// JsonConverters that deserialize to Adpative Elements and require
/// ParseContext must inherit this Class
/// ParseContext provides id generation, id collision detections, and other useful
/// services during deserialization
/// </summary>
public abstract class AdaptiveTypedBaseElementConverter : JsonConverter
{
public ParseContext ParseContext { get; set; } = new ParseContext();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public abstract class AdaptiveTypedElement
public AdaptiveFallbackElement Fallback { get; set; }

[JsonIgnore]
public AdaptiveInternalID InternalID { get; }
public AdaptiveInternalID InternalID { get; set; }

/// <summary>
/// A unique ID associated with the element. For Inputs the ID will be used as the key for Action.Submit response
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace AdaptiveCards
/// <summary>
/// This handles using type field to instantiate strongly typed object on deserialization
/// </summary>
public class AdaptiveTypedElementConverter : JsonConverter, ILogWarnings
public class AdaptiveTypedElementConverter : AdaptiveTypedBaseElementConverter, ILogWarnings
{
public List<AdaptiveWarning> Warnings { get; set; } = new List<AdaptiveWarning>();

Expand Down Expand Up @@ -98,6 +98,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
try
{
serializer.Populate(jObject.CreateReader(), result);
result.InternalID = internalID;
}
catch (JsonSerializationException) { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace AdaptiveCards
{
public class IgnoreEmptyItemsConverter<T> : JsonConverter
public class IgnoreEmptyItemsConverter<T> : AdaptiveTypedBaseElementConverter
{
public override bool CanConvert(Type objectType)
{
Expand Down
22 changes: 9 additions & 13 deletions source/dotnet/Library/AdaptiveCards/ParseContext.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;

namespace AdaptiveCards
{
static class ParseContext
public class ParseContext
{
public static void Initialize()
{
elementIds = new Dictionary<string, List<AdaptiveInternalID>>();
idStack = new Stack<Tuple<string, AdaptiveInternalID, bool>>();
}

public enum ContextType { Element, Action };

public static ContextType Type { get; set; }
public ContextType Type { get; set; }

private static IDictionary<string, List<AdaptiveInternalID>> elementIds = new Dictionary<string, List<AdaptiveInternalID>>();
private IDictionary<string, List<AdaptiveInternalID>> elementIds = new Dictionary<string, List<AdaptiveInternalID>>();

private static Stack<Tuple<string, AdaptiveInternalID, bool>> idStack = new Stack<Tuple<string, AdaptiveInternalID, bool>>();
private Stack<Tuple<string, AdaptiveInternalID, bool>> idStack = new Stack<Tuple<string, AdaptiveInternalID, bool>>();

// Push the provided state on to our ID stack
public static void PushElement(string idJsonProperty, AdaptiveInternalID internalId)
public void PushElement(string idJsonProperty, AdaptiveInternalID internalId)
{
if (internalId.Equals(AdaptiveInternalID.Invalid))
{
Expand All @@ -32,7 +28,7 @@ public static void PushElement(string idJsonProperty, AdaptiveInternalID interna
}

// Pop the last id off our stack and perform validation
public static void PopElement()
public void PopElement()
{
// about to pop an element off the stack. perform collision list maintenance and detection.
var idsToPop = idStack.Peek();
Expand Down Expand Up @@ -111,7 +107,7 @@ public static void PopElement()

// Walk stack looking for first element to be marked fallback (which isn't the ID we're supposed to skip), then
// return its internal ID. If none, return an invalid ID. (see comment above)
public static AdaptiveInternalID GetNearestFallbackID(AdaptiveInternalID skipID)
public AdaptiveInternalID GetNearestFallbackID(AdaptiveInternalID skipID)
{
foreach (var curElement in idStack)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ public class AdaptiveHostConfig : AdaptiveConfigBase
public FactSetConfig FactSet { get; set; } = new FactSetConfig();

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
[Obsolete("AdaptiveHostConfig.FontFamily has been deprecated. Use AdaptiveHostConfig.FontStyles.Default.FontFamily", false)]
[Obsolete("AdaptiveHostConfig.FontFamily has been deprecated. Use AdaptiveHostConfig.FontTypes.Default.FontFamily", false)]
public string FontFamily { get; set; }

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
[Obsolete("AdaptiveHostConfig.FontSizes has been deprecated. Use AdaptiveHostConfig.FontStyles.Default.FontSizes", false)]
[Obsolete("AdaptiveHostConfig.FontSizes has been deprecated. Use AdaptiveHostConfig.FontTypes.Default.FontSizes", false)]
public FontSizesConfig FontSizes { get; set; } = new FontSizesConfig();

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
[Obsolete("AdaptiveHostConfig.FontWeights has been deprecated. Use AdaptiveHostConfig.FontStyles.Default.FontWeights", false)]
[Obsolete("AdaptiveHostConfig.FontWeights has been deprecated. Use AdaptiveHostConfig.FontTypes.Default.FontWeights", false)]
public FontWeightsConfig FontWeights { get; set; } = new FontWeightsConfig();

[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
Expand Down
Loading