Skip to content

Commit 63fa2e6

Browse files
committed
Add interface for [NotificationXmlAttribute]
1 parent 35dacb4 commit 63fa2e6

20 files changed

+416
-24
lines changed

Microsoft.Toolkit.Uwp.Notifications/Adaptive/Elements/Element_AdaptiveImage.cs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Collections.Generic;
6+
57
namespace Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements
68
{
7-
internal sealed class Element_AdaptiveImage : IElement_TileBindingChild, IElement_ToastBindingChild, IElement_AdaptiveSubgroupChild, IHaveXmlName
9+
internal sealed class Element_AdaptiveImage : IElement_TileBindingChild, IElement_ToastBindingChild, IElement_AdaptiveSubgroupChild, IHaveXmlName, IHaveXmlNamedProperties
810
{
911
internal const AdaptiveImagePlacement DEFAULT_PLACEMENT = AdaptiveImagePlacement.Inline;
1012
internal const AdaptiveImageCrop DEFAULT_CROP = AdaptiveImageCrop.Default;
@@ -69,5 +71,36 @@ public int? Overlay
6971

7072
/// <inheritdoc/>
7173
string IHaveXmlName.Name => "image";
74+
75+
/// <inheritdoc/>
76+
IEnumerable<KeyValuePair<string, object>> IHaveXmlNamedProperties.EnumerateNamedProperties()
77+
{
78+
yield return new("id", Id);
79+
yield return new("src", Src);
80+
yield return new("alt", Alt);
81+
yield return new("addImageQuery", AddImageQuery);
82+
83+
if (Placement != DEFAULT_PLACEMENT)
84+
{
85+
yield return new("placement", Placement.ToPascalCaseString());
86+
}
87+
88+
if (Align != DEFAULT_ALIGN)
89+
{
90+
yield return new("hint-align", Align.ToPascalCaseString());
91+
}
92+
93+
if (Crop != DEFAULT_CROP)
94+
{
95+
yield return new("hint-crop", Crop.ToPascalCaseString());
96+
}
97+
98+
yield return new("hint-removeMargin", RemoveMargin);
99+
yield return new("hint-overlay", Overlay);
100+
yield return new("spritesheet-src", SpriteSheetSrc);
101+
yield return new("spritesheet-height", SpriteSheetHeight);
102+
yield return new("spritesheet-fps", SpriteSheetFps);
103+
yield return new("spritesheet-startingFrame", SpriteSheetStartingFrame);
104+
}
72105
}
73106
}

Microsoft.Toolkit.Uwp.Notifications/Adaptive/Elements/Element_AdaptiveProgressBar.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System.Collections.Generic;
6+
57
namespace Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements
68
{
7-
internal sealed class Element_AdaptiveProgressBar : IElement_ToastBindingChild, IHaveXmlName
9+
internal sealed class Element_AdaptiveProgressBar : IElement_ToastBindingChild, IHaveXmlName, IHaveXmlNamedProperties
810
{
911
[NotificationXmlAttribute("value")]
1012
public string Value { get; set; }
@@ -20,5 +22,14 @@ internal sealed class Element_AdaptiveProgressBar : IElement_ToastBindingChild,
2022

2123
/// <inheritdoc/>
2224
string IHaveXmlName.Name => "progress";
25+
26+
/// <inheritdoc/>
27+
IEnumerable<KeyValuePair<string, object>> IHaveXmlNamedProperties.EnumerateNamedProperties()
28+
{
29+
yield return new("value", Value);
30+
yield return new("title", Title);
31+
yield return new("valueStringOverride", ValueStringOverride);
32+
yield return new("status", Status);
33+
}
2334
}
2435
}

Microsoft.Toolkit.Uwp.Notifications/Adaptive/Elements/Element_AdaptiveSubgroup.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements
99
{
10-
internal sealed class Element_AdaptiveSubgroup : IElementWithDescendants, IHaveXmlName
10+
internal sealed class Element_AdaptiveSubgroup : IElementWithDescendants, IHaveXmlName, IHaveXmlNamedProperties
1111
{
1212
internal const AdaptiveSubgroupTextStacking DEFAULT_TEXT_STACKING = AdaptiveSubgroupTextStacking.Default;
1313

@@ -53,6 +53,17 @@ public IEnumerable<object> Descendants()
5353

5454
/// <inheritdoc/>
5555
string IHaveXmlName.Name => "subgroup";
56+
57+
/// <inheritdoc/>
58+
IEnumerable<KeyValuePair<string, object>> IHaveXmlNamedProperties.EnumerateNamedProperties()
59+
{
60+
if (TextStacking != DEFAULT_TEXT_STACKING)
61+
{
62+
yield return new("hint-textStacking", TextStacking.ToPascalCaseString());
63+
}
64+
65+
yield return new("hint-weight", Weight);
66+
}
5667
}
5768

5869
internal interface IElement_AdaptiveSubgroupChild

Microsoft.Toolkit.Uwp.Notifications/Adaptive/Elements/Element_AdaptiveText.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6+
using System.Collections.Generic;
67

78
namespace Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements
89
{
9-
internal sealed class Element_AdaptiveText : IElement_TileBindingChild, IElement_AdaptiveSubgroupChild, IElement_ToastBindingChild, IHaveXmlName
10+
internal sealed class Element_AdaptiveText : IElement_TileBindingChild, IElement_AdaptiveSubgroupChild, IElement_ToastBindingChild, IHaveXmlName, IHaveXmlNamedProperties
1011
{
1112
internal const AdaptiveTextStyle DEFAULT_STYLE = AdaptiveTextStyle.Default;
1213
internal const AdaptiveTextAlign DEFAULT_ALIGN = AdaptiveTextAlign.Default;
@@ -93,5 +94,32 @@ internal static void CheckMinLinesValue(int value)
9394

9495
/// <inheritdoc/>
9596
string IHaveXmlName.Name => "text";
97+
98+
/// <inheritdoc/>
99+
IEnumerable<KeyValuePair<string, object>> IHaveXmlNamedProperties.EnumerateNamedProperties()
100+
{
101+
yield return new("id", Id);
102+
yield return new("lang", Lang);
103+
104+
if (Align != DEFAULT_ALIGN)
105+
{
106+
yield return new("hint-align", Align.ToPascalCaseString());
107+
}
108+
109+
yield return new("hint-maxLines", MaxLines);
110+
yield return new("hint-minLines", MinLines);
111+
112+
if (Style != DEFAULT_STYLE)
113+
{
114+
yield return new("hint-style", Style.ToPascalCaseString());
115+
}
116+
117+
yield return new("hint-wrap", Wrap);
118+
119+
if (Placement != DEFAULT_PLACEMENT)
120+
{
121+
yield return new("placement", Placement.ToPascalCaseString());
122+
}
123+
}
96124
}
97125
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
7+
#nullable enable
8+
9+
namespace Microsoft.Toolkit.Uwp.Notifications;
10+
11+
/// <summary>
12+
/// A helper class that can be used to format <see cref="Enum"/> values.
13+
/// </summary>
14+
internal static class EnumFormatter
15+
{
16+
/// <summary>
17+
/// Returns a <see cref="string"/> representation of an enum value with pascal casing.
18+
/// </summary>
19+
/// <typeparam name="T">The <see cref="Enum"/> type to format.</typeparam>
20+
/// <param name="value">The <typeparamref name="T"/> value to format.</param>
21+
/// <returns>The pascal case <see cref="string"/> representation of <paramref name="value"/>.</returns>
22+
public static string? ToPascalCaseString<T>(this T? value)
23+
where T : unmanaged, Enum
24+
{
25+
if (value is null)
26+
{
27+
return null;
28+
}
29+
30+
return ToPascalCaseString(value.Value);
31+
}
32+
33+
/// <summary>
34+
/// Returns a <see cref="string"/> representation of an enum value with pascal casing.
35+
/// </summary>
36+
/// <typeparam name="T">The <see cref="Enum"/> type to format.</typeparam>
37+
/// <param name="value">The <typeparamref name="T"/> value to format.</param>
38+
/// <returns>The pascal case <see cref="string"/> representation of <paramref name="value"/>.</returns>
39+
public static string? ToPascalCaseString<T>(this T value)
40+
where T : unmanaged, Enum
41+
{
42+
string? text = value.ToString();
43+
44+
if (text is null or { Length: 0 })
45+
{
46+
return text;
47+
}
48+
49+
if (text is { Length: 1 })
50+
{
51+
return text.ToLowerInvariant();
52+
}
53+
54+
return $"{char.ToLowerInvariant(text[0])}{text.Substring(1)}";
55+
}
56+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Collections.Generic;
6+
7+
#nullable enable
8+
9+
namespace Microsoft.Toolkit.Uwp.Notifications;
10+
11+
/// <summary>
12+
/// An interface for a notification XML element with named properties.
13+
/// </summary>
14+
internal interface IHaveXmlNamedProperties
15+
{
16+
/// <summary>
17+
/// Enumerates the available named properties for the element.
18+
/// </summary>
19+
/// <returns>A sequence of named properties for the element.</returns>
20+
/// <remarks>The returned values must be valid XML values when <see cref="object.ToString"/> is called on them.</remarks>
21+
IEnumerable<KeyValuePair<string, object?>> EnumerateNamedProperties();
22+
}

Microsoft.Toolkit.Uwp.Notifications/Common/XmlWriterHelper.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,7 @@ public static void Write(System.Xml.XmlWriter writer, object element)
5555
// If it's an attribute
5656
else if (attr != null)
5757
{
58-
object defaultValue = attr.DefaultValue;
59-
60-
// If the value is not the default value (and it's not null) we'll write it
61-
if (!object.Equals(propertyValue, defaultValue) && propertyValue != null)
62-
{
63-
writer.WriteAttributeString(attr.Name, PropertyValueToString(propertyValue));
64-
}
58+
continue;
6559
}
6660

6761
// If it's a content attribute
@@ -80,6 +74,14 @@ public static void Write(System.Xml.XmlWriter writer, object element)
8074
}
8175
}
8276

77+
foreach (var property in (element as IHaveXmlNamedProperties)?.EnumerateNamedProperties() ?? Enumerable.Empty<KeyValuePair<string, object>>())
78+
{
79+
if (property.Value is not null)
80+
{
81+
writer.WriteAttributeString(property.Key, PropertyValueToString(property.Value));
82+
}
83+
}
84+
8385
// Then write children
8486
foreach (object el in elements)
8587
{

Microsoft.Toolkit.Uwp.Notifications/Tiles/Elements/Element_TileBinding.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Microsoft.Toolkit.Uwp.Notifications
99
{
10-
internal sealed class Element_TileBinding : IElementWithDescendants, IHaveXmlName
10+
internal sealed class Element_TileBinding : IElementWithDescendants, IHaveXmlName, IHaveXmlNamedProperties
1111
{
1212
internal const TileBranding DEFAULT_BRANDING = TileBranding.Auto;
1313
internal const TileTextStacking DEFAULT_TEXT_STACKING = TileTextStacking.Top;
@@ -121,6 +121,33 @@ public IEnumerable<object> Descendants()
121121

122122
/// <inheritdoc/>
123123
string IHaveXmlName.Name => "binding";
124+
125+
/// <inheritdoc/>
126+
IEnumerable<KeyValuePair<string, object>> IHaveXmlNamedProperties.EnumerateNamedProperties()
127+
{
128+
yield return new("template", Template);
129+
yield return new("addImageQuery", AddImageQuery);
130+
yield return new("baseUri", BaseUri);
131+
132+
if (Branding != DEFAULT_BRANDING)
133+
{
134+
yield return new("branding", Branding);
135+
}
136+
137+
yield return new("contentId", ContentId);
138+
yield return new("displayName", DisplayName);
139+
yield return new("lang", Language);
140+
yield return new("hint-lockDetailedStatus1", LockDetailedStatus1);
141+
yield return new("hint-lockDetailedStatus2", LockDetailedStatus2);
142+
yield return new("hint-lockDetailedStatus3", LockDetailedStatus3);
143+
yield return new("arguments", Arguments);
144+
yield return new("hint-presentation", Presentation.ToPascalCaseString());
145+
146+
if (TextStacking != DEFAULT_TEXT_STACKING)
147+
{
148+
yield return new("hint-textStacking", TextStacking.ToPascalCaseString());
149+
}
150+
}
124151
}
125152

126153
internal interface IElement_TileBindingChild

Microsoft.Toolkit.Uwp.Notifications/Tiles/Elements/Element_TileVisual.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Microsoft.Toolkit.Uwp.Notifications
99
{
10-
internal sealed class Element_TileVisual : IHaveXmlName
10+
internal sealed class Element_TileVisual : IHaveXmlName, IHaveXmlNamedProperties
1111
{
1212
internal const TileBranding DEFAULT_BRANDING = TileBranding.Auto;
1313
internal const bool DEFAULT_ADD_IMAGE_QUERY = false;
@@ -37,5 +37,22 @@ internal sealed class Element_TileVisual : IHaveXmlName
3737

3838
/// <inheritdoc/>
3939
string IHaveXmlName.Name => "visual";
40+
41+
/// <inheritdoc/>
42+
IEnumerable<KeyValuePair<string, object>> IHaveXmlNamedProperties.EnumerateNamedProperties()
43+
{
44+
yield return new("addImageQuery", AddImageQuery);
45+
yield return new("baseUri", BaseUri);
46+
47+
if (Branding != DEFAULT_BRANDING)
48+
{
49+
yield return new("branding", Branding.ToPascalCaseString());
50+
}
51+
52+
yield return new("contentId", ContentId);
53+
yield return new("displayName", DisplayName);
54+
yield return new("lang", Language);
55+
yield return new("arguments", Arguments);
56+
}
4057
}
4158
}

Microsoft.Toolkit.Uwp.Notifications/Toasts/Elements/Element_Toast.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Microsoft.Toolkit.Uwp.Notifications
99
{
10-
internal sealed class Element_Toast : BaseElement, IElement_ToastActivatable, IElement_AdditionalProperties, IHaveXmlName
10+
internal sealed class Element_Toast : BaseElement, IElement_ToastActivatable, IElement_AdditionalProperties, IHaveXmlName, IHaveXmlNamedProperties
1111
{
1212
internal const ToastScenario DEFAULT_SCENARIO = ToastScenario.Default;
1313
internal const Element_ToastActivationType DEFAULT_ACTIVATION_TYPE = Element_ToastActivationType.Foreground;
@@ -84,6 +84,38 @@ public static Element_ToastActivationType ConvertActivationType(ToastActivationT
8484

8585
/// <inheritdoc/>
8686
string IHaveXmlName.Name => "toast";
87+
88+
/// <inheritdoc/>
89+
IEnumerable<KeyValuePair<string, object>> IHaveXmlNamedProperties.EnumerateNamedProperties()
90+
{
91+
if (ActivationType != DEFAULT_ACTIVATION_TYPE)
92+
{
93+
yield return new("activationType", ActivationType.ToPascalCaseString());
94+
}
95+
96+
yield return new("protocolActivationTargetApplicationPfn", ProtocolActivationTargetApplicationPfn);
97+
98+
if (AfterActivationBehavior != ToastAfterActivationBehavior.Default)
99+
{
100+
yield return new("afterActivationBehavior", AfterActivationBehavior.ToPascalCaseString());
101+
}
102+
103+
if (Duration != DEFAULT_DURATION)
104+
{
105+
yield return new("duration", Duration.ToPascalCaseString());
106+
}
107+
108+
yield return new("launch", Launch);
109+
110+
if (Scenario != DEFAULT_SCENARIO)
111+
{
112+
yield return new("scenario", Scenario.ToPascalCaseString());
113+
}
114+
115+
yield return new("displayTimestamp", DisplayTimestamp);
116+
yield return new("hint-toastId", HintToastId);
117+
yield return new("hint-people", HintPeople);
118+
}
87119
}
88120

89121
/// <summary>

0 commit comments

Comments
 (0)