Skip to content

Commit f9045de

Browse files
committed
Simplified generic toast arguments
1 parent f1a3f02 commit f9045de

File tree

13 files changed

+546
-149
lines changed

13 files changed

+546
-149
lines changed

Microsoft.Toolkit.Uwp.Notifications/Toasts/Builder/ToastContentBuilder.Actions.cs

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,30 @@ private IList<IToastInput> InputList
6060
#endif
6161
public ToastContentBuilder AddButton(string content, ToastActivationType activationType, ToastArguments arguments)
6262
{
63-
return AddButton(content, activationType, arguments.ToString());
63+
AddButton(content, activationType, SerializeArgumentsIncludingGeneric(arguments));
64+
65+
// Remove this button from the custom arguments list
66+
_buttonsUsingCustomArguments.RemoveAt(_buttonsUsingCustomArguments.Count - 1);
67+
68+
return this;
69+
}
70+
71+
private string SerializeArgumentsIncludingGeneric(ToastArguments arguments)
72+
{
73+
if (_genericArguments.Count == 0)
74+
{
75+
return arguments.ToString();
76+
}
77+
78+
foreach (var genericArg in _genericArguments)
79+
{
80+
if (!arguments.Contains(genericArg.Key))
81+
{
82+
arguments.Add(genericArg.Key, genericArg.Value);
83+
}
84+
}
85+
86+
return arguments.ToString();
6487
}
6588

6689
/// <summary>
@@ -76,7 +99,12 @@ public ToastContentBuilder AddButton(string content, ToastActivationType activat
7699
#endif
77100
public ToastContentBuilder AddButton(string content, ToastActivationType activationType, ToastArguments arguments, Uri imageUri)
78101
{
79-
return AddButton(content, activationType, arguments.ToString(), imageUri);
102+
AddButton(content, activationType, SerializeArgumentsIncludingGeneric(arguments), imageUri);
103+
104+
// Remove this button from the custom arguments list
105+
_buttonsUsingCustomArguments.RemoveAt(_buttonsUsingCustomArguments.Count - 1);
106+
107+
return this;
80108
}
81109

82110
/// <summary>
@@ -91,6 +119,19 @@ public ToastContentBuilder AddButton(string content, ToastActivationType activat
91119
return AddButton(content, activationType, arguments, default);
92120
}
93121

122+
/// <summary>
123+
/// Add an button to the toast that will be display to the right of the input text box, achieving a quick reply scenario.
124+
/// </summary>
125+
/// <param name="textBoxId">ID of an existing <see cref="ToastTextBox"/> in order to have this button display to the right of the input, achieving a quick reply scenario.</param>
126+
/// <param name="content">Text to display on the button.</param>
127+
/// <param name="activationType">Type of activation this button will use when clicked. Defaults to Foreground.</param>
128+
/// <param name="arguments">App-defined arguments that the app can later retrieve once it is activated when the user clicks the button.</param>
129+
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
130+
public ToastContentBuilder AddButton(string textBoxId, string content, ToastActivationType activationType, ToastArguments arguments)
131+
{
132+
return AddButton(textBoxId, content, activationType, arguments, default);
133+
}
134+
94135
/// <summary>
95136
/// Add a button to the current toast.
96137
/// </summary>
@@ -129,7 +170,12 @@ public ToastContentBuilder AddButton(string content, ToastActivationType activat
129170
#endif
130171
public ToastContentBuilder AddButton(string textBoxId, string content, ToastActivationType activationType, ToastArguments arguments, Uri imageUri)
131172
{
132-
return AddButton(textBoxId, content, activationType, arguments.ToString(), imageUri);
173+
AddButton(textBoxId, content, activationType, SerializeArgumentsIncludingGeneric(arguments), imageUri);
174+
175+
// Remove this button from the custom arguments list
176+
_buttonsUsingCustomArguments.RemoveAt(_buttonsUsingCustomArguments.Count - 1);
177+
178+
return this;
133179
}
134180

135181
/// <summary>
@@ -147,6 +193,11 @@ public ToastContentBuilder AddButton(IToastButton button)
147193

148194
ButtonList.Add(button);
149195

196+
if (button is ToastButton b)
197+
{
198+
_buttonsUsingCustomArguments.Add(b);
199+
}
200+
150201
return this;
151202
}
152203

Microsoft.Toolkit.Uwp.Notifications/Toasts/Builder/ToastContentBuilder.cs

Lines changed: 179 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
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
89
{
@@ -11,6 +12,12 @@ namespace Microsoft.Toolkit.Uwp.Notifications
1112
/// </summary>
1213
public partial class ToastContentBuilder
1314
{
15+
private Dictionary<string, string> _genericArguments = new Dictionary<string, string>();
16+
17+
private bool _customArgumentsUsedOnToastItself;
18+
19+
private List<ToastButton> _buttonsUsingCustomArguments = new List<ToastButton>();
20+
1421
/// <summary>
1522
/// Gets internal instance of <see cref="ToastContent"/>. This is equivalent to the call to <see cref="ToastContentBuilder.GetToastContent"/>.
1623
/// </summary>
@@ -44,6 +51,22 @@ public ToastContentBuilder AddCustomTimeStamp(
4451
return this;
4552
}
4653

54+
/// <summary>
55+
/// Add a header to a toast.
56+
/// </summary>
57+
/// <param name="id">A developer-created identifier that uniquely identifies this header. If two notifications have the same header id, they will be displayed underneath the same header in Action Center.</param>
58+
/// <param name="title">A title for the header.</param>
59+
/// <param name="arguments">Developer-defined arguments that are returned to the app when the user clicks this header.</param>
60+
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
61+
/// <remarks>More info about toast header: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/toast-headers </remarks>
62+
#if WINRT
63+
[Windows.Foundation.Metadata.DefaultOverload]
64+
#endif
65+
public ToastContentBuilder AddHeader(string id, string title, ToastArguments arguments)
66+
{
67+
return AddHeader(id, title, arguments.ToString());
68+
}
69+
4770
/// <summary>
4871
/// Add a header to a toast.
4972
/// </summary>
@@ -60,44 +83,184 @@ public ToastContentBuilder AddHeader(string id, string title, string arguments)
6083
}
6184

6285
/// <summary>
63-
/// Add info that can be used by the application when the app was activated/launched by the toast. Uses foreground activation.
86+
/// Adds a key (without value) to the activation arguments that will be returned when the toast notification or its buttons are clicked.
6487
/// </summary>
65-
/// <param name="launchArgs">Custom app-defined launch arguments to be passed along on toast activation</param>
88+
/// <param name="key">The key.</param>
89+
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
90+
public ToastContentBuilder AddArgument(string key)
91+
{
92+
return AddArgumentHelper(key, null);
93+
}
94+
95+
/// <summary>
96+
/// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked.
97+
/// </summary>
98+
/// <param name="key">The key for this value.</param>
99+
/// <param name="value">The value itself.</param>
66100
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
67101
#if WINRT
68102
[Windows.Foundation.Metadata.DefaultOverload]
103+
[return: System.Runtime.InteropServices.WindowsRuntime.ReturnValueName("toastContentBuilder")]
69104
#endif
70-
public ToastContentBuilder AddToastActivationInfo(ToastArguments launchArgs)
105+
public ToastContentBuilder AddArgument(string key, string value)
71106
{
72-
return AddToastActivationInfo(launchArgs.ToString());
107+
return AddArgumentHelper(key, value);
73108
}
74109

75110
/// <summary>
76-
/// Add info that can be used by the application when the app was activated/launched by the toast.
111+
/// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked.
77112
/// </summary>
78-
/// <param name="launchArgs">Custom app-defined launch arguments to be passed along on toast activation</param>
79-
/// <param name="activationType">Set the activation type that will be used when the user click on this toast</param>
113+
/// <param name="key">The key for this value.</param>
114+
/// <param name="value">The value itself.</param>
80115
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
81116
#if WINRT
82-
[Windows.Foundation.Metadata.DefaultOverload]
117+
[return: System.Runtime.InteropServices.WindowsRuntime.ReturnValueName("toastContentBuilder")]
83118
#endif
84-
public ToastContentBuilder AddToastActivationInfo(ToastArguments launchArgs, ToastActivationType activationType)
119+
public ToastContentBuilder AddArgument(string key, int value)
85120
{
86-
return AddToastActivationInfo(launchArgs.ToString(), activationType);
121+
return AddArgumentHelper(key, value.ToString());
87122
}
88123

89124
/// <summary>
90-
/// Add info that can be used by the application when the app was activated/launched by the toast. Uses foreground activation.
125+
/// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked.
126+
/// </summary>
127+
/// <param name="key">The key for this value.</param>
128+
/// <param name="value">The value itself.</param>
129+
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
130+
#if WINRT
131+
[return: System.Runtime.InteropServices.WindowsRuntime.ReturnValueName("toastContentBuilder")]
132+
#endif
133+
public ToastContentBuilder AddArgument(string key, double value)
134+
{
135+
return AddArgumentHelper(key, value.ToString());
136+
}
137+
138+
/// <summary>
139+
/// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked.
140+
/// </summary>
141+
/// <param name="key">The key for this value.</param>
142+
/// <param name="value">The value itself.</param>
143+
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
144+
#if WINRT
145+
[return: System.Runtime.InteropServices.WindowsRuntime.ReturnValueName("toastContentBuilder")]
146+
#endif
147+
public ToastContentBuilder AddArgument(string key, float value)
148+
{
149+
return AddArgumentHelper(key, value.ToString());
150+
}
151+
152+
/// <summary>
153+
/// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked.
154+
/// </summary>
155+
/// <param name="key">The key for this value.</param>
156+
/// <param name="value">The value itself.</param>
157+
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
158+
#if WINRT
159+
[return: System.Runtime.InteropServices.WindowsRuntime.ReturnValueName("toastContentBuilder")]
160+
#endif
161+
public ToastContentBuilder AddArgument(string key, bool value)
162+
{
163+
return AddArgumentHelper(key, value ? "1" : "0"); // Encode as 1 or 0 to save string space
164+
}
165+
166+
#if !WINRT
167+
/// <summary>
168+
/// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked.
169+
/// </summary>
170+
/// <param name="key">The key for this value.</param>
171+
/// <param name="value">The value itself. Note that the enums are stored using their numeric value, so be aware that changing your enum number values might break existing activation of toasts currently in Action Center.</param>
172+
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
173+
public ToastContentBuilder AddArgument(string key, Enum value)
174+
{
175+
return AddArgumentHelper(key, ((int)(object)value).ToString());
176+
}
177+
#endif
178+
179+
private ToastContentBuilder AddArgumentHelper(string key, string value)
180+
{
181+
if (key == null)
182+
{
183+
throw new ArgumentNullException(nameof(key));
184+
}
185+
186+
bool alreadyExists = _genericArguments.ContainsKey(key);
187+
188+
_genericArguments[key] = value;
189+
190+
if (Content.ActivationType != ToastActivationType.Protocol && !_customArgumentsUsedOnToastItself)
191+
{
192+
Content.Launch = alreadyExists ? SerializeArgumentsHelper(_genericArguments) : AddArgumentHelper(Content.Launch, key, value);
193+
}
194+
195+
if (Content.Actions is ToastActionsCustom actions)
196+
{
197+
foreach (var button in actions.Buttons)
198+
{
199+
if (button is ToastButton b && b.ActivationType != ToastActivationType.Protocol && !_buttonsUsingCustomArguments.Contains(b))
200+
{
201+
var bArgs = ToastArguments.Parse(b.Arguments);
202+
if (!bArgs.Contains(key))
203+
{
204+
bArgs.Add(key, value);
205+
b.Arguments = bArgs.ToString();
206+
}
207+
}
208+
}
209+
}
210+
211+
return this;
212+
}
213+
214+
private string SerializeArgumentsHelper(IDictionary<string, string> arguments)
215+
{
216+
var args = new ToastArguments();
217+
218+
foreach (var a in arguments)
219+
{
220+
args.Add(a.Key, a.Value);
221+
}
222+
223+
return args.ToString();
224+
}
225+
226+
private string AddArgumentHelper(string existing, string key, string value)
227+
{
228+
string pair = ToastArguments.EncodePair(key, value);
229+
230+
if (existing == null)
231+
{
232+
return pair;
233+
}
234+
else
235+
{
236+
return existing + ToastArguments.Separator + pair;
237+
}
238+
}
239+
240+
/// <summary>
241+
/// Configures the toast notification to launch the specified url when the toast body is clicked.
242+
/// </summary>
243+
/// <param name="protocol">The protocol to launch.</param>
244+
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
245+
public ToastContentBuilder SetProtocolActivation(Uri protocol)
246+
{
247+
Content.Launch = protocol.ToString();
248+
Content.ActivationType = ToastActivationType.Protocol;
249+
return this;
250+
}
251+
252+
/// <summary>
253+
/// Configures the toast notification to use background activation when the toast body is clicked.
91254
/// </summary>
92-
/// <param name="launchArgs">Custom app-defined launch arguments to be passed along on toast activation</param>
93255
/// <returns>The current instance of <see cref="ToastContentBuilder"/></returns>
94-
public ToastContentBuilder AddToastActivationInfo(string launchArgs)
256+
public ToastContentBuilder SetBackgroundActivation()
95257
{
96-
return AddToastActivationInfo(launchArgs, ToastActivationType.Foreground);
258+
Content.ActivationType = ToastActivationType.Background;
259+
return this;
97260
}
98261

99262
/// <summary>
100-
/// Add info that can be used by the application when the app was activated/launched by the toast.
263+
/// Instead of this method, for foreground/background activation, it is suggested to use <see cref="AddArgument(string, string)"/> and optionally <see cref="SetBackgroundActivation"/>. For protocol activation, you should use <see cref="SetProtocolActivation(Uri)"/>. Add info that can be used by the application when the app was activated/launched by the toast.
101264
/// </summary>
102265
/// <param name="launchArgs">Custom app-defined launch arguments to be passed along on toast activation</param>
103266
/// <param name="activationType">Set the activation type that will be used when the user click on this toast</param>
@@ -106,6 +269,7 @@ public ToastContentBuilder AddToastActivationInfo(string launchArgs, ToastActiva
106269
{
107270
Content.Launch = launchArgs;
108271
Content.ActivationType = activationType;
272+
_customArgumentsUsedOnToastItself = true;
109273
return this;
110274
}
111275

0 commit comments

Comments
 (0)