From 8766f3290dd3171690918df7ee0c0f602fee6693 Mon Sep 17 00:00:00 2001 From: Arlo Godfrey Date: Tue, 6 Aug 2024 14:00:58 -0500 Subject: [PATCH 01/33] Fix possible nullrefs --- components/AppServices/src/AppServiceComponent.cs | 2 +- components/AppServices/src/AppServiceHost.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/AppServices/src/AppServiceComponent.cs b/components/AppServices/src/AppServiceComponent.cs index 3a61892ca..3e70a95f0 100644 --- a/components/AppServices/src/AppServiceComponent.cs +++ b/components/AppServices/src/AppServiceComponent.cs @@ -462,7 +462,7 @@ private async void Connection_RequestReceived(AppServiceConnection sender, AppSe try { // Try to get the registered endpoint with the command name, and invoke it - if (_endpoints.TryGetValue(commandStr, out Func> endpoint)) + if (_endpoints.TryGetValue(commandStr, out Func>? endpoint) && endpoint is {}) { response = await endpoint(new AppServiceParameters(this, sender, parameters)); } diff --git a/components/AppServices/src/AppServiceHost.cs b/components/AppServices/src/AppServiceHost.cs index a3558338d..ddf507046 100644 --- a/components/AppServices/src/AppServiceHost.cs +++ b/components/AppServices/src/AppServiceHost.cs @@ -204,9 +204,9 @@ private void AppServiceConnection_RequestReceived(AppServiceConnection sender, A if (args.Request.Message.TryGetValue(ProgressKey, out object? progressKey) && args.Request.Message.TryGetValue(ProgressValue, out object? progressValue) && progressKey is Guid id && - _progressTrackers.TryGetValue(id, out IProgress progress)) + _progressTrackers.TryGetValue(id, out IProgress? progress)) { - progress.Report(progressValue); + progress?.Report(progressValue); } } From 5b14120848cfed606e3b9cd984d1f3e23e325d41 Mon Sep 17 00:00:00 2001 From: Arlo Godfrey Date: Tue, 6 Aug 2024 14:01:14 -0500 Subject: [PATCH 02/33] Only reference WindowsDesktop SDK on legacy uwp --- .../AppServices/src/CommunityToolkit.AppServices.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/AppServices/src/CommunityToolkit.AppServices.csproj b/components/AppServices/src/CommunityToolkit.AppServices.csproj index dcab9109a..114ab24f2 100644 --- a/components/AppServices/src/CommunityToolkit.AppServices.csproj +++ b/components/AppServices/src/CommunityToolkit.AppServices.csproj @@ -29,7 +29,7 @@ - + Windows Desktop Extensions for the UWP @@ -55,7 +55,7 @@ - + From b7df0467ed4666560dc4bfbf255bf83388a4f627 Mon Sep 17 00:00:00 2001 From: Arlo Godfrey Date: Tue, 6 Aug 2024 14:01:29 -0500 Subject: [PATCH 03/33] Updating tooling --- tooling | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling b/tooling index fda081e11..729f09647 160000 --- a/tooling +++ b/tooling @@ -1 +1 @@ -Subproject commit fda081e11081ec7b0c034cdacbb817d906128b24 +Subproject commit 729f096478e6e01bae43411b6da3210e7b118cb4 From 694177de38e9e98972889ed61caa5628598b3a4c Mon Sep 17 00:00:00 2001 From: Arlo Godfrey Date: Tue, 6 Aug 2024 15:12:14 -0500 Subject: [PATCH 04/33] Include CommunityToolkit.AppServices.targets in nupkg for net8.0-windows10.0.22621 --- components/AppServices/src/CommunityToolkit.AppServices.csproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/AppServices/src/CommunityToolkit.AppServices.csproj b/components/AppServices/src/CommunityToolkit.AppServices.csproj index 114ab24f2..e0f0267bc 100644 --- a/components/AppServices/src/CommunityToolkit.AppServices.csproj +++ b/components/AppServices/src/CommunityToolkit.AppServices.csproj @@ -51,8 +51,11 @@ + + + From 09617b26b5e85cd88e9c0724c587741f788a0701 Mon Sep 17 00:00:00 2001 From: Arlo Godfrey Date: Fri, 23 Aug 2024 15:36:44 -0500 Subject: [PATCH 05/33] Update tooling to latest main --- tooling | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling b/tooling index 729f09647..df780af45 160000 --- a/tooling +++ b/tooling @@ -1 +1 @@ -Subproject commit 729f096478e6e01bae43411b6da3210e7b118cb4 +Subproject commit df780af45016b43606f04d202255e37033402af5 From e2929f358b22ce6b0ff4018a6781df68af720c72 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 10 Oct 2024 23:31:33 -0700 Subject: [PATCH 06/33] Add support for modern .NET to AppServices library --- .../AppServiceGenerator.Helpers.cs | 24 +++++++- .../AppServiceGenerator.cs | 10 ++-- ...eratorAttributeSyntaxContextWithOptions.cs | 34 +++++++++++ .../GeneratorSyntaxContextWithOptions.cs | 27 +++++++++ ...eneratorInitializationContextExtensions.cs | 59 +++++++++++++++++++ .../AppServices/src/AppServiceComponent.cs | 2 +- .../src/CommunityToolkit.AppServices.csproj | 11 +--- .../src/CommunityToolkit.AppServices.targets | 5 ++ components/AppServices/src/MultiTarget.props | 2 +- 9 files changed, 155 insertions(+), 19 deletions(-) create mode 100644 components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/GeneratorAttributeSyntaxContextWithOptions.cs create mode 100644 components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/GeneratorSyntaxContextWithOptions.cs create mode 100644 components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/IncrementalGeneratorInitializationContextExtensions.cs diff --git a/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/AppServiceGenerator.Helpers.cs b/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/AppServiceGenerator.Helpers.cs index 94c333763..ed86c952a 100644 --- a/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/AppServiceGenerator.Helpers.cs +++ b/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/AppServiceGenerator.Helpers.cs @@ -1,8 +1,9 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; namespace CommunityToolkit.AppServices.SourceGenerators; @@ -18,10 +19,27 @@ private static class Helpers /// Gets whether the current target is a UWP application. /// /// The input instance to inspect. + /// The analyzer options to use to get info on the target application. /// Whether the current target is a UWP application. - public static bool IsUwpTarget(Compilation compilation) + public static bool IsUwpTarget(Compilation compilation, AnalyzerConfigOptions analyzerOptions) { - return compilation.Options.OutputKind == OutputKind.WindowsRuntimeApplication; + // If the application type is a Windows Runtime application, then it's for sure a UWP app + if (compilation.Options.OutputKind == OutputKind.WindowsRuntimeApplication) + { + return true; + } + + // Otherwise, the application is UWP if "UseUwpTools" is set + if (analyzerOptions.TryGetValue("build_property.UseUwpTools", out string? propertyValue)) + { + if (bool.TryParse(propertyValue, out bool useUwpTools)) + { + return true; + } + } + + // The app is definitely not a UWP app + return false; } } } diff --git a/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/AppServiceGenerator.cs b/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/AppServiceGenerator.cs index 466f313bc..f85e2a73b 100644 --- a/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/AppServiceGenerator.cs +++ b/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/AppServiceGenerator.cs @@ -24,13 +24,12 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { // Get all app service class implementations, and only enable this branch if the target is not a UWP app (the component) IncrementalValuesProvider<(HierarchyInfo Hierarchy, AppServiceInfo Info)> appServiceComponentInfo = - context.SyntaxProvider - .CreateSyntaxProvider( + context.CreateSyntaxProviderWithOptions( static (node, _) => node is ClassDeclarationSyntax classDeclaration && classDeclaration.HasOrPotentiallyHasBaseTypes(), static (context, token) => { // Only retrieve host info if the target is not a UWP application - if (Helpers.IsUwpTarget(context.SemanticModel.Compilation)) + if (Helpers.IsUwpTarget(context.SemanticModel.Compilation, context.GlobalOptions)) { return default; } @@ -80,14 +79,13 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Gather all interfaces, and only enable this branch if the target is a UWP app (the host) IncrementalValuesProvider<(HierarchyInfo Hierarchy, AppServiceInfo Info)> appServiceHostInfo = - context.SyntaxProvider - .ForAttributeWithMetadataName( + context.ForAttributeWithMetadataNameAndOptions( "CommunityToolkit.AppServices.AppServiceAttribute", static (node, _) => node is InterfaceDeclarationSyntax, static (context, token) => { // Only retrieve host info if the target is a UWP application - if (!Helpers.IsUwpTarget(context.SemanticModel.Compilation)) + if (!Helpers.IsUwpTarget(context.SemanticModel.Compilation, context.GlobalOptions)) { return default; } diff --git a/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/GeneratorAttributeSyntaxContextWithOptions.cs b/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/GeneratorAttributeSyntaxContextWithOptions.cs new file mode 100644 index 000000000..7f7596e01 --- /dev/null +++ b/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/GeneratorAttributeSyntaxContextWithOptions.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace CommunityToolkit.AppServices.SourceGenerators.Extensions; + +/// +/// +/// +/// The original value. +/// The original value. +internal readonly struct GeneratorAttributeSyntaxContextWithOptions( + GeneratorAttributeSyntaxContext syntaxContext, + AnalyzerConfigOptions globalOptions) +{ + /// + public SyntaxNode TargetNode { get; } = syntaxContext.TargetNode; + + /// + public ISymbol TargetSymbol { get; } = syntaxContext.TargetSymbol; + + /// + public SemanticModel SemanticModel { get; } = syntaxContext.SemanticModel; + + /// + public ImmutableArray Attributes { get; } = syntaxContext.Attributes; + + /// + public AnalyzerConfigOptions GlobalOptions { get; } = globalOptions; +} diff --git a/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/GeneratorSyntaxContextWithOptions.cs b/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/GeneratorSyntaxContextWithOptions.cs new file mode 100644 index 000000000..141087948 --- /dev/null +++ b/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/GeneratorSyntaxContextWithOptions.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace CommunityToolkit.AppServices.SourceGenerators.Extensions; + +/// +/// +/// +/// The original value. +/// The original value. +internal readonly struct GeneratorSyntaxContextWithOptions( + GeneratorSyntaxContext syntaxContext, + AnalyzerConfigOptions globalOptions) +{ + /// + public SyntaxNode Node { get; } = syntaxContext.Node; + + /// + public SemanticModel SemanticModel { get; } = syntaxContext.SemanticModel; + + /// + public AnalyzerConfigOptions GlobalOptions { get; } = globalOptions; +} diff --git a/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/IncrementalGeneratorInitializationContextExtensions.cs b/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/IncrementalGeneratorInitializationContextExtensions.cs new file mode 100644 index 000000000..d8e900d9b --- /dev/null +++ b/components/AppServices/CommunityToolkit.AppServices.SourceGenerators/Extensions/IncrementalGeneratorInitializationContextExtensions.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Threading; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace CommunityToolkit.AppServices.SourceGenerators.Extensions; + +/// +/// Extension methods for . +/// +internal static class IncrementalGeneratorInitializationContextExtensions +{ + /// + public static IncrementalValuesProvider ForAttributeWithMetadataNameAndOptions( + this IncrementalGeneratorInitializationContext context, + string fullyQualifiedMetadataName, + Func predicate, + Func transform) + { + // Invoke 'ForAttributeWithMetadataName' normally, but just return the context directly + IncrementalValuesProvider syntaxContext = context.SyntaxProvider.ForAttributeWithMetadataName( + fullyQualifiedMetadataName, + predicate, + static (context, token) => context); + + // Do the same for the analyzer config options + IncrementalValueProvider configOptions = context.AnalyzerConfigOptionsProvider.Select(static (provider, token) => provider.GlobalOptions); + + // Merge the two and invoke the provided transform on these two values. Neither value + // is equatable, meaning the pipeline will always re-run until this point. This is + // intentional: we don't want any symbols or other expensive objects to be kept alive + // across incremental steps, especially if they could cause entire compilations to be + // rooted, which would significantly increase memory use and introduce more GC pauses. + // In this specific case, flowing non equatable values in a pipeline is therefore fine. + return syntaxContext.Combine(configOptions).Select((input, token) => transform(new GeneratorAttributeSyntaxContextWithOptions(input.Left, input.Right), token)); + } + + /// + public static IncrementalValuesProvider CreateSyntaxProviderWithOptions( + this IncrementalGeneratorInitializationContext context, + Func predicate, + Func transform) + { + // Invoke 'ForAttributeWithMetadataName' normally, but just return the context directly + IncrementalValuesProvider syntaxContext = context.SyntaxProvider.CreateSyntaxProvider( + predicate, + static (context, token) => context); + + // Do the same for the analyzer config options + IncrementalValueProvider configOptions = context.AnalyzerConfigOptionsProvider.Select(static (provider, token) => provider.GlobalOptions); + + // Merge the two and invoke the provided transform, like the extension above + return syntaxContext.Combine(configOptions).Select((input, token) => transform(new GeneratorSyntaxContextWithOptions(input.Left, input.Right), token)); + } +} diff --git a/components/AppServices/src/AppServiceComponent.cs b/components/AppServices/src/AppServiceComponent.cs index 3e70a95f0..2692f96fe 100644 --- a/components/AppServices/src/AppServiceComponent.cs +++ b/components/AppServices/src/AppServiceComponent.cs @@ -14,7 +14,7 @@ using System.Diagnostics.CodeAnalysis; using CommunityToolkit.AppServices.Helpers; -#pragma warning disable CA2213, CA1063 +#pragma warning disable CA2213, CA1063, CsWinRT1028 namespace CommunityToolkit.AppServices; diff --git a/components/AppServices/src/CommunityToolkit.AppServices.csproj b/components/AppServices/src/CommunityToolkit.AppServices.csproj index e0f0267bc..ed88531c1 100644 --- a/components/AppServices/src/CommunityToolkit.AppServices.csproj +++ b/components/AppServices/src/CommunityToolkit.AppServices.csproj @@ -36,7 +36,7 @@ - + @@ -49,13 +49,8 @@ - - - - - - - + + diff --git a/components/AppServices/src/CommunityToolkit.AppServices.targets b/components/AppServices/src/CommunityToolkit.AppServices.targets index 78089e0a2..21ddc5cf2 100644 --- a/components/AppServices/src/CommunityToolkit.AppServices.targets +++ b/components/AppServices/src/CommunityToolkit.AppServices.targets @@ -1,5 +1,10 @@ + + + + + diff --git a/components/AppServices/src/MultiTarget.props b/components/AppServices/src/MultiTarget.props index c8f516392..5385c58a1 100644 --- a/components/AppServices/src/MultiTarget.props +++ b/components/AppServices/src/MultiTarget.props @@ -4,6 +4,6 @@ MultiTarget is a custom property that indicates which target a project is designed to be built for / run on. Used to create project references, generate solution files, enable/disable TargetFrameworks, and build nuget packages. --> - uwp;netstandard; + uwp;netstandard;net8.0-windows10.0.17763.0 From d423cfefa712699e4f8af4f77f60101a990e5fc1 Mon Sep 17 00:00:00 2001 From: Arlo Date: Mon, 14 Oct 2024 14:36:04 -0500 Subject: [PATCH 07/33] Update components/AppServices/src/MultiTarget.props --- components/AppServices/src/MultiTarget.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/AppServices/src/MultiTarget.props b/components/AppServices/src/MultiTarget.props index 5385c58a1..c8f516392 100644 --- a/components/AppServices/src/MultiTarget.props +++ b/components/AppServices/src/MultiTarget.props @@ -4,6 +4,6 @@ MultiTarget is a custom property that indicates which target a project is designed to be built for / run on. Used to create project references, generate solution files, enable/disable TargetFrameworks, and build nuget packages. --> - uwp;netstandard;net8.0-windows10.0.17763.0 + uwp;netstandard; From 49de3099cac4e2b8e9852ab8bfa511ed434ee591 Mon Sep 17 00:00:00 2001 From: Arlo Godfrey Date: Mon, 14 Oct 2024 15:05:19 -0500 Subject: [PATCH 08/33] Fixed invalid namespace reference --- components/AppServices/src/AppServiceHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/AppServices/src/AppServiceHost.cs b/components/AppServices/src/AppServiceHost.cs index ddf507046..28cb0b727 100644 --- a/components/AppServices/src/AppServiceHost.cs +++ b/components/AppServices/src/AppServiceHost.cs @@ -75,7 +75,7 @@ protected AppServiceHost(string appServiceName) private static bool CanUseAppServiceFunctionality { get; } = AnalyticsInfo.VersionInfo.DeviceFamily == "Windows.Desktop" && ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0); /// - /// Handles the app service activation when is invoked. + /// Handles the app service activation when is invoked. /// /// The args for the background activation. /// Whether this activation was an app service connection that could be handled by this host. From 7c88625eac0ef493fd4b02c63135b8c628a9217d Mon Sep 17 00:00:00 2001 From: Arlo Godfrey Date: Mon, 14 Oct 2024 15:32:52 -0500 Subject: [PATCH 09/33] Update Microsoft.Windows.SDK.Contracts to only be included under netstandard --- components/AppServices/src/CommunityToolkit.AppServices.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/AppServices/src/CommunityToolkit.AppServices.csproj b/components/AppServices/src/CommunityToolkit.AppServices.csproj index ed88531c1..fe55ef734 100644 --- a/components/AppServices/src/CommunityToolkit.AppServices.csproj +++ b/components/AppServices/src/CommunityToolkit.AppServices.csproj @@ -36,7 +36,7 @@ - + From bcd3874aa08eb6e9959ddced40d54495db7814da Mon Sep 17 00:00:00 2001 From: Arlo Godfrey Date: Mon, 14 Oct 2024 15:41:14 -0500 Subject: [PATCH 10/33] Update Microsoft.Windows.SDK.Contracts to 10.0.26100.1742 --- components/AppServices/src/CommunityToolkit.AppServices.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/AppServices/src/CommunityToolkit.AppServices.csproj b/components/AppServices/src/CommunityToolkit.AppServices.csproj index fe55ef734..066d1a589 100644 --- a/components/AppServices/src/CommunityToolkit.AppServices.csproj +++ b/components/AppServices/src/CommunityToolkit.AppServices.csproj @@ -37,7 +37,7 @@ - + From cdbde343bf61220d287ba5a6c120afd6751138b4 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Tue, 15 Oct 2024 08:49:49 -0700 Subject: [PATCH 11/33] Fix name of AppService targets --- .../AppServices/src/CommunityToolkit.AppServices.csproj | 4 ++-- ...ices.targets => CommunityToolkit.Labs.AppServices.targets} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename components/AppServices/src/{CommunityToolkit.AppServices.targets => CommunityToolkit.Labs.AppServices.targets} (100%) diff --git a/components/AppServices/src/CommunityToolkit.AppServices.csproj b/components/AppServices/src/CommunityToolkit.AppServices.csproj index 066d1a589..cf4e183b4 100644 --- a/components/AppServices/src/CommunityToolkit.AppServices.csproj +++ b/components/AppServices/src/CommunityToolkit.AppServices.csproj @@ -49,8 +49,8 @@ - - + + diff --git a/components/AppServices/src/CommunityToolkit.AppServices.targets b/components/AppServices/src/CommunityToolkit.Labs.AppServices.targets similarity index 100% rename from components/AppServices/src/CommunityToolkit.AppServices.targets rename to components/AppServices/src/CommunityToolkit.Labs.AppServices.targets From 1a9bbf82245fc7b9d5677f566a6d3f91b5790011 Mon Sep 17 00:00:00 2001 From: Arlo Godfrey Date: Wed, 13 Nov 2024 14:05:06 -0600 Subject: [PATCH 12/33] Fixed AoT build error --- components/Notifications/src/Toasts/ToastArguments.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Notifications/src/Toasts/ToastArguments.cs b/components/Notifications/src/Toasts/ToastArguments.cs index de9862c11..c7d756a5c 100644 --- a/components/Notifications/src/Toasts/ToastArguments.cs +++ b/components/Notifications/src/Toasts/ToastArguments.cs @@ -12,7 +12,7 @@ namespace CommunityToolkit.Notifications /// /// A class that supports serializing simple key/value pairs into a format that's friendly for being used within toast notifications. The serialized format is similar to a query string, however optimized for being placed within an XML property (uses semicolons instead of ampersands since those don't need to be XML-escaped, doesn't url-encode all special characters since not being used within a URL, etc). /// - public sealed class ToastArguments : IEnumerable> + public sealed partial class ToastArguments : IEnumerable> { private Dictionary _dictionary = new Dictionary(); From 8ce50b73b1a93117e64441fb2a54fe1f2f547050 Mon Sep 17 00:00:00 2001 From: Arlo Godfrey Date: Wed, 13 Nov 2024 14:06:17 -0600 Subject: [PATCH 13/33] Update subproject commit reference in tooling --- tooling | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling b/tooling index d71b08b2d..01984d303 160000 --- a/tooling +++ b/tooling @@ -1 +1 @@ -Subproject commit d71b08b2dccf94c3ceaeda99526679bc0cfc3b8a +Subproject commit 01984d3035cdd0cc56e08764aac473d24778ac69 From ce173c4c4904a6053b67c9fde468b002a24d6728 Mon Sep 17 00:00:00 2001 From: Arlo Date: Wed, 4 Dec 2024 17:57:26 -0600 Subject: [PATCH 14/33] Update .NET version to 9.0 and related dependencies --- .devcontainer/Dockerfile | 7 ++----- .devcontainer/devcontainer.json | 2 +- .github/workflows/build.yml | 2 +- Directory.Build.targets | 2 +- .../src/CommunityToolkit.Notifications.csproj | 2 ++ global.json | 2 +- tooling | 2 +- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index f09593147..6935449fd 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,8 +1,5 @@ -# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.208.0/containers/dotnet/.devcontainer/base.Dockerfile - -# [Choice] .NET version: 6.0, 5.0, 3.1, 6.0-bullseye, 5.0-bullseye, 3.1-bullseye, 6.0-focal, 5.0-focal, 3.1-focal, etc -ARG VARIANT="8.0-bullseye-slim" -FROM mcr.microsoft.com/vscode/devcontainers/dotnet:0-${VARIANT} +# See https://github.com/devcontainers/images/tree/main/src/dotnet for image choices +FROM mcr.microsoft.com/vscode/devcontainers/dotnet:9.0 # [Choice] Node.js version: none, lts/*, 16, 14, 12, 10 ARG NODE_VERSION="none" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index d21671858..f616c78fc 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -7,7 +7,7 @@ "args": { // Update 'VARIANT' to pick a .NET Core version: 3.1, 5.0, 6.0 // Append -bullseye or -focal to pin to an OS version. - "VARIANT": "6.0", + "VARIANT": "9.0", // Options "NODE_VERSION": "lts/*" } diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 02c0edab0..c51dbcb26 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ on: merge_group: env: - DOTNET_VERSION: ${{ '8.0.201' }} + DOTNET_VERSION: ${{ '9.0.x' }} ENABLE_DIAGNOSTICS: false #COREHOST_TRACE: 1 MSBUILD_VERBOSITY: normal diff --git a/Directory.Build.targets b/Directory.Build.targets index 22dfa3191..40046bdf3 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,7 +1,7 @@ - + diff --git a/components/Notifications/src/CommunityToolkit.Notifications.csproj b/components/Notifications/src/CommunityToolkit.Notifications.csproj index 4112bc6c6..2b4d84952 100644 --- a/components/Notifications/src/CommunityToolkit.Notifications.csproj +++ b/components/Notifications/src/CommunityToolkit.Notifications.csproj @@ -14,6 +14,8 @@ $(PackageIdPrefix).$(ToolkitComponentName) disable false + + uap10.0.17763;net8.0-windows10.0.17763.0; diff --git a/global.json b/global.json index 91187a7c4..27a187755 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.403", + "version": "9.0.101", "rollForward": "latestFeature" }, "msbuild-sdks": diff --git a/tooling b/tooling index 01984d303..58dd1c561 160000 --- a/tooling +++ b/tooling @@ -1 +1 @@ -Subproject commit 01984d3035cdd0cc56e08764aac473d24778ac69 +Subproject commit 58dd1c5615f575fe2d08717b0787a6313e99f2e6 From bb8ccefee12b1f5e4d3ccf4982fe6a810d2db53b Mon Sep 17 00:00:00 2001 From: Arlo Date: Thu, 19 Dec 2024 11:50:10 -0600 Subject: [PATCH 15/33] Add workaround for WebView2 SDKReference issue in Directory.Build.targets --- Directory.Build.targets | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Directory.Build.targets b/Directory.Build.targets index 40046bdf3..77e29d5d4 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,4 +1,8 @@ + + + + From 148f00429562094f495e543dabd6a4a0528305df Mon Sep 17 00:00:00 2001 From: Arlo Date: Thu, 19 Dec 2024 11:56:25 -0600 Subject: [PATCH 16/33] Update CommunityToolkit package references to PR version 8.2.241219-pull-584.1339 --- components/CanvasView/src/Dependencies.props | 8 ++++---- components/DataTable/samples/Dependencies.props | 8 ++++---- components/DataTable/src/Dependencies.props | 12 ++++++------ components/RivePlayer/samples/Dependencies.props | 8 ++++---- components/Shimmer/src/Dependencies.props | 8 ++++---- components/TokenView/src/Dependencies.props | 16 ++++++++-------- .../TransitionHelper/samples/Dependencies.props | 8 ++++---- .../TransitionHelper/src/Dependencies.props | 16 ++++++++-------- nuget.config | 1 + tooling | 2 +- 10 files changed, 44 insertions(+), 43 deletions(-) diff --git a/components/CanvasView/src/Dependencies.props b/components/CanvasView/src/Dependencies.props index a52b7ba47..b2e69d931 100644 --- a/components/CanvasView/src/Dependencies.props +++ b/components/CanvasView/src/Dependencies.props @@ -11,21 +11,21 @@ - + - + - + - + diff --git a/components/DataTable/samples/Dependencies.props b/components/DataTable/samples/Dependencies.props index 86bd9e0c5..2353d5347 100644 --- a/components/DataTable/samples/Dependencies.props +++ b/components/DataTable/samples/Dependencies.props @@ -11,14 +11,14 @@ - - + + - - + + diff --git a/components/DataTable/src/Dependencies.props b/components/DataTable/src/Dependencies.props index f58250e21..8b66d5b59 100644 --- a/components/DataTable/src/Dependencies.props +++ b/components/DataTable/src/Dependencies.props @@ -14,15 +14,15 @@ - - - + + + - - - + + + diff --git a/components/RivePlayer/samples/Dependencies.props b/components/RivePlayer/samples/Dependencies.props index 813f9dd9d..77b7ec0bc 100644 --- a/components/RivePlayer/samples/Dependencies.props +++ b/components/RivePlayer/samples/Dependencies.props @@ -12,24 +12,24 @@ - + - + - + - + diff --git a/components/Shimmer/src/Dependencies.props b/components/Shimmer/src/Dependencies.props index 288b65b9a..73a92fa58 100644 --- a/components/Shimmer/src/Dependencies.props +++ b/components/Shimmer/src/Dependencies.props @@ -12,24 +12,24 @@ - + - + - + - + diff --git a/components/TokenView/src/Dependencies.props b/components/TokenView/src/Dependencies.props index 3e20f9746..28c39e301 100644 --- a/components/TokenView/src/Dependencies.props +++ b/components/TokenView/src/Dependencies.props @@ -11,25 +11,25 @@ - - + + - - + + - - + + - - + + diff --git a/components/TransitionHelper/samples/Dependencies.props b/components/TransitionHelper/samples/Dependencies.props index 4dfd1d74a..bd8b49100 100644 --- a/components/TransitionHelper/samples/Dependencies.props +++ b/components/TransitionHelper/samples/Dependencies.props @@ -11,21 +11,21 @@ - + - + - + - + diff --git a/components/TransitionHelper/src/Dependencies.props b/components/TransitionHelper/src/Dependencies.props index d7912ab7d..e420d9d80 100644 --- a/components/TransitionHelper/src/Dependencies.props +++ b/components/TransitionHelper/src/Dependencies.props @@ -11,25 +11,25 @@ - - + + - - + + - - + + - - + + diff --git a/nuget.config b/nuget.config index c5b04e7aa..d2f2227e8 100644 --- a/nuget.config +++ b/nuget.config @@ -3,6 +3,7 @@ + diff --git a/tooling b/tooling index 58dd1c561..228d7c503 160000 --- a/tooling +++ b/tooling @@ -1 +1 @@ -Subproject commit 58dd1c5615f575fe2d08717b0787a6313e99f2e6 +Subproject commit 228d7c5037cf30ee7c6157b696aa44d424940132 From c95c9b0771991b557560e1b6da7d4632e4a9cd57 Mon Sep 17 00:00:00 2001 From: Arlo Date: Thu, 19 Dec 2024 12:01:49 -0600 Subject: [PATCH 17/33] Update subproject commit reference in tooling --- tooling | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling b/tooling index 228d7c503..a58a89ab7 160000 --- a/tooling +++ b/tooling @@ -1 +1 @@ -Subproject commit 228d7c5037cf30ee7c6157b696aa44d424940132 +Subproject commit a58a89ab79deb9740e7fa9c3951f803af7260975 From 3bd4e8afafe748a7030af98a720e0902040386a6 Mon Sep 17 00:00:00 2001 From: Arlo Date: Fri, 20 Dec 2024 14:46:57 -0600 Subject: [PATCH 18/33] Update TFM overrides --- .../Notifications/src/CommunityToolkit.Notifications.csproj | 2 +- components/RivePlayer/samples/RivePlayer.Samples.csproj | 1 + .../src/CommunityToolkit.Labs.WinUI.Rive.RivePlayer.csproj | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/components/Notifications/src/CommunityToolkit.Notifications.csproj b/components/Notifications/src/CommunityToolkit.Notifications.csproj index 2b4d84952..bc0704010 100644 --- a/components/Notifications/src/CommunityToolkit.Notifications.csproj +++ b/components/Notifications/src/CommunityToolkit.Notifications.csproj @@ -15,7 +15,7 @@ disable false - uap10.0.17763;net8.0-windows10.0.17763.0; + uap10.0.17763;net8.0-windows10.0.17763.0; diff --git a/components/RivePlayer/samples/RivePlayer.Samples.csproj b/components/RivePlayer/samples/RivePlayer.Samples.csproj index b14d2ab0b..8932e3150 100644 --- a/components/RivePlayer/samples/RivePlayer.Samples.csproj +++ b/components/RivePlayer/samples/RivePlayer.Samples.csproj @@ -2,6 +2,7 @@ RivePlayer + uap10.0.17763; diff --git a/components/RivePlayer/src/CommunityToolkit.Labs.WinUI.Rive.RivePlayer.csproj b/components/RivePlayer/src/CommunityToolkit.Labs.WinUI.Rive.RivePlayer.csproj index 3d74f9921..9b99f6e7a 100644 --- a/components/RivePlayer/src/CommunityToolkit.Labs.WinUI.Rive.RivePlayer.csproj +++ b/components/RivePlayer/src/CommunityToolkit.Labs.WinUI.Rive.RivePlayer.csproj @@ -7,6 +7,7 @@ CommunityToolkit.Labs.WinUI.RivePlayerRns true + uap10.0.17763; From 7717f6fe144f9b88e551f0d07a83cf90a1fdfc9c Mon Sep 17 00:00:00 2001 From: Arlo Date: Fri, 20 Dec 2024 14:47:20 -0600 Subject: [PATCH 19/33] Minor cleanup, remove templated example --- components/RivePlayer/src/Dependencies.props | 4 ---- 1 file changed, 4 deletions(-) diff --git a/components/RivePlayer/src/Dependencies.props b/components/RivePlayer/src/Dependencies.props index 6c847f517..857208ac2 100644 --- a/components/RivePlayer/src/Dependencies.props +++ b/components/RivePlayer/src/Dependencies.props @@ -16,25 +16,21 @@ - - - - From 348a368231a49c33e7033ede0278bc79e00ba148 Mon Sep 17 00:00:00 2001 From: Arlo Date: Fri, 20 Dec 2024 14:48:11 -0600 Subject: [PATCH 20/33] Updated away from deprecated Behaviors namespaces --- .../samples/RivePlayerCustomSample.xaml | 13 ++++---- .../samples/TransitionHelperFullExample.xaml | 33 +++++++++---------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/components/RivePlayer/samples/RivePlayerCustomSample.xaml b/components/RivePlayer/samples/RivePlayerCustomSample.xaml index 56bd8b76b..66c2ddaa7 100644 --- a/components/RivePlayer/samples/RivePlayerCustomSample.xaml +++ b/components/RivePlayer/samples/RivePlayerCustomSample.xaml @@ -4,7 +4,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:i="using:Microsoft.Xaml.Interactivity" - xmlns:ic="using:Microsoft.Xaml.Interactions.Core" xmlns:local="using:RivePlayerExperiment.Samples" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:rive="using:CommunityToolkit.Labs.WinUI.Rive" @@ -50,18 +49,18 @@ Content="Hands Up" /> diff --git a/components/TransitionHelper/samples/TransitionHelperFullExample.xaml b/components/TransitionHelper/samples/TransitionHelperFullExample.xaml index 381d2f40b..e2a9ca006 100644 --- a/components/TransitionHelper/samples/TransitionHelperFullExample.xaml +++ b/components/TransitionHelper/samples/TransitionHelperFullExample.xaml @@ -3,7 +3,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:i="using:Microsoft.Xaml.Interactivity" - xmlns:ic="using:Microsoft.Xaml.Interactions.Core" xmlns:labs="using:CommunityToolkit.Labs.WinUI" xmlns:local="using:TransitionHelperExperiment.Samples" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" @@ -52,22 +51,22 @@ Content="" Style="{StaticResource NavigationBackButtonNormalStyle}"> - + - + @@ -100,31 +99,31 @@ @@ -204,31 +203,31 @@ From 3870435a4f85aa70c0a09371a59f7f98d8784e1f Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 21 Dec 2024 18:33:37 +0100 Subject: [PATCH 21/33] Add 'net9.0-windows10.0.17763.0' TFM for UWP --- .../Notifications/src/CommunityToolkit.Notifications.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/Notifications/src/CommunityToolkit.Notifications.csproj b/components/Notifications/src/CommunityToolkit.Notifications.csproj index bc0704010..f0dc09f9b 100644 --- a/components/Notifications/src/CommunityToolkit.Notifications.csproj +++ b/components/Notifications/src/CommunityToolkit.Notifications.csproj @@ -15,7 +15,8 @@ disable false - uap10.0.17763;net8.0-windows10.0.17763.0; + + uap10.0.17763;net8.0-windows10.0.17763.0;net9.0-windows10.0.17763.0; From 14b9a8e003eca1b9717fb9bc86e6873e5b83b698 Mon Sep 17 00:00:00 2001 From: Arlo Date: Mon, 23 Dec 2024 13:36:22 -0600 Subject: [PATCH 22/33] Ran XAML styler --- components/RivePlayer/samples/RivePlayerCustomSample.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/RivePlayer/samples/RivePlayerCustomSample.xaml b/components/RivePlayer/samples/RivePlayerCustomSample.xaml index 66c2ddaa7..95f128dd7 100644 --- a/components/RivePlayer/samples/RivePlayerCustomSample.xaml +++ b/components/RivePlayer/samples/RivePlayerCustomSample.xaml @@ -51,7 +51,7 @@ + TargetObject="{x:Bind FailureTrigger}" /> @@ -59,7 +59,7 @@ + TargetObject="{x:Bind SuccessTrigger}" /> From 91de16da767491ed8e3940582ef3c0aac2fdf9c1 Mon Sep 17 00:00:00 2001 From: Arlo Date: Mon, 23 Dec 2024 13:39:39 -0600 Subject: [PATCH 23/33] Use normal windows-latest runner for Xaml Style Check --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1cc92604e..9db0a33a8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ env: jobs: # This workflow contains a single job called "Xaml-Style-Check" Xaml-Style-Check: - runs-on: windows-latest-large + runs-on: windows-latest # Steps represent a sequence of tasks that will be executed as part of the job steps: From 9e161f10c56c47dd855ff5c7d032e2ac6b70ef17 Mon Sep 17 00:00:00 2001 From: Arlo Date: Mon, 23 Dec 2024 14:00:00 -0600 Subject: [PATCH 24/33] Use tooling to declare GlobalUsings --- Windows.Toolkit.Common.props | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Windows.Toolkit.Common.props b/Windows.Toolkit.Common.props index 83f9ae093..773d2effe 100644 --- a/Windows.Toolkit.Common.props +++ b/Windows.Toolkit.Common.props @@ -29,8 +29,4 @@ true true - - - - From 5c0fb58c0acca09dabe77c193a589cc54c636fe0 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Mon, 23 Dec 2024 21:06:25 +0100 Subject: [PATCH 25/33] Fix some trim warnings --- components/CanvasView/src/CanvasView.cs | 6 ++++++ components/CanvasView/src/FrameworkElementExtensions.cs | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/components/CanvasView/src/CanvasView.cs b/components/CanvasView/src/CanvasView.cs index 72f13bd36..2268159ca 100644 --- a/components/CanvasView/src/CanvasView.cs +++ b/components/CanvasView/src/CanvasView.cs @@ -2,6 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif using CommunityToolkit.Labs.WinUI.CanvasViewInternal; using CommunityToolkit.WinUI.Helpers; @@ -59,6 +62,9 @@ protected override void ClearContainerForItemOverride(DependencyObject element, } } +#if NET8_0_OR_GREATER + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "These use of 'SetBindingExpressionValue' might be fine (we should revisit this later)")] +#endif private void ContentPresenter_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) { // Move the rectangle. diff --git a/components/CanvasView/src/FrameworkElementExtensions.cs b/components/CanvasView/src/FrameworkElementExtensions.cs index 4619b4977..ad70d1122 100644 --- a/components/CanvasView/src/FrameworkElementExtensions.cs +++ b/components/CanvasView/src/FrameworkElementExtensions.cs @@ -2,6 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif + namespace CommunityToolkit.Labs.WinUI.CanvasViewInternal; public static partial class FrameworkElementExtensions @@ -16,6 +20,9 @@ public static partial class FrameworkElementExtensions /// The with the property to update. /// The to update the underlying bound value of. /// The new value to update the bound property to. +#if NET8_0_OR_GREATER + [RequiresUnreferencedCode("This method accesses properties of binding expressions in a trim-unsafe way.")] +#endif public static void SetBindingExpressionValue(this FrameworkElement fe, DependencyProperty property, object value) { var subBinding = fe.GetBindingExpression(property); From b2c0ab98acd15e41f94c453ea77416c804f601b7 Mon Sep 17 00:00:00 2001 From: Arlo Date: Tue, 24 Dec 2024 14:48:30 -0600 Subject: [PATCH 26/33] Update CommunityToolkit package references to version 8.2.241223-build.1367 --- components/CanvasView/src/Dependencies.props | 8 ++++---- components/DataTable/samples/Dependencies.props | 8 ++++---- components/DataTable/src/Dependencies.props | 12 ++++++------ components/RivePlayer/samples/Dependencies.props | 8 ++++---- components/Shimmer/src/Dependencies.props | 8 ++++---- components/TokenView/src/Dependencies.props | 16 ++++++++-------- .../TransitionHelper/samples/Dependencies.props | 8 ++++---- .../TransitionHelper/src/Dependencies.props | 16 ++++++++-------- nuget.config | 1 - tooling | 2 +- 10 files changed, 43 insertions(+), 44 deletions(-) diff --git a/components/CanvasView/src/Dependencies.props b/components/CanvasView/src/Dependencies.props index b2e69d931..04027d391 100644 --- a/components/CanvasView/src/Dependencies.props +++ b/components/CanvasView/src/Dependencies.props @@ -11,21 +11,21 @@ - + - + - + - + diff --git a/components/DataTable/samples/Dependencies.props b/components/DataTable/samples/Dependencies.props index 2353d5347..83b846be8 100644 --- a/components/DataTable/samples/Dependencies.props +++ b/components/DataTable/samples/Dependencies.props @@ -11,14 +11,14 @@ - - + + - - + + diff --git a/components/DataTable/src/Dependencies.props b/components/DataTable/src/Dependencies.props index 8b66d5b59..eb8a0bf0f 100644 --- a/components/DataTable/src/Dependencies.props +++ b/components/DataTable/src/Dependencies.props @@ -14,15 +14,15 @@ - - - + + + - - - + + + diff --git a/components/RivePlayer/samples/Dependencies.props b/components/RivePlayer/samples/Dependencies.props index 77b7ec0bc..171dc2a6b 100644 --- a/components/RivePlayer/samples/Dependencies.props +++ b/components/RivePlayer/samples/Dependencies.props @@ -12,24 +12,24 @@ - + - + - + - + diff --git a/components/Shimmer/src/Dependencies.props b/components/Shimmer/src/Dependencies.props index 73a92fa58..797e0385c 100644 --- a/components/Shimmer/src/Dependencies.props +++ b/components/Shimmer/src/Dependencies.props @@ -12,24 +12,24 @@ - + - + - + - + diff --git a/components/TokenView/src/Dependencies.props b/components/TokenView/src/Dependencies.props index 28c39e301..3038a47fc 100644 --- a/components/TokenView/src/Dependencies.props +++ b/components/TokenView/src/Dependencies.props @@ -11,25 +11,25 @@ - - + + - - + + - - + + - - + + diff --git a/components/TransitionHelper/samples/Dependencies.props b/components/TransitionHelper/samples/Dependencies.props index bd8b49100..88188fe42 100644 --- a/components/TransitionHelper/samples/Dependencies.props +++ b/components/TransitionHelper/samples/Dependencies.props @@ -11,21 +11,21 @@ - + - + - + - + diff --git a/components/TransitionHelper/src/Dependencies.props b/components/TransitionHelper/src/Dependencies.props index e420d9d80..e5a72eec1 100644 --- a/components/TransitionHelper/src/Dependencies.props +++ b/components/TransitionHelper/src/Dependencies.props @@ -11,25 +11,25 @@ - - + + - - + + - - + + - - + + diff --git a/nuget.config b/nuget.config index d2f2227e8..c5b04e7aa 100644 --- a/nuget.config +++ b/nuget.config @@ -3,7 +3,6 @@ - diff --git a/tooling b/tooling index a58a89ab7..eb7c4426e 160000 --- a/tooling +++ b/tooling @@ -1 +1 @@ -Subproject commit a58a89ab79deb9740e7fa9c3951f803af7260975 +Subproject commit eb7c4426ef1bcaabad255fd6463057b75befad34 From d96cd929849800b3379248b2276a292eeb02a47a Mon Sep 17 00:00:00 2001 From: Arlo Date: Tue, 24 Dec 2024 14:54:08 -0600 Subject: [PATCH 27/33] Update tooling pointer to PR https://github.com/CommunityToolkit/Tooling-Windows-Submodule/pull/241 --- tooling | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling b/tooling index eb7c4426e..74e403ce4 160000 --- a/tooling +++ b/tooling @@ -1 +1 @@ -Subproject commit eb7c4426ef1bcaabad255fd6463057b75befad34 +Subproject commit 74e403ce43898e1f6f716f3f6c3ad170d87e8fd1 From db70025ec1cd9c501fdfe13294f04af12e03ffd1 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 25 Dec 2024 00:29:30 +0100 Subject: [PATCH 28/33] Add trim annotations to 'TokenView' --- .../TokenView/src/TokenView/TokenView.ItemsSource.cs | 7 +++++++ components/TokenView/src/TokenView/TokenView.cs | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/components/TokenView/src/TokenView/TokenView.ItemsSource.cs b/components/TokenView/src/TokenView/TokenView.ItemsSource.cs index 03be63a13..e9faf929b 100644 --- a/components/TokenView/src/TokenView/TokenView.ItemsSource.cs +++ b/components/TokenView/src/TokenView/TokenView.ItemsSource.cs @@ -2,6 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif + namespace CommunityToolkit.Labs.WinUI; public partial class TokenView : ListViewBase @@ -15,6 +19,9 @@ protected override void OnItemsChanged(object e) base.OnItemsChanged(e); } +#if NET8_0_OR_GREATER + [RequiresUnreferencedCode("This method accesses the 'Remove' method of the assigned items source collection in a trim-unsafe way.")] +#endif private void ItemsSource_PropertyChanged(DependencyObject sender, DependencyProperty dp) { // Use reflection to store a 'Remove' method of any possible collection in ItemsSource diff --git a/components/TokenView/src/TokenView/TokenView.cs b/components/TokenView/src/TokenView/TokenView.cs index de2881e83..40b75bd47 100644 --- a/components/TokenView/src/TokenView/TokenView.cs +++ b/components/TokenView/src/TokenView/TokenView.cs @@ -2,6 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#if NET8_0_OR_GREATER +using System.Diagnostics.CodeAnalysis; +#endif + namespace CommunityToolkit.Labs.WinUI; /// @@ -26,6 +30,9 @@ public partial class TokenView : ListViewBase /// /// Creates a new instance of the class. /// +#if NET8_0_OR_GREATER + [RequiresUnreferencedCode("This method accesses the 'Remove' method of the assigned items source collection in a trim-unsafe way.")] +#endif public TokenView() { this.DefaultStyleKey = typeof(TokenView); From 1227d43d91632e991619dc8224f6d60c791463b4 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 25 Dec 2024 00:55:05 +0100 Subject: [PATCH 29/33] Just suppress the trim warning for now --- components/TokenView/src/TokenView/TokenView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/TokenView/src/TokenView/TokenView.cs b/components/TokenView/src/TokenView/TokenView.cs index 40b75bd47..9b94564b7 100644 --- a/components/TokenView/src/TokenView/TokenView.cs +++ b/components/TokenView/src/TokenView/TokenView.cs @@ -31,7 +31,7 @@ public partial class TokenView : ListViewBase /// Creates a new instance of the class. /// #if NET8_0_OR_GREATER - [RequiresUnreferencedCode("This method accesses the 'Remove' method of the assigned items source collection in a trim-unsafe way.")] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "The 'ItemsSource' change handler accesses the 'Remove' method of the collection in a trim-unsafe (we should revisit this later).")] #endif public TokenView() { From f66a707ad5efb293506cc68c8bf760c11bb495d9 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 25 Dec 2024 13:11:45 +0100 Subject: [PATCH 30/33] Update tooling pointer to PR https://github.com/CommunityToolkit/Tooling-Windows-Submodule/pull/242 --- tooling | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling b/tooling index 74e403ce4..ce1cffc50 160000 --- a/tooling +++ b/tooling @@ -1 +1 @@ -Subproject commit 74e403ce43898e1f6f716f3f6c3ad170d87e8fd1 +Subproject commit ce1cffc5002a04089b176c1a5f17d6021aef9d7d From ba37852f2f60ebe4d8a470c75db04447b8c806b0 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 25 Dec 2024 13:13:11 +0100 Subject: [PATCH 31/33] Disable WUX in 'Notifications' package --- .../Notifications/src/CommunityToolkit.Notifications.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/components/Notifications/src/CommunityToolkit.Notifications.csproj b/components/Notifications/src/CommunityToolkit.Notifications.csproj index f0dc09f9b..bc175d9ac 100644 --- a/components/Notifications/src/CommunityToolkit.Notifications.csproj +++ b/components/Notifications/src/CommunityToolkit.Notifications.csproj @@ -13,6 +13,7 @@ CommunityToolkit.Notifications $(PackageIdPrefix).$(ToolkitComponentName) disable + false false From d6c144b3b7d70684d9cb33762bd67714b37bb9f8 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 25 Dec 2024 13:28:39 +0100 Subject: [PATCH 32/33] Update tooling pointer to commit b121eb57cc0fdca03206a9e1a08960d7e3cd824c --- tooling | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tooling b/tooling index ce1cffc50..b121eb57c 160000 --- a/tooling +++ b/tooling @@ -1 +1 @@ -Subproject commit ce1cffc5002a04089b176c1a5f17d6021aef9d7d +Subproject commit b121eb57cc0fdca03206a9e1a08960d7e3cd824c From d2d708beca868d51b2d8c1b9a9ce8dd7bb589da1 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 25 Dec 2024 16:32:01 +0100 Subject: [PATCH 33/33] Switch to file-scoped namespaces --- .../src/Adaptive/AdaptiveGroup.cs | 45 +- .../src/Adaptive/AdaptiveHelper.cs | 57 +- .../src/Adaptive/AdaptiveImage.cs | 137 +- .../src/Adaptive/AdaptiveImageEnums.cs | 101 +- .../src/Adaptive/AdaptiveProgressBar.cs | 87 +- .../src/Adaptive/AdaptiveProgressBarValue.cs | 133 +- .../src/Adaptive/AdaptiveSubgroup.cs | 97 +- .../src/Adaptive/AdaptiveSubgroupEnums.cs | 41 +- .../src/Adaptive/AdaptiveText.cs | 197 +- .../src/Adaptive/AdaptiveTextEnums.cs | 269 +- .../src/Adaptive/BaseImageHelper.cs | 41 +- .../src/Adaptive/BaseTextHelper.cs | 17 +- .../BindableProgressBarValue.cs | 131 +- .../Adaptive/BindableValues/BindableString.cs | 99 +- .../Elements/Element_AdaptiveGroup.cs | 37 +- .../Elements/Element_AdaptiveImage.cs | 117 +- .../Elements/Element_AdaptiveImageEnums.cs | 17 +- .../Elements/Element_AdaptiveProgressBar.cs | 33 +- .../Elements/Element_AdaptiveSubgroup.cs | 85 +- .../Adaptive/Elements/Element_AdaptiveText.cs | 141 +- .../src/Adaptive/IAdaptiveChild.cs | 15 +- .../src/Adaptive/IAdaptiveSubgroupChild.cs | 15 +- .../Notifications/src/Adaptive/IBaseImage.cs | 33 +- .../Notifications/src/Adaptive/IBaseText.cs | 25 +- .../src/Badges/BadgeGlyphContent.cs | 131 +- .../src/Badges/BadgeGlyphValue.cs | 115 +- .../src/Badges/BadgeNumericContent.cs | 117 +- .../src/Common/ArgumentValidator.cs | 29 +- .../Notifications/src/Common/BaseElement.cs | 63 +- .../Notifications/src/Common/EnumFormatter.cs | 71 +- .../src/Common/INotificationContent.cs | 29 +- .../src/Common/LimitedList{T}.cs | 145 +- .../NotificationContentValidationException.cs | 17 +- .../IHaveXmlAdditionalProperties.cs | 17 +- .../Common/Serialization/IHaveXmlChildren.cs | 17 +- .../src/Common/Serialization/IHaveXmlName.cs | 17 +- .../Serialization/IHaveXmlNamedProperties.cs | 21 +- .../src/Common/Serialization/IHaveXmlText.cs | 17 +- .../src/Common/XmlWriterHelper.cs | 117 +- .../TileContentBuilder.SpecialTiles.cs | 236 +- .../src/Tiles/Builder/TileContentBuilder.cs | 801 ++-- .../src/Tiles/Elements/Element_Tile.cs | 17 +- .../src/Tiles/Elements/Element_TileBinding.cs | 227 +- .../src/Tiles/Elements/Element_TileVisual.cs | 61 +- .../src/Tiles/Elements/TileElementsCommon.cs | 25 +- .../Tiles/ITileBindingContentAdaptiveChild.cs | 15 +- .../TileBindingContentContact.cs | 51 +- .../TileBindingContentIconic.cs | 49 +- .../TileBindingContentPeople.cs | 37 +- .../TileBindingContentPhotos.cs | 35 +- .../src/Tiles/TileBackgroundImage.cs | 117 +- .../Notifications/src/Tiles/TileBasicImage.cs | 59 +- .../Notifications/src/Tiles/TileBasicText.cs | 53 +- .../Notifications/src/Tiles/TileBinding.cs | 279 +- .../src/Tiles/TileBindingContentAdaptive.cs | 93 +- .../Notifications/src/Tiles/TileBranding.cs | 49 +- .../Notifications/src/Tiles/TileCommon.cs | 43 +- .../Notifications/src/Tiles/TileContent.cs | 69 +- .../Notifications/src/Tiles/TileImages.cs | 65 +- .../Notifications/src/Tiles/TilePeekImage.cs | 119 +- .../TileSizeToAdaptiveTemplateConverter.cs | 31 +- .../src/Tiles/TileTemplateNameV3.cs | 167 +- .../src/Tiles/TileTextStacking.cs | 33 +- .../Notifications/src/Tiles/TileVisual.cs | 345 +- .../src/Toasts/Builder/CustomizeToast.cs | 49 +- .../Builder/ToastContentBuilder.Actions.cs | 424 +-- .../Builder/ToastContentBuilder.Visuals.cs | 661 ++-- .../src/Toasts/Builder/ToastContentBuilder.cs | 703 ++-- .../Compat/ToastNotificationHistoryCompat.cs | 125 +- .../Compat/ToastNotificationManagerCompat.cs | 53 +- .../src/Toasts/Compat/ToastNotifierCompat.cs | 157 +- .../src/Toasts/Elements/Element_Toast.cs | 209 +- .../Toasts/Elements/Element_ToastAction.cs | 155 +- .../Toasts/Elements/Element_ToastActions.cs | 47 +- .../src/Toasts/Elements/Element_ToastAudio.cs | 55 +- .../Toasts/Elements/Element_ToastBinding.cs | 109 +- .../Toasts/Elements/Element_ToastHeader.cs | 69 +- .../src/Toasts/Elements/Element_ToastImage.cs | 101 +- .../src/Toasts/Elements/Element_ToastInput.cs | 97 +- .../Toasts/Elements/Element_ToastSelection.cs | 37 +- .../src/Toasts/Elements/Element_ToastText.cs | 43 +- .../Toasts/Elements/Element_ToastVisual.cs | 41 +- .../Elements/IElement_ToastActivatable.cs | 13 +- .../Notifications/src/Toasts/IToastActions.cs | 19 +- .../src/Toasts/IToastActivateableBuilder.cs | 143 +- .../src/Toasts/IToastBindingGenericChild.cs | 15 +- .../Notifications/src/Toasts/IToastButton.cs | 29 +- .../Notifications/src/Toasts/IToastInput.cs | 13 +- .../src/Toasts/ToastActionsCustom.cs | 131 +- .../Toasts/ToastActionsSnoozeAndDismiss.cs | 47 +- .../src/Toasts/ToastActivationOptions.cs | 45 +- .../src/Toasts/ToastArguments.cs | 665 ++-- .../Notifications/src/Toasts/ToastAudio.cs | 47 +- .../src/Toasts/ToastBindingGeneric.cs | 145 +- .../src/Toasts/ToastBindingShoulderTap.cs | 83 +- .../Notifications/src/Toasts/ToastButton.cs | 705 ++-- .../src/Toasts/ToastButtonDismiss.cs | 93 +- .../src/Toasts/ToastButtonSnooze.cs | 113 +- .../Notifications/src/Toasts/ToastCommon.cs | 57 +- .../Notifications/src/Toasts/ToastContent.cs | 307 +- .../src/Toasts/ToastContextMenuItem.cs | 109 +- .../src/Toasts/ToastGenericAppLogo.cs | 95 +- .../src/Toasts/ToastGenericAppLogoEnums.cs | 33 +- .../src/Toasts/ToastGenericAttributionText.cs | 57 +- .../src/Toasts/ToastGenericHeroImage.cs | 77 +- .../Notifications/src/Toasts/ToastHeader.cs | 163 +- .../Notifications/src/Toasts/ToastPeople.cs | 83 +- .../src/Toasts/ToastSelectionBox.cs | 85 +- .../src/Toasts/ToastSelectionBoxItem.cs | 57 +- .../src/Toasts/ToastShoulderTapImage.cs | 81 +- .../src/Toasts/ToastSpriteSheet.cs | 73 +- .../Notifications/src/Toasts/ToastTextBox.cs | 85 +- .../Notifications/src/Toasts/ToastVisual.cs | 87 +- .../Notifications/tests/TestAssertHelper.cs | 639 ++-- components/Notifications/tests/TestMail.cs | 237 +- .../tests/TestTileContentBuilder.cs | 185 +- .../Notifications/tests/TestToastArguments.cs | 741 ++-- .../tests/TestToastContentBuilder.cs | 2099 ++++++----- components/Notifications/tests/TestWeather.cs | 417 ++- .../Notifications/tests/Test_Adaptive_Xml.cs | 903 +++-- .../Notifications/tests/Test_Badge_Xml.cs | 103 +- .../Notifications/tests/Test_Tile_Xml.cs | 2691 +++++++------- .../Notifications/tests/Test_Toast_Xml.cs | 3225 ++++++++--------- .../Notifications/tests/TextXboxModern.cs | 207 +- 124 files changed, 12092 insertions(+), 12214 deletions(-) diff --git a/components/Notifications/src/Adaptive/AdaptiveGroup.cs b/components/Notifications/src/Adaptive/AdaptiveGroup.cs index e4f6310cc..889019282 100644 --- a/components/Notifications/src/Adaptive/AdaptiveGroup.cs +++ b/components/Notifications/src/Adaptive/AdaptiveGroup.cs @@ -6,36 +6,35 @@ using System.Collections.Generic; using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Groups semantically identify that the content in the group must either be displayed as a whole, or not displayed if it cannot fit. Groups also allow creating multiple columns. Supported on Tiles since RTM. Supported on Toasts since Anniversary Update. +/// +public sealed class AdaptiveGroup : ITileBindingContentAdaptiveChild, IAdaptiveChild, IToastBindingGenericChild { /// - /// Groups semantically identify that the content in the group must either be displayed as a whole, or not displayed if it cannot fit. Groups also allow creating multiple columns. Supported on Tiles since RTM. Supported on Toasts since Anniversary Update. + /// Gets the only valid children of groups are . + /// Each subgroup is displayed as a separate vertical column. Note that you must + /// include at least one subgroup in your group, otherwise an + /// will be thrown when you try to retrieve the XML for the notification. /// - public sealed class AdaptiveGroup : ITileBindingContentAdaptiveChild, IAdaptiveChild, IToastBindingGenericChild - { - /// - /// Gets the only valid children of groups are . - /// Each subgroup is displayed as a separate vertical column. Note that you must - /// include at least one subgroup in your group, otherwise an - /// will be thrown when you try to retrieve the XML for the notification. - /// - public IList Children { get; private set; } = new List(); + public IList Children { get; private set; } = new List(); - internal Element_AdaptiveGroup ConvertToElement() + internal Element_AdaptiveGroup ConvertToElement() + { + if (Children.Count == 0) { - if (Children.Count == 0) - { - throw new InvalidOperationException("Groups must have at least one child subgroup. The Children property had zero items in it."); - } - - Element_AdaptiveGroup group = new Element_AdaptiveGroup(); + throw new InvalidOperationException("Groups must have at least one child subgroup. The Children property had zero items in it."); + } - foreach (var subgroup in Children) - { - group.Children.Add(subgroup.ConvertToElement()); - } + Element_AdaptiveGroup group = new Element_AdaptiveGroup(); - return group; + foreach (var subgroup in Children) + { + group.Children.Add(subgroup.ConvertToElement()); } + + return group; } } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/AdaptiveHelper.cs b/components/Notifications/src/Adaptive/AdaptiveHelper.cs index 67b4db649..03d8f26a0 100644 --- a/components/Notifications/src/Adaptive/AdaptiveHelper.cs +++ b/components/Notifications/src/Adaptive/AdaptiveHelper.cs @@ -4,38 +4,37 @@ using System; -namespace CommunityToolkit.Notifications.Adaptive +namespace CommunityToolkit.Notifications.Adaptive; + +internal static class AdaptiveHelper { - internal static class AdaptiveHelper + internal static object ConvertToElement(object obj) { - internal static object ConvertToElement(object obj) + if (obj is AdaptiveText) + { + return (obj as AdaptiveText).ConvertToElement(); + } + + if (obj is AdaptiveImage) + { + return (obj as AdaptiveImage).ConvertToElement(); + } + + if (obj is AdaptiveGroup) { - if (obj is AdaptiveText) - { - return (obj as AdaptiveText).ConvertToElement(); - } - - if (obj is AdaptiveImage) - { - return (obj as AdaptiveImage).ConvertToElement(); - } - - if (obj is AdaptiveGroup) - { - return (obj as AdaptiveGroup).ConvertToElement(); - } - - if (obj is AdaptiveSubgroup) - { - return (obj as AdaptiveSubgroup).ConvertToElement(); - } - - if (obj is AdaptiveProgressBar) - { - return (obj as AdaptiveProgressBar).ConvertToElement(); - } - - throw new NotImplementedException("Unknown object: " + obj.GetType()); + return (obj as AdaptiveGroup).ConvertToElement(); } + + if (obj is AdaptiveSubgroup) + { + return (obj as AdaptiveSubgroup).ConvertToElement(); + } + + if (obj is AdaptiveProgressBar) + { + return (obj as AdaptiveProgressBar).ConvertToElement(); + } + + throw new NotImplementedException("Unknown object: " + obj.GetType()); } } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/AdaptiveImage.cs b/components/Notifications/src/Adaptive/AdaptiveImage.cs index 2a5a756f2..7d8687ffb 100644 --- a/components/Notifications/src/Adaptive/AdaptiveImage.cs +++ b/components/Notifications/src/Adaptive/AdaptiveImage.cs @@ -4,89 +4,88 @@ using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// An inline image. +/// +public sealed class AdaptiveImage + : IBaseImage, + IToastBindingGenericChild, + ITileBindingContentAdaptiveChild, + IAdaptiveChild, + IAdaptiveSubgroupChild { /// - /// An inline image. + /// Gets or sets the desired cropping of the image. + /// Supported on Tiles since RTM. Supported on Toast since Anniversary Update. /// - public sealed class AdaptiveImage - : IBaseImage, - IToastBindingGenericChild, - ITileBindingContentAdaptiveChild, - IAdaptiveChild, - IAdaptiveSubgroupChild - { - /// - /// Gets or sets the desired cropping of the image. - /// Supported on Tiles since RTM. Supported on Toast since Anniversary Update. - /// - public AdaptiveImageCrop HintCrop { get; set; } + public AdaptiveImageCrop HintCrop { get; set; } - /// - /// Gets or sets a value whether a margin is removed. images have an 8px margin around them. - /// You can remove this margin by setting this property to true. - /// Supported on Tiles since RTM. Supported on Toast since Anniversary Update. - /// - public bool? HintRemoveMargin { get; set; } + /// + /// Gets or sets a value whether a margin is removed. images have an 8px margin around them. + /// You can remove this margin by setting this property to true. + /// Supported on Tiles since RTM. Supported on Toast since Anniversary Update. + /// + public bool? HintRemoveMargin { get; set; } - /// - /// Gets or sets the horizontal alignment of the image. - /// For Toast, this is only supported when inside an . - /// - public AdaptiveImageAlign HintAlign { get; set; } + /// + /// Gets or sets the horizontal alignment of the image. + /// For Toast, this is only supported when inside an . + /// + public AdaptiveImageAlign HintAlign { get; set; } - private string _source; + private string _source; - /// - /// Gets or sets the URI of the image (Required). - /// Can be from your application package, application data, or the internet. - /// Internet images must be less than 200 KB in size. - /// - public string Source - { - get { return _source; } - set { BaseImageHelper.SetSource(ref _source, value); } - } + /// + /// Gets or sets the URI of the image (Required). + /// Can be from your application package, application data, or the internet. + /// Internet images must be less than 200 KB in size. + /// + public string Source + { + get { return _source; } + set { BaseImageHelper.SetSource(ref _source, value); } + } - /// - /// Gets or sets a description of the image, for users of assistive technologies. - /// - public string AlternateText { get; set; } + /// + /// Gets or sets a description of the image, for users of assistive technologies. + /// + public string AlternateText { get; set; } - /// - /// Gets or sets set to true to allow Windows to append a query string to the image URI - /// supplied in the Tile notification. Use this attribute if your server hosts - /// images and can handle query strings, either by retrieving an image variant based - /// on the query strings or by ignoring the query string and returning the image - /// as specified without the query string. This query string specifies scale, - /// contrast setting, and language. - /// - public bool? AddImageQuery { get; set; } + /// + /// Gets or sets set to true to allow Windows to append a query string to the image URI + /// supplied in the Tile notification. Use this attribute if your server hosts + /// images and can handle query strings, either by retrieving an image variant based + /// on the query strings or by ignoring the query string and returning the image + /// as specified without the query string. This query string specifies scale, + /// contrast setting, and language. + /// + public bool? AddImageQuery { get; set; } - /// - /// Returns the image's source string. - /// - /// The image's source string. - public override string ToString() + /// + /// Returns the image's source string. + /// + /// The image's source string. + public override string ToString() + { + if (Source == null) { - if (Source == null) - { - return "Source is null"; - } - - return Source; + return "Source is null"; } - internal Element_AdaptiveImage ConvertToElement() - { - Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this); + return Source; + } - image.Crop = HintCrop; - image.RemoveMargin = HintRemoveMargin; - image.Align = HintAlign; - image.Placement = AdaptiveImagePlacement.Inline; + internal Element_AdaptiveImage ConvertToElement() + { + Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this); - return image; - } + image.Crop = HintCrop; + image.RemoveMargin = HintRemoveMargin; + image.Align = HintAlign; + image.Placement = AdaptiveImagePlacement.Inline; + + return image; } } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/AdaptiveImageEnums.cs b/components/Notifications/src/Adaptive/AdaptiveImageEnums.cs index 498471c97..2e2f44d14 100644 --- a/components/Notifications/src/Adaptive/AdaptiveImageEnums.cs +++ b/components/Notifications/src/Adaptive/AdaptiveImageEnums.cs @@ -2,57 +2,56 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Specifies the horizontal alignment for an image. +/// +public enum AdaptiveImageAlign +{ + /// + /// Default value, alignment behavior determined by renderer. + /// + Default, + + /// + /// Image stretches to fill available width (and potentially available height too, depending on where the image is). + /// + Stretch, + + /// + /// Align the image to the left, displaying the image at its native resolution. + /// + Left, + + /// + /// Align the image in the center horizontally, displaying the image at its native resolution. + /// + Center, + + /// + /// Align the image to the right, displaying the image at its native resolution. + /// + Right +} + +/// +/// Specify the desired cropping of the image. +/// +public enum AdaptiveImageCrop { /// - /// Specifies the horizontal alignment for an image. - /// - public enum AdaptiveImageAlign - { - /// - /// Default value, alignment behavior determined by renderer. - /// - Default, - - /// - /// Image stretches to fill available width (and potentially available height too, depending on where the image is). - /// - Stretch, - - /// - /// Align the image to the left, displaying the image at its native resolution. - /// - Left, - - /// - /// Align the image in the center horizontally, displaying the image at its native resolution. - /// - Center, - - /// - /// Align the image to the right, displaying the image at its native resolution. - /// - Right - } - - /// - /// Specify the desired cropping of the image. - /// - public enum AdaptiveImageCrop - { - /// - /// Default value, cropping behavior determined by renderer. - /// - Default, - - /// - /// Image is not cropped. - /// - None, - - /// - /// Image is cropped to a circle shape. - /// - Circle - } + /// Default value, cropping behavior determined by renderer. + /// + Default, + + /// + /// Image is not cropped. + /// + None, + + /// + /// Image is cropped to a circle shape. + /// + Circle } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/AdaptiveProgressBar.cs b/components/Notifications/src/Adaptive/AdaptiveProgressBar.cs index 7f39bbceb..bb1e174f8 100644 --- a/components/Notifications/src/Adaptive/AdaptiveProgressBar.cs +++ b/components/Notifications/src/Adaptive/AdaptiveProgressBar.cs @@ -9,55 +9,54 @@ using BindableProgressBarValue = CommunityToolkit.Notifications.BindableProgressBarValue; using BindableString = CommunityToolkit.Notifications.BindableString; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// New in Creators Update: A progress bar. Only supported on toasts on Desktop, build 15007 or newer. +/// +public sealed class AdaptiveProgressBar : IToastBindingGenericChild { /// - /// New in Creators Update: A progress bar. Only supported on toasts on Desktop, build 15007 or newer. + /// Gets or sets an optional title string. Supports data binding. /// - public sealed class AdaptiveProgressBar : IToastBindingGenericChild + public BindableString Title { get; set; } + + /// + /// Gets or sets the value of the progress bar. Supports data binding. Defaults to 0. + /// + public BindableProgressBarValue Value { get; set; } = AdaptiveProgressBarValue.FromValue(0); + + /// + /// Gets or sets an optional string to be displayed instead of the default percentage string. If this isn't provided, something like "70%" will be displayed. + /// + public BindableString ValueStringOverride { get; set; } + + /// + /// Gets or sets a status string (Required), which is displayed underneath the progress bar. This string should reflect the status of the operation, like "Downloading..." or "Installing..." + /// + public BindableString Status { get; set; } + + internal Element_AdaptiveProgressBar ConvertToElement() { - /// - /// Gets or sets an optional title string. Supports data binding. - /// - public BindableString Title { get; set; } - - /// - /// Gets or sets the value of the progress bar. Supports data binding. Defaults to 0. - /// - public BindableProgressBarValue Value { get; set; } = AdaptiveProgressBarValue.FromValue(0); - - /// - /// Gets or sets an optional string to be displayed instead of the default percentage string. If this isn't provided, something like "70%" will be displayed. - /// - public BindableString ValueStringOverride { get; set; } - - /// - /// Gets or sets a status string (Required), which is displayed underneath the progress bar. This string should reflect the status of the operation, like "Downloading..." or "Installing..." - /// - public BindableString Status { get; set; } - - internal Element_AdaptiveProgressBar ConvertToElement() + // If Value not provided, we use 0 + var val = Value; + if (val == null) + { + val = AdaptiveProgressBarValue.FromValue(0); + } + + var answer = new Element_AdaptiveProgressBar(); + + answer.Title = Title?.ToXmlString(); + answer.Value = val.ToXmlString(); + answer.ValueStringOverride = ValueStringOverride?.ToXmlString(); + answer.Status = Status?.ToXmlString(); + + if (answer.Status == null) { - // If Value not provided, we use 0 - var val = Value; - if (val == null) - { - val = AdaptiveProgressBarValue.FromValue(0); - } - - var answer = new Element_AdaptiveProgressBar(); - - answer.Title = Title?.ToXmlString(); - answer.Value = val.ToXmlString(); - answer.ValueStringOverride = ValueStringOverride?.ToXmlString(); - answer.Status = Status?.ToXmlString(); - - if (answer.Status == null) - { - throw new NullReferenceException("Status property is required."); - } - - return answer; + throw new NullReferenceException("Status property is required."); } + + return answer; } } diff --git a/components/Notifications/src/Adaptive/AdaptiveProgressBarValue.cs b/components/Notifications/src/Adaptive/AdaptiveProgressBarValue.cs index a6e6880cd..9390bcef3 100644 --- a/components/Notifications/src/Adaptive/AdaptiveProgressBarValue.cs +++ b/components/Notifications/src/Adaptive/AdaptiveProgressBarValue.cs @@ -4,93 +4,92 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A class that represents the progress bar's value. +/// +public sealed class AdaptiveProgressBarValue { /// - /// A class that represents the progress bar's value. + /// Gets or sets the property name to bind to. /// - public sealed class AdaptiveProgressBarValue - { - /// - /// Gets or sets the property name to bind to. - /// - public string BindingName { get; set; } + public string BindingName { get; set; } - /// - /// Gets or sets the value (0-1) representing the percent complete. - /// - public double Value { get; set; } + /// + /// Gets or sets the value (0-1) representing the percent complete. + /// + public double Value { get; set; } - /// - /// Gets or sets a value indicating whether the progress bar is indeterminate. - /// - public bool IsIndeterminate { get; set; } + /// + /// Gets or sets a value indicating whether the progress bar is indeterminate. + /// + public bool IsIndeterminate { get; set; } - /// - /// Initializes a new instance of the class. - /// - private AdaptiveProgressBarValue() - { - } + /// + /// Initializes a new instance of the class. + /// + private AdaptiveProgressBarValue() + { + } - internal string ToXmlString() + internal string ToXmlString() + { + if (IsIndeterminate) { - if (IsIndeterminate) - { - return "indeterminate"; - } - - if (BindingName != null) - { - return "{" + BindingName + "}"; - } - - return Value.ToString(); + return "indeterminate"; } - /// - /// Gets an indeterminate progress bar value. - /// - public static AdaptiveProgressBarValue Indeterminate + if (BindingName != null) { - get - { - return new AdaptiveProgressBarValue() - { - IsIndeterminate = true - }; - } + return "{" + BindingName + "}"; } - /// - /// Returns a progress bar value using the specified value (0-1) representing the percent complete. - /// - /// The value, 0-1, inclusive. - /// A progress bar value. - public static AdaptiveProgressBarValue FromValue(double d) - { - if (d < 0 || d > 1) - { - throw new ArgumentOutOfRangeException("d", "Value must be between 0 and 1, inclusive."); - } + return Value.ToString(); + } + /// + /// Gets an indeterminate progress bar value. + /// + public static AdaptiveProgressBarValue Indeterminate + { + get + { return new AdaptiveProgressBarValue() { - Value = d + IsIndeterminate = true }; } + } - /// - /// Returns a progress bar value using the specified binding name. - /// - /// The property to bind to. - /// A progress bar value. - public static AdaptiveProgressBarValue FromBinding(string bindingName) + /// + /// Returns a progress bar value using the specified value (0-1) representing the percent complete. + /// + /// The value, 0-1, inclusive. + /// A progress bar value. + public static AdaptiveProgressBarValue FromValue(double d) + { + if (d < 0 || d > 1) { - return new AdaptiveProgressBarValue() - { - BindingName = bindingName - }; + throw new ArgumentOutOfRangeException("d", "Value must be between 0 and 1, inclusive."); } + + return new AdaptiveProgressBarValue() + { + Value = d + }; + } + + /// + /// Returns a progress bar value using the specified binding name. + /// + /// The property to bind to. + /// A progress bar value. + public static AdaptiveProgressBarValue FromBinding(string bindingName) + { + return new AdaptiveProgressBarValue() + { + BindingName = bindingName + }; } } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/AdaptiveSubgroup.cs b/components/Notifications/src/Adaptive/AdaptiveSubgroup.cs index 9a136c843..7db375bb6 100644 --- a/components/Notifications/src/Adaptive/AdaptiveSubgroup.cs +++ b/components/Notifications/src/Adaptive/AdaptiveSubgroup.cs @@ -6,72 +6,71 @@ using System.Collections.Generic; using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Subgroups are vertical columns that can contain text and images. Supported on Tiles since RTM. Supported on Toasts since Anniversary Update. +/// +public sealed class AdaptiveSubgroup { /// - /// Subgroups are vertical columns that can contain text and images. Supported on Tiles since RTM. Supported on Toasts since Anniversary Update. + /// Gets a list of Children. and are valid children of subgroups. /// - public sealed class AdaptiveSubgroup - { - /// - /// Gets a list of Children. and are valid children of subgroups. - /// - public IList Children { get; private set; } = new List(); + public IList Children { get; private set; } = new List(); - private int? _hintWeight; + private int? _hintWeight; - /// - /// Gets or sets the width of this subgroup column by specifying the weight, relative to the other subgroups. - /// - public int? HintWeight + /// + /// Gets or sets the width of this subgroup column by specifying the weight, relative to the other subgroups. + /// + public int? HintWeight + { + get { - get - { - return _hintWeight; - } + return _hintWeight; + } - set - { - Element_AdaptiveSubgroup.CheckWeight(value); + set + { + Element_AdaptiveSubgroup.CheckWeight(value); - _hintWeight = value; - } + _hintWeight = value; } + } + + /// + /// Gets or sets the vertical alignment of this subgroup's content. + /// + public AdaptiveSubgroupTextStacking HintTextStacking { get; set; } = Element_AdaptiveSubgroup.DEFAULT_TEXT_STACKING; - /// - /// Gets or sets the vertical alignment of this subgroup's content. - /// - public AdaptiveSubgroupTextStacking HintTextStacking { get; set; } = Element_AdaptiveSubgroup.DEFAULT_TEXT_STACKING; + internal Element_AdaptiveSubgroup ConvertToElement() + { + var subgroup = new Element_AdaptiveSubgroup() + { + Weight = HintWeight, + TextStacking = HintTextStacking + }; - internal Element_AdaptiveSubgroup ConvertToElement() + foreach (var child in Children) { - var subgroup = new Element_AdaptiveSubgroup() - { - Weight = HintWeight, - TextStacking = HintTextStacking - }; + subgroup.Children.Add(ConvertToSubgroupChildElement(child)); + } - foreach (var child in Children) - { - subgroup.Children.Add(ConvertToSubgroupChildElement(child)); - } + return subgroup; + } - return subgroup; + private static IElement_AdaptiveSubgroupChild ConvertToSubgroupChildElement(IAdaptiveSubgroupChild child) + { + if (child is AdaptiveText) + { + return (child as AdaptiveText).ConvertToElement(); } - private static IElement_AdaptiveSubgroupChild ConvertToSubgroupChildElement(IAdaptiveSubgroupChild child) + if (child is AdaptiveImage) { - if (child is AdaptiveText) - { - return (child as AdaptiveText).ConvertToElement(); - } - - if (child is AdaptiveImage) - { - return (child as AdaptiveImage).ConvertToElement(); - } - - throw new NotImplementedException("Unknown child: " + child.GetType()); + return (child as AdaptiveImage).ConvertToElement(); } + + throw new NotImplementedException("Unknown child: " + child.GetType()); } } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/AdaptiveSubgroupEnums.cs b/components/Notifications/src/Adaptive/AdaptiveSubgroupEnums.cs index ce41b799c..d4d603b82 100644 --- a/components/Notifications/src/Adaptive/AdaptiveSubgroupEnums.cs +++ b/components/Notifications/src/Adaptive/AdaptiveSubgroupEnums.cs @@ -2,31 +2,30 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// TextStacking specifies the vertical alignment of content. +/// +public enum AdaptiveSubgroupTextStacking { /// - /// TextStacking specifies the vertical alignment of content. + /// Renderer automatically selects the default vertical alignment. /// - public enum AdaptiveSubgroupTextStacking - { - /// - /// Renderer automatically selects the default vertical alignment. - /// - Default, + Default, - /// - /// Vertical align to the top. - /// - Top, + /// + /// Vertical align to the top. + /// + Top, - /// - /// Vertical align to the center. - /// - Center, + /// + /// Vertical align to the center. + /// + Center, - /// - /// Vertical align to the bottom. - /// - Bottom - } + /// + /// Vertical align to the bottom. + /// + Bottom } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/AdaptiveText.cs b/components/Notifications/src/Adaptive/AdaptiveText.cs index 68775c9c0..6aa4df70b 100644 --- a/components/Notifications/src/Adaptive/AdaptiveText.cs +++ b/components/Notifications/src/Adaptive/AdaptiveText.cs @@ -8,126 +8,125 @@ using CommunityToolkit.Notifications.Adaptive.Elements; using BindableString = CommunityToolkit.Notifications.BindableString; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// An adaptive text element. +/// +public sealed class AdaptiveText + : IAdaptiveChild, + IAdaptiveSubgroupChild, + ITileBindingContentAdaptiveChild, + IToastBindingGenericChild { /// - /// An adaptive text element. + /// Gets or sets the text to display. Data binding support added in Creators Update, + /// only works for toast top-level text elements. /// - public sealed class AdaptiveText - : IAdaptiveChild, - IAdaptiveSubgroupChild, - ITileBindingContentAdaptiveChild, - IToastBindingGenericChild + public BindableString Text { get; set; } + + /// + /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags + /// such as "en-US" or "fr-FR". The locale specified here overrides any other specified + /// locale, such as that in binding or visual. If this value is a literal string, + /// this attribute defaults to the user's UI language. If this value is a string reference, + /// this attribute defaults to the locale chosen by Windows Runtime in resolving the string. + /// + public string Language { get; set; } + + /// + /// Gets or sets the style that controls the text's font size, weight, and opacity. + /// Note that for Toast, the style will only take effect if the text is inside an . + /// + public AdaptiveTextStyle HintStyle { get; set; } + + /// + /// Gets or sets a value whether text wrapping is enabled. For Tiles, this is false by default. + /// For Toasts, this is true on top-level text elements, and false inside an . + /// Note that for Toast, setting wrap will only take effect if the text is inside an + /// (you can use HintMaxLines = 1 to prevent top-level text elements from wrapping). + /// + public bool? HintWrap { get; set; } + + private int? _hintMaxLines; + + /// + /// Gets or sets the maximum number of lines the text element is allowed to display. + /// For Tiles, this is infinity by default. For Toasts, top-level text elements will + /// have varying max line amounts (and in the Anniversary Update you can change the max lines). + /// Text on a Toast inside an will behave identically to Tiles (default to infinity). + /// + public int? HintMaxLines { - /// - /// Gets or sets the text to display. Data binding support added in Creators Update, - /// only works for toast top-level text elements. - /// - public BindableString Text { get; set; } - - /// - /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags - /// such as "en-US" or "fr-FR". The locale specified here overrides any other specified - /// locale, such as that in binding or visual. If this value is a literal string, - /// this attribute defaults to the user's UI language. If this value is a string reference, - /// this attribute defaults to the locale chosen by Windows Runtime in resolving the string. - /// - public string Language { get; set; } - - /// - /// Gets or sets the style that controls the text's font size, weight, and opacity. - /// Note that for Toast, the style will only take effect if the text is inside an . - /// - public AdaptiveTextStyle HintStyle { get; set; } - - /// - /// Gets or sets a value whether text wrapping is enabled. For Tiles, this is false by default. - /// For Toasts, this is true on top-level text elements, and false inside an . - /// Note that for Toast, setting wrap will only take effect if the text is inside an - /// (you can use HintMaxLines = 1 to prevent top-level text elements from wrapping). - /// - public bool? HintWrap { get; set; } - - private int? _hintMaxLines; - - /// - /// Gets or sets the maximum number of lines the text element is allowed to display. - /// For Tiles, this is infinity by default. For Toasts, top-level text elements will - /// have varying max line amounts (and in the Anniversary Update you can change the max lines). - /// Text on a Toast inside an will behave identically to Tiles (default to infinity). - /// - public int? HintMaxLines + get { - get - { - return _hintMaxLines; - } + return _hintMaxLines; + } - set + set + { + if (value != null) { - if (value != null) - { - Element_AdaptiveText.CheckMaxLinesValue(value.Value); - } - - _hintMaxLines = value; + Element_AdaptiveText.CheckMaxLinesValue(value.Value); } + + _hintMaxLines = value; } + } - private int? _hintMinLines; + private int? _hintMinLines; - /// - /// Gets or sets the minimum number of lines the text element must display. - /// Note that for Toast, this property will only take effect if the text is inside an . - /// - public int? HintMinLines + /// + /// Gets or sets the minimum number of lines the text element must display. + /// Note that for Toast, this property will only take effect if the text is inside an . + /// + public int? HintMinLines + { + get { - get - { - return _hintMinLines; - } + return _hintMinLines; + } - set + set + { + if (value != null) { - if (value != null) - { - Element_AdaptiveText.CheckMinLinesValue(value.Value); - } - - _hintMinLines = value; + Element_AdaptiveText.CheckMinLinesValue(value.Value); } + + _hintMinLines = value; } + } - /// - /// Gets or sets the horizontal alignment of the text. Note that for Toast, this property will - /// only take effect if the text is inside an . - /// - public AdaptiveTextAlign HintAlign { get; set; } + /// + /// Gets or sets the horizontal alignment of the text. Note that for Toast, this property will + /// only take effect if the text is inside an . + /// + public AdaptiveTextAlign HintAlign { get; set; } - internal Element_AdaptiveText ConvertToElement() + internal Element_AdaptiveText ConvertToElement() + { + var answer = new Element_AdaptiveText() { - var answer = new Element_AdaptiveText() - { - Lang = Language, - Style = HintStyle, - Wrap = HintWrap, - MaxLines = HintMaxLines, - MinLines = HintMinLines, - Align = HintAlign - }; + Lang = Language, + Style = HintStyle, + Wrap = HintWrap, + MaxLines = HintMaxLines, + MinLines = HintMinLines, + Align = HintAlign + }; - answer.Text = Text?.ToXmlString(); + answer.Text = Text?.ToXmlString(); - return answer; - } + return answer; + } - /// - /// Returns the value of the Text property. - /// - /// The value of the Text property. - public override string ToString() - { - return Text; - } + /// + /// Returns the value of the Text property. + /// + /// The value of the Text property. + public override string ToString() + { + return Text; } } diff --git a/components/Notifications/src/Adaptive/AdaptiveTextEnums.cs b/components/Notifications/src/Adaptive/AdaptiveTextEnums.cs index 60eb0d72e..4634f925f 100644 --- a/components/Notifications/src/Adaptive/AdaptiveTextEnums.cs +++ b/components/Notifications/src/Adaptive/AdaptiveTextEnums.cs @@ -2,141 +2,140 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Text style controls font size, weight, and opacity. +/// +public enum AdaptiveTextStyle { /// - /// Text style controls font size, weight, and opacity. - /// - public enum AdaptiveTextStyle - { - /// - /// Style is determined by the renderer. - /// - Default, - - /// - /// Default value. Paragraph font size, normal weight and opacity. - /// - Caption, - - /// - /// Same as Caption but with subtle opacity. - /// - CaptionSubtle, - - /// - /// H5 font size. - /// - Body, - - /// - /// Same as Body but with subtle opacity. - /// - BodySubtle, - - /// - /// H5 font size, bold weight. Essentially the bold version of Body. - /// - Base, - - /// - /// Same as Base but with subtle opacity. - /// - BaseSubtle, - - /// - /// H4 font size. - /// - Subtitle, - - /// - /// Same as Subtitle but with subtle opacity. - /// - SubtitleSubtle, - - /// - /// H3 font size. - /// - Title, - - /// - /// Same as Title but with subtle opacity. - /// - TitleSubtle, - - /// - /// Same as Title but with top/bottom padding removed. - /// - TitleNumeral, - - /// - /// H2 font size. - /// - Subheader, - - /// - /// Same as Subheader but with subtle opacity. - /// - SubheaderSubtle, - - /// - /// Same as Subheader but with top/bottom padding removed. - /// - SubheaderNumeral, - - /// - /// H1 font size. - /// - Header, - - /// - /// Same as Header but with subtle opacity. - /// - HeaderSubtle, - - /// - /// Same as Header but with top/bottom padding removed. - /// - HeaderNumeral - } - - /// - /// Controls the horizontal alignment of text. - /// - public enum AdaptiveTextAlign - { - /// - /// Alignment is automatically determined by - /// - Default, - - /// - /// The system automatically decides the alignment based on the language and culture. - /// - Auto, - - /// - /// Horizontally align the text to the left. - /// - Left, - - /// - /// Horizontally align the text in the center. - /// - Center, - - /// - /// Horizontally align the text to the right. - /// - Right - } - - internal enum AdaptiveTextPlacement - { - /// - /// Default value - /// - Inline, - Attribution - } + /// Style is determined by the renderer. + /// + Default, + + /// + /// Default value. Paragraph font size, normal weight and opacity. + /// + Caption, + + /// + /// Same as Caption but with subtle opacity. + /// + CaptionSubtle, + + /// + /// H5 font size. + /// + Body, + + /// + /// Same as Body but with subtle opacity. + /// + BodySubtle, + + /// + /// H5 font size, bold weight. Essentially the bold version of Body. + /// + Base, + + /// + /// Same as Base but with subtle opacity. + /// + BaseSubtle, + + /// + /// H4 font size. + /// + Subtitle, + + /// + /// Same as Subtitle but with subtle opacity. + /// + SubtitleSubtle, + + /// + /// H3 font size. + /// + Title, + + /// + /// Same as Title but with subtle opacity. + /// + TitleSubtle, + + /// + /// Same as Title but with top/bottom padding removed. + /// + TitleNumeral, + + /// + /// H2 font size. + /// + Subheader, + + /// + /// Same as Subheader but with subtle opacity. + /// + SubheaderSubtle, + + /// + /// Same as Subheader but with top/bottom padding removed. + /// + SubheaderNumeral, + + /// + /// H1 font size. + /// + Header, + + /// + /// Same as Header but with subtle opacity. + /// + HeaderSubtle, + + /// + /// Same as Header but with top/bottom padding removed. + /// + HeaderNumeral +} + +/// +/// Controls the horizontal alignment of text. +/// +public enum AdaptiveTextAlign +{ + /// + /// Alignment is automatically determined by + /// + Default, + + /// + /// The system automatically decides the alignment based on the language and culture. + /// + Auto, + + /// + /// Horizontally align the text to the left. + /// + Left, + + /// + /// Horizontally align the text in the center. + /// + Center, + + /// + /// Horizontally align the text to the right. + /// + Right +} + +internal enum AdaptiveTextPlacement +{ + /// + /// Default value + /// + Inline, + Attribution } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/BaseImageHelper.cs b/components/Notifications/src/Adaptive/BaseImageHelper.cs index 778aedbb1..a12e8a248 100644 --- a/components/Notifications/src/Adaptive/BaseImageHelper.cs +++ b/components/Notifications/src/Adaptive/BaseImageHelper.cs @@ -5,33 +5,32 @@ using System; using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal static class BaseImageHelper { - internal static class BaseImageHelper + internal static void SetSource(ref string destination, string value) { - internal static void SetSource(ref string destination, string value) + if (value == null) { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - destination = value; + throw new ArgumentNullException(nameof(value)); } - internal static Element_AdaptiveImage CreateBaseElement(IBaseImage current) - { - if (current.Source == null) - { - throw new NullReferenceException("Source property is required."); - } + destination = value; + } - return new Element_AdaptiveImage() - { - Src = current.Source, - Alt = current.AlternateText, - AddImageQuery = current.AddImageQuery - }; + internal static Element_AdaptiveImage CreateBaseElement(IBaseImage current) + { + if (current.Source == null) + { + throw new NullReferenceException("Source property is required."); } + + return new Element_AdaptiveImage() + { + Src = current.Source, + Alt = current.AlternateText, + AddImageQuery = current.AddImageQuery + }; } } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/BaseTextHelper.cs b/components/Notifications/src/Adaptive/BaseTextHelper.cs index a65f43d93..64ef2ca90 100644 --- a/components/Notifications/src/Adaptive/BaseTextHelper.cs +++ b/components/Notifications/src/Adaptive/BaseTextHelper.cs @@ -4,17 +4,16 @@ using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal class BaseTextHelper { - internal class BaseTextHelper + internal static Element_AdaptiveText CreateBaseElement(IBaseText current) { - internal static Element_AdaptiveText CreateBaseElement(IBaseText current) + return new Element_AdaptiveText() { - return new Element_AdaptiveText() - { - Text = current.Text, - Lang = current.Language - }; - } + Text = current.Text, + Lang = current.Language + }; } } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/BindableValues/BindableProgressBarValue.cs b/components/Notifications/src/Adaptive/BindableValues/BindableProgressBarValue.cs index 1e84cb3f9..895368950 100644 --- a/components/Notifications/src/Adaptive/BindableValues/BindableProgressBarValue.cs +++ b/components/Notifications/src/Adaptive/BindableValues/BindableProgressBarValue.cs @@ -2,87 +2,86 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A binding value for doubles. +/// +public sealed class BindableProgressBarValue { /// - /// A binding value for doubles. + /// Gets raw value used for the implicit converter case, where dev provided a raw double. We store the raw value, + /// so that later on when generating the XML, we can provide this value rather than binding syntax. /// - public sealed class BindableProgressBarValue - { - /// - /// Gets raw value used for the implicit converter case, where dev provided a raw double. We store the raw value, - /// so that later on when generating the XML, we can provide this value rather than binding syntax. - /// - internal AdaptiveProgressBarValue RawValue { get; private set; } + internal AdaptiveProgressBarValue RawValue { get; private set; } - internal bool RawIsIndeterminate { get; private set; } + internal bool RawIsIndeterminate { get; private set; } - /// - /// Gets or sets the name that maps to your binding data value. - /// - public string BindingName { get; set; } + /// + /// Gets or sets the name that maps to your binding data value. + /// + public string BindingName { get; set; } - /// - /// Initializes a new instance of the class. - /// A new binding for a double value, with the required binding value name. Do NOT include surrounding {} brackets. - /// - /// The name that maps to your binding data value. - public BindableProgressBarValue(string bindingName) - { - BindingName = bindingName; - } + /// + /// Initializes a new instance of the class. + /// A new binding for a double value, with the required binding value name. Do NOT include surrounding {} brackets. + /// + /// The name that maps to your binding data value. + public BindableProgressBarValue(string bindingName) + { + BindingName = bindingName; + } - /// - /// Initializes a new instance of the class. - /// Private constructor used by the implicit converter to assign the raw value. - /// - private BindableProgressBarValue() - { - } + /// + /// Initializes a new instance of the class. + /// Private constructor used by the implicit converter to assign the raw value. + /// + private BindableProgressBarValue() + { + } - internal string ToXmlString() + internal string ToXmlString() + { + if (BindingName != null) { - if (BindingName != null) - { - return "{" + BindingName + "}"; - } - - if (RawValue != null) - { - return RawValue.ToXmlString(); - } - - return null; + return "{" + BindingName + "}"; } - /// - /// Creates a that has a raw value assigned. - /// - /// The raw value - public static implicit operator BindableProgressBarValue(AdaptiveProgressBarValue v) + if (RawValue != null) { - return new BindableProgressBarValue() - { - RawValue = v - }; + return RawValue.ToXmlString(); } - /// - /// Returns the raw value of the . - /// - /// The to obtain the raw value from. - public static implicit operator AdaptiveProgressBarValue(BindableProgressBarValue b) - { - return b.RawValue; - } + return null; + } - /// - /// Creates an that has the raw double value. - /// - /// The raw value - public static implicit operator BindableProgressBarValue(double d) + /// + /// Creates a that has a raw value assigned. + /// + /// The raw value + public static implicit operator BindableProgressBarValue(AdaptiveProgressBarValue v) + { + return new BindableProgressBarValue() { - return AdaptiveProgressBarValue.FromValue(d); - } + RawValue = v + }; + } + + /// + /// Returns the raw value of the . + /// + /// The to obtain the raw value from. + public static implicit operator AdaptiveProgressBarValue(BindableProgressBarValue b) + { + return b.RawValue; + } + + /// + /// Creates an that has the raw double value. + /// + /// The raw value + public static implicit operator BindableProgressBarValue(double d) + { + return AdaptiveProgressBarValue.FromValue(d); } } diff --git a/components/Notifications/src/Adaptive/BindableValues/BindableString.cs b/components/Notifications/src/Adaptive/BindableValues/BindableString.cs index 97849d70e..ad48f116f 100644 --- a/components/Notifications/src/Adaptive/BindableValues/BindableString.cs +++ b/components/Notifications/src/Adaptive/BindableValues/BindableString.cs @@ -2,67 +2,66 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A binding value for strings. +/// +public sealed class BindableString { + internal string RawValue { get; private set; } + /// - /// A binding value for strings. + /// Gets or sets the name that maps to your binding data value. /// - public sealed class BindableString - { - internal string RawValue { get; private set; } + public string BindingName { get; set; } - /// - /// Gets or sets the name that maps to your binding data value. - /// - public string BindingName { get; set; } + /// + /// Initializes a new instance of the class. + /// A new binding for a string value, with the required binding name. Do NOT include surrounding {} brackets. + /// + /// The name that maps to your data binding value. + public BindableString(string bindingName) + { + BindingName = bindingName; + } - /// - /// Initializes a new instance of the class. - /// A new binding for a string value, with the required binding name. Do NOT include surrounding {} brackets. - /// - /// The name that maps to your data binding value. - public BindableString(string bindingName) - { - BindingName = bindingName; - } + /// + /// Initializes a new instance of the class. + /// Private constructor used by the implicit converter to assign the raw value. + /// + private BindableString() + { + } - /// - /// Initializes a new instance of the class. - /// Private constructor used by the implicit converter to assign the raw value. - /// - private BindableString() + internal string ToXmlString() + { + if (BindingName != null) { + return "{" + BindingName + "}"; } - internal string ToXmlString() - { - if (BindingName != null) - { - return "{" + BindingName + "}"; - } - - return RawValue; - } + return RawValue; + } - /// - /// Creates a that has a raw value assigned. - /// - /// The raw value - public static implicit operator BindableString(string d) + /// + /// Creates a that has a raw value assigned. + /// + /// The raw value + public static implicit operator BindableString(string d) + { + return new BindableString() { - return new BindableString() - { - RawValue = d - }; - } + RawValue = d + }; + } - /// - /// Returns the raw value of the . - /// - /// The to obtain the raw value from. - public static implicit operator string(BindableString b) - { - return b.RawValue; - } + /// + /// Returns the raw value of the . + /// + /// The to obtain the raw value from. + public static implicit operator string(BindableString b) + { + return b.RawValue; } } diff --git a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveGroup.cs b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveGroup.cs index 339ca0a03..974d687a8 100644 --- a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveGroup.cs +++ b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveGroup.cs @@ -4,31 +4,30 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications.Adaptive.Elements +namespace CommunityToolkit.Notifications.Adaptive.Elements; + +internal sealed class Element_AdaptiveGroup : IElement_TileBindingChild, IElement_ToastBindingChild, IElementWithDescendants, IHaveXmlName, IHaveXmlChildren { - internal sealed class Element_AdaptiveGroup : IElement_TileBindingChild, IElement_ToastBindingChild, IElementWithDescendants, IHaveXmlName, IHaveXmlChildren - { - public IList Children { get; private set; } = new List(); + public IList Children { get; private set; } = new List(); - public IEnumerable Descendants() + public IEnumerable Descendants() + { + foreach (Element_AdaptiveSubgroup subgroup in Children) { - foreach (Element_AdaptiveSubgroup subgroup in Children) - { - // Return the subgroup - yield return subgroup; + // Return the subgroup + yield return subgroup; - // And also return its descendants - foreach (object descendant in subgroup.Descendants()) - { - yield return descendant; - } + // And also return its descendants + foreach (object descendant in subgroup.Descendants()) + { + yield return descendant; } } + } - /// - string IHaveXmlName.Name => "group"; + /// + string IHaveXmlName.Name => "group"; - /// - IEnumerable IHaveXmlChildren.Children => Children; - } + /// + IEnumerable IHaveXmlChildren.Children => Children; } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveImage.cs b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveImage.cs index 3ffe0b0f5..337a02817 100644 --- a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveImage.cs +++ b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveImage.cs @@ -4,90 +4,89 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications.Adaptive.Elements +namespace CommunityToolkit.Notifications.Adaptive.Elements; + +internal sealed class Element_AdaptiveImage : IElement_TileBindingChild, IElement_ToastBindingChild, IElement_AdaptiveSubgroupChild, IHaveXmlName, IHaveXmlNamedProperties { - internal sealed class Element_AdaptiveImage : IElement_TileBindingChild, IElement_ToastBindingChild, IElement_AdaptiveSubgroupChild, IHaveXmlName, IHaveXmlNamedProperties - { - internal const AdaptiveImagePlacement DEFAULT_PLACEMENT = AdaptiveImagePlacement.Inline; - internal const AdaptiveImageCrop DEFAULT_CROP = AdaptiveImageCrop.Default; - internal const AdaptiveImageAlign DEFAULT_ALIGN = AdaptiveImageAlign.Default; + internal const AdaptiveImagePlacement DEFAULT_PLACEMENT = AdaptiveImagePlacement.Inline; + internal const AdaptiveImageCrop DEFAULT_CROP = AdaptiveImageCrop.Default; + internal const AdaptiveImageAlign DEFAULT_ALIGN = AdaptiveImageAlign.Default; - public int? Id { get; set; } + public int? Id { get; set; } - public string Src { get; set; } + public string Src { get; set; } - public string Alt { get; set; } + public string Alt { get; set; } - public bool? AddImageQuery { get; set; } + public bool? AddImageQuery { get; set; } - public AdaptiveImagePlacement Placement { get; set; } = DEFAULT_PLACEMENT; + public AdaptiveImagePlacement Placement { get; set; } = DEFAULT_PLACEMENT; - public AdaptiveImageAlign Align { get; set; } = DEFAULT_ALIGN; + public AdaptiveImageAlign Align { get; set; } = DEFAULT_ALIGN; - public AdaptiveImageCrop Crop { get; set; } = DEFAULT_CROP; + public AdaptiveImageCrop Crop { get; set; } = DEFAULT_CROP; - public bool? RemoveMargin { get; set; } + public bool? RemoveMargin { get; set; } - private int? _overlay; + private int? _overlay; - public int? Overlay + public int? Overlay + { + get { - get - { - return _overlay; - } + return _overlay; + } - set + set + { + if (value != null) { - if (value != null) - { - Element_TileBinding.CheckOverlayValue(value.Value); - } - - _overlay = value; + Element_TileBinding.CheckOverlayValue(value.Value); } - } - public string SpriteSheetSrc { get; set; } + _overlay = value; + } + } - public uint? SpriteSheetHeight { get; set; } + public string SpriteSheetSrc { get; set; } - public uint? SpriteSheetFps { get; set; } + public uint? SpriteSheetHeight { get; set; } - public uint? SpriteSheetStartingFrame { get; set; } + public uint? SpriteSheetFps { get; set; } - /// - string IHaveXmlName.Name => "image"; + public uint? SpriteSheetStartingFrame { get; set; } - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("id", Id); - yield return new("src", Src); - yield return new("alt", Alt); - yield return new("addImageQuery", AddImageQuery); + /// + string IHaveXmlName.Name => "image"; - if (Placement != DEFAULT_PLACEMENT) - { - yield return new("placement", Placement.ToPascalCaseString()); - } + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("id", Id); + yield return new("src", Src); + yield return new("alt", Alt); + yield return new("addImageQuery", AddImageQuery); - if (Align != DEFAULT_ALIGN) - { - yield return new("hint-align", Align.ToPascalCaseString()); - } + if (Placement != DEFAULT_PLACEMENT) + { + yield return new("placement", Placement.ToPascalCaseString()); + } - if (Crop != DEFAULT_CROP) - { - yield return new("hint-crop", Crop.ToPascalCaseString()); - } + if (Align != DEFAULT_ALIGN) + { + yield return new("hint-align", Align.ToPascalCaseString()); + } - yield return new("hint-removeMargin", RemoveMargin); - yield return new("hint-overlay", Overlay); - yield return new("spritesheet-src", SpriteSheetSrc); - yield return new("spritesheet-height", SpriteSheetHeight); - yield return new("spritesheet-fps", SpriteSheetFps); - yield return new("spritesheet-startingFrame", SpriteSheetStartingFrame); + if (Crop != DEFAULT_CROP) + { + yield return new("hint-crop", Crop.ToPascalCaseString()); } + + yield return new("hint-removeMargin", RemoveMargin); + yield return new("hint-overlay", Overlay); + yield return new("spritesheet-src", SpriteSheetSrc); + yield return new("spritesheet-height", SpriteSheetHeight); + yield return new("spritesheet-fps", SpriteSheetFps); + yield return new("spritesheet-startingFrame", SpriteSheetStartingFrame); } } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveImageEnums.cs b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveImageEnums.cs index e817f880c..6ea77275c 100644 --- a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveImageEnums.cs +++ b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveImageEnums.cs @@ -2,14 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications.Adaptive.Elements +namespace CommunityToolkit.Notifications.Adaptive.Elements; + +internal enum AdaptiveImagePlacement { - internal enum AdaptiveImagePlacement - { - Inline, - Background, - Peek, - Hero, - AppLogoOverride - } + Inline, + Background, + Peek, + Hero, + AppLogoOverride } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveProgressBar.cs b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveProgressBar.cs index d26e96ee4..4a5da6a19 100644 --- a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveProgressBar.cs +++ b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveProgressBar.cs @@ -4,28 +4,27 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications.Adaptive.Elements +namespace CommunityToolkit.Notifications.Adaptive.Elements; + +internal sealed class Element_AdaptiveProgressBar : IElement_ToastBindingChild, IHaveXmlName, IHaveXmlNamedProperties { - internal sealed class Element_AdaptiveProgressBar : IElement_ToastBindingChild, IHaveXmlName, IHaveXmlNamedProperties - { - public string Value { get; set; } + public string Value { get; set; } - public string Title { get; set; } + public string Title { get; set; } - public string ValueStringOverride { get; set; } + public string ValueStringOverride { get; set; } - public string Status { get; set; } + public string Status { get; set; } - /// - string IHaveXmlName.Name => "progress"; + /// + string IHaveXmlName.Name => "progress"; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("value", Value); - yield return new("title", Title); - yield return new("valueStringOverride", ValueStringOverride); - yield return new("status", Status); - } + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("value", Value); + yield return new("title", Title); + yield return new("valueStringOverride", ValueStringOverride); + yield return new("status", Status); } } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveSubgroup.cs b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveSubgroup.cs index be3a0953c..2d85be283 100644 --- a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveSubgroup.cs +++ b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveSubgroup.cs @@ -5,69 +5,68 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications.Adaptive.Elements +namespace CommunityToolkit.Notifications.Adaptive.Elements; + +internal sealed class Element_AdaptiveSubgroup : IElementWithDescendants, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren { - internal sealed class Element_AdaptiveSubgroup : IElementWithDescendants, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren - { - internal const AdaptiveSubgroupTextStacking DEFAULT_TEXT_STACKING = AdaptiveSubgroupTextStacking.Default; + internal const AdaptiveSubgroupTextStacking DEFAULT_TEXT_STACKING = AdaptiveSubgroupTextStacking.Default; - public AdaptiveSubgroupTextStacking TextStacking { get; set; } = DEFAULT_TEXT_STACKING; + public AdaptiveSubgroupTextStacking TextStacking { get; set; } = DEFAULT_TEXT_STACKING; - private int? _weight; + private int? _weight; - public int? Weight + public int? Weight + { + get { - get - { - return _weight; - } + return _weight; + } - set - { - CheckWeight(value); + set + { + CheckWeight(value); - _weight = value; - } + _weight = value; } + } - internal static void CheckWeight(int? weight) + internal static void CheckWeight(int? weight) + { + if (weight != null && weight.Value < 1) { - if (weight != null && weight.Value < 1) - { - throw new ArgumentOutOfRangeException("Weight must be between 1 and int.MaxValue, inclusive (or null)"); - } + throw new ArgumentOutOfRangeException("Weight must be between 1 and int.MaxValue, inclusive (or null)"); } + } - public IList Children { get; private set; } = new List(); + public IList Children { get; private set; } = new List(); - public IEnumerable Descendants() + public IEnumerable Descendants() + { + foreach (IElement_AdaptiveSubgroupChild child in Children) { - foreach (IElement_AdaptiveSubgroupChild child in Children) - { - // Return each child (we know there's no further descendants) - yield return child; - } + // Return each child (we know there's no further descendants) + yield return child; } + } - /// - string IHaveXmlName.Name => "subgroup"; + /// + string IHaveXmlName.Name => "subgroup"; - /// - IEnumerable IHaveXmlChildren.Children => Children; + /// + IEnumerable IHaveXmlChildren.Children => Children; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + if (TextStacking != DEFAULT_TEXT_STACKING) { - if (TextStacking != DEFAULT_TEXT_STACKING) - { - yield return new("hint-textStacking", TextStacking.ToPascalCaseString()); - } - - yield return new("hint-weight", Weight); + yield return new("hint-textStacking", TextStacking.ToPascalCaseString()); } - } - internal interface IElement_AdaptiveSubgroupChild - { + yield return new("hint-weight", Weight); } +} + +internal interface IElement_AdaptiveSubgroupChild +{ } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveText.cs b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveText.cs index 4b87fe9cb..f689d8080 100644 --- a/components/Notifications/src/Adaptive/Elements/Element_AdaptiveText.cs +++ b/components/Notifications/src/Adaptive/Elements/Element_AdaptiveText.cs @@ -5,112 +5,111 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications.Adaptive.Elements +namespace CommunityToolkit.Notifications.Adaptive.Elements; + +internal sealed class Element_AdaptiveText : IElement_TileBindingChild, IElement_AdaptiveSubgroupChild, IElement_ToastBindingChild, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlText { - internal sealed class Element_AdaptiveText : IElement_TileBindingChild, IElement_AdaptiveSubgroupChild, IElement_ToastBindingChild, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlText - { - internal const AdaptiveTextStyle DEFAULT_STYLE = AdaptiveTextStyle.Default; - internal const AdaptiveTextAlign DEFAULT_ALIGN = AdaptiveTextAlign.Default; - internal const AdaptiveTextPlacement DEFAULT_PLACEMENT = AdaptiveTextPlacement.Inline; + internal const AdaptiveTextStyle DEFAULT_STYLE = AdaptiveTextStyle.Default; + internal const AdaptiveTextAlign DEFAULT_ALIGN = AdaptiveTextAlign.Default; + internal const AdaptiveTextPlacement DEFAULT_PLACEMENT = AdaptiveTextPlacement.Inline; - public string Text { get; set; } + public string Text { get; set; } - public int? Id { get; set; } + public int? Id { get; set; } - public string Lang { get; set; } + public string Lang { get; set; } - public AdaptiveTextAlign Align { get; set; } = DEFAULT_ALIGN; + public AdaptiveTextAlign Align { get; set; } = DEFAULT_ALIGN; - private int? _maxLines; + private int? _maxLines; - public int? MaxLines + public int? MaxLines + { + get { - get - { - return _maxLines; - } + return _maxLines; + } - set + set + { + if (value != null) { - if (value != null) - { - CheckMaxLinesValue(value.Value); - } - - _maxLines = value; + CheckMaxLinesValue(value.Value); } + + _maxLines = value; } + } - internal static void CheckMaxLinesValue(int value) + internal static void CheckMaxLinesValue(int value) + { + if (value < 1) { - if (value < 1) - { - throw new ArgumentOutOfRangeException("MaxLines must be between 1 and int.MaxValue, inclusive."); - } + throw new ArgumentOutOfRangeException("MaxLines must be between 1 and int.MaxValue, inclusive."); } + } - private int? _minLines; + private int? _minLines; - public int? MinLines + public int? MinLines + { + get { - get - { - return _minLines; - } + return _minLines; + } - set + set + { + if (value != null) { - if (value != null) - { - CheckMinLinesValue(value.Value); - } - - _minLines = value; + CheckMinLinesValue(value.Value); } + + _minLines = value; } + } - internal static void CheckMinLinesValue(int value) + internal static void CheckMinLinesValue(int value) + { + if (value < 1) { - if (value < 1) - { - throw new ArgumentOutOfRangeException("MinLines must be between 1 and int.MaxValue, inclusive."); - } + throw new ArgumentOutOfRangeException("MinLines must be between 1 and int.MaxValue, inclusive."); } + } - public AdaptiveTextStyle Style { get; set; } = DEFAULT_STYLE; + public AdaptiveTextStyle Style { get; set; } = DEFAULT_STYLE; - public bool? Wrap { get; set; } + public bool? Wrap { get; set; } - public AdaptiveTextPlacement Placement { get; set; } = DEFAULT_PLACEMENT; + public AdaptiveTextPlacement Placement { get; set; } = DEFAULT_PLACEMENT; - /// - string IHaveXmlName.Name => "text"; + /// + string IHaveXmlName.Name => "text"; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("id", Id); - yield return new("lang", Lang); + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("id", Id); + yield return new("lang", Lang); - if (Align != DEFAULT_ALIGN) - { - yield return new("hint-align", Align.ToPascalCaseString()); - } + if (Align != DEFAULT_ALIGN) + { + yield return new("hint-align", Align.ToPascalCaseString()); + } - yield return new("hint-maxLines", MaxLines); - yield return new("hint-minLines", MinLines); + yield return new("hint-maxLines", MaxLines); + yield return new("hint-minLines", MinLines); - if (Style != DEFAULT_STYLE) - { - yield return new("hint-style", Style.ToPascalCaseString()); - } + if (Style != DEFAULT_STYLE) + { + yield return new("hint-style", Style.ToPascalCaseString()); + } - yield return new("hint-wrap", Wrap); + yield return new("hint-wrap", Wrap); - if (Placement != DEFAULT_PLACEMENT) - { - yield return new("placement", Placement.ToPascalCaseString()); - } + if (Placement != DEFAULT_PLACEMENT) + { + yield return new("placement", Placement.ToPascalCaseString()); } } } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/IAdaptiveChild.cs b/components/Notifications/src/Adaptive/IAdaptiveChild.cs index 1c345e518..c78e9fd6d 100644 --- a/components/Notifications/src/Adaptive/IAdaptiveChild.cs +++ b/components/Notifications/src/Adaptive/IAdaptiveChild.cs @@ -2,13 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Elements that can be direct children of adaptive content, including (, , and ). +/// +public interface IAdaptiveChild { - /// - /// Elements that can be direct children of adaptive content, including (, , and ). - /// - public interface IAdaptiveChild - { - // Blank interface simply for compile-enforcing the child types in the list. - } + // Blank interface simply for compile-enforcing the child types in the list. } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/IAdaptiveSubgroupChild.cs b/components/Notifications/src/Adaptive/IAdaptiveSubgroupChild.cs index 9d257f032..c58dc6ea1 100644 --- a/components/Notifications/src/Adaptive/IAdaptiveSubgroupChild.cs +++ b/components/Notifications/src/Adaptive/IAdaptiveSubgroupChild.cs @@ -2,13 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Elements that can be direct children of an , including ( and ). +/// +public interface IAdaptiveSubgroupChild { - /// - /// Elements that can be direct children of an , including ( and ). - /// - public interface IAdaptiveSubgroupChild - { - // Blank interface simply for compile-enforcing the child types in the list. - } + // Blank interface simply for compile-enforcing the child types in the list. } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/IBaseImage.cs b/components/Notifications/src/Adaptive/IBaseImage.cs index c20127153..0a48ed73f 100644 --- a/components/Notifications/src/Adaptive/IBaseImage.cs +++ b/components/Notifications/src/Adaptive/IBaseImage.cs @@ -2,26 +2,25 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Contains the base properties that an image needs. +/// +public interface IBaseImage { /// - /// Contains the base properties that an image needs. + /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. /// - public interface IBaseImage - { - /// - /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. - /// - string Source { get; set; } + string Source { get; set; } - /// - /// Gets or sets a description of the image, for users of assistive technologies. - /// - string AlternateText { get; set; } + /// + /// Gets or sets a description of the image, for users of assistive technologies. + /// + string AlternateText { get; set; } - /// - /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. - /// - bool? AddImageQuery { get; set; } - } + /// + /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. + /// + bool? AddImageQuery { get; set; } } \ No newline at end of file diff --git a/components/Notifications/src/Adaptive/IBaseText.cs b/components/Notifications/src/Adaptive/IBaseText.cs index 38eb7bab4..b674a3737 100644 --- a/components/Notifications/src/Adaptive/IBaseText.cs +++ b/components/Notifications/src/Adaptive/IBaseText.cs @@ -2,21 +2,20 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Defines the basic properties of a text element. +/// +public interface IBaseText { /// - /// Defines the basic properties of a text element. + /// Gets or sets the text to display. /// - public interface IBaseText - { - /// - /// Gets or sets the text to display. - /// - string Text { get; set; } + string Text { get; set; } - /// - /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. - /// - string Language { get; set; } - } + /// + /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. + /// + string Language { get; set; } } \ No newline at end of file diff --git a/components/Notifications/src/Badges/BadgeGlyphContent.cs b/components/Notifications/src/Badges/BadgeGlyphContent.cs index 5d02da2fd..51724d717 100644 --- a/components/Notifications/src/Badges/BadgeGlyphContent.cs +++ b/components/Notifications/src/Badges/BadgeGlyphContent.cs @@ -5,90 +5,89 @@ using System; using Windows.Data.Xml.Dom; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Notification content object to display a glyph on a Tile's badge. +/// +public sealed class BadgeGlyphContent : INotificationContent { /// - /// Notification content object to display a glyph on a Tile's badge. + /// Initializes a new instance of the class. + /// Default constructor to create a glyph badge content object. /// - public sealed class BadgeGlyphContent : INotificationContent + public BadgeGlyphContent() { - /// - /// Initializes a new instance of the class. - /// Default constructor to create a glyph badge content object. - /// - public BadgeGlyphContent() - { - } + } - /// - /// Initializes a new instance of the class. - /// Constructor to create a glyph badge content object with a glyph. - /// - /// The glyph to be displayed on the badge. - public BadgeGlyphContent(BadgeGlyphValue glyph) - { - _glyph = glyph; - } + /// + /// Initializes a new instance of the class. + /// Constructor to create a glyph badge content object with a glyph. + /// + /// The glyph to be displayed on the badge. + public BadgeGlyphContent(BadgeGlyphValue glyph) + { + _glyph = glyph; + } - /// - /// Gets or sets the glyph to be displayed on the badge. - /// - public BadgeGlyphValue Glyph + /// + /// Gets or sets the glyph to be displayed on the badge. + /// + public BadgeGlyphValue Glyph + { + get { - get - { - return _glyph; - } - - set - { - if (!Enum.IsDefined(typeof(BadgeGlyphValue), value)) - { - throw new ArgumentOutOfRangeException(nameof(value)); - } - - _glyph = value; - } + return _glyph; } - /// - /// Retrieves the notification Xml content as a string. - /// - /// The notification Xml content as a string. - public string GetContent() + set { - if (!Enum.IsDefined(typeof(BadgeGlyphValue), _glyph)) + if (!Enum.IsDefined(typeof(BadgeGlyphValue), value)) { - throw new NotificationContentValidationException("The badge glyph property was left unset."); + throw new ArgumentOutOfRangeException(nameof(value)); } - string glyphString = _glyph.ToString(); - - // lower case the first character of the enum value to match the Xml schema - glyphString = string.Format("{0}{1}", char.ToLowerInvariant(glyphString[0]), glyphString.Substring(1)); - return string.Format("", glyphString); + _glyph = value; } + } - /// - /// Retrieves the notification XML content as a string. - /// - /// The notification XML content as a string. - public override string ToString() + /// + /// Retrieves the notification Xml content as a string. + /// + /// The notification Xml content as a string. + public string GetContent() + { + if (!Enum.IsDefined(typeof(BadgeGlyphValue), _glyph)) { - return GetContent(); + throw new NotificationContentValidationException("The badge glyph property was left unset."); } - /// - /// Retrieves the notification XML content as a WinRT Xml document. - /// - /// The notification XML content as a WinRT Xml document. - public XmlDocument GetXml() - { - XmlDocument xml = new XmlDocument(); - xml.LoadXml(GetContent()); - return xml; - } + string glyphString = _glyph.ToString(); + + // lower case the first character of the enum value to match the Xml schema + glyphString = string.Format("{0}{1}", char.ToLowerInvariant(glyphString[0]), glyphString.Substring(1)); + return string.Format("", glyphString); + } - private BadgeGlyphValue _glyph = (BadgeGlyphValue)(-1); + /// + /// Retrieves the notification XML content as a string. + /// + /// The notification XML content as a string. + public override string ToString() + { + return GetContent(); } + + /// + /// Retrieves the notification XML content as a WinRT Xml document. + /// + /// The notification XML content as a WinRT Xml document. + public XmlDocument GetXml() + { + XmlDocument xml = new XmlDocument(); + xml.LoadXml(GetContent()); + return xml; + } + + private BadgeGlyphValue _glyph = (BadgeGlyphValue)(-1); } diff --git a/components/Notifications/src/Badges/BadgeGlyphValue.cs b/components/Notifications/src/Badges/BadgeGlyphValue.cs index 17bcb61b8..28f8b3f41 100644 --- a/components/Notifications/src/Badges/BadgeGlyphValue.cs +++ b/components/Notifications/src/Badges/BadgeGlyphValue.cs @@ -2,77 +2,76 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// The types of glyphs that can be placed on a badge. +/// +public enum BadgeGlyphValue { /// - /// The types of glyphs that can be placed on a badge. + /// No glyph. If there is a numeric badge, or a glyph currently on the badge, + /// it will be removed. /// - public enum BadgeGlyphValue - { - /// - /// No glyph. If there is a numeric badge, or a glyph currently on the badge, - /// it will be removed. - /// - None = 0, + None = 0, - /// - /// A glyph representing application activity. - /// - Activity, + /// + /// A glyph representing application activity. + /// + Activity, - /// - /// A glyph representing an alert. - /// - Alert, + /// + /// A glyph representing an alert. + /// + Alert, - /// - /// A glyph representing an alarm. - /// - Alarm, + /// + /// A glyph representing an alarm. + /// + Alarm, - /// - /// A glyph representing availability status. - /// - Available, + /// + /// A glyph representing availability status. + /// + Available, - /// - /// A glyph representing away status - /// - Away, + /// + /// A glyph representing away status + /// + Away, - /// - /// A glyph representing busy status. - /// - Busy, + /// + /// A glyph representing busy status. + /// + Busy, - /// - /// A glyph representing that a new message is available. - /// - NewMessage, + /// + /// A glyph representing that a new message is available. + /// + NewMessage, - /// - /// A glyph representing that media is paused. - /// - Paused, + /// + /// A glyph representing that media is paused. + /// + Paused, - /// - /// A glyph representing that media is playing. - /// - Playing, + /// + /// A glyph representing that media is playing. + /// + Playing, - /// - /// A glyph representing unavailable status. - /// - Unavailable, + /// + /// A glyph representing unavailable status. + /// + Unavailable, - /// - /// A glyph representing an error. - /// - Error, + /// + /// A glyph representing an error. + /// + Error, - /// - /// A glyph representing attention status. - /// - Attention - } + /// + /// A glyph representing attention status. + /// + Attention } \ No newline at end of file diff --git a/components/Notifications/src/Badges/BadgeNumericContent.cs b/components/Notifications/src/Badges/BadgeNumericContent.cs index c3cda912b..97c540e62 100644 --- a/components/Notifications/src/Badges/BadgeNumericContent.cs +++ b/components/Notifications/src/Badges/BadgeNumericContent.cs @@ -4,73 +4,72 @@ using Windows.Data.Xml.Dom; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Notification content object to display a number on a Tile's badge. +/// +public sealed class BadgeNumericContent : INotificationContent { /// - /// Notification content object to display a number on a Tile's badge. + /// Initializes a new instance of the class. + /// Default constructor to create a numeric badge content object. /// - public sealed class BadgeNumericContent : INotificationContent + public BadgeNumericContent() { - /// - /// Initializes a new instance of the class. - /// Default constructor to create a numeric badge content object. - /// - public BadgeNumericContent() - { - } - - /// - /// Initializes a new instance of the class. - /// Constructor to create a numeric badge content object with a number. - /// - /// - /// The number that will appear on the badge. If the number is 0, the badge - /// will be removed. - /// - public BadgeNumericContent(uint number) - { - _number = number; - } + } - /// - /// Gets or sets the number that will appear on the badge. If the number is 0, the badge - /// will be removed. - /// - public uint Number - { - get { return _number; } - set { _number = value; } - } + /// + /// Initializes a new instance of the class. + /// Constructor to create a numeric badge content object with a number. + /// + /// + /// The number that will appear on the badge. If the number is 0, the badge + /// will be removed. + /// + public BadgeNumericContent(uint number) + { + _number = number; + } - /// - /// Retrieves the notification Xml content as a string. - /// - /// The notification Xml content as a string. - public string GetContent() - { - return string.Format("", _number); - } + /// + /// Gets or sets the number that will appear on the badge. If the number is 0, the badge + /// will be removed. + /// + public uint Number + { + get { return _number; } + set { _number = value; } + } - /// - /// Retrieves the notification Xml content as a string. - /// - /// The notification Xml content as a string. - public override string ToString() - { - return GetContent(); - } + /// + /// Retrieves the notification Xml content as a string. + /// + /// The notification Xml content as a string. + public string GetContent() + { + return string.Format("", _number); + } - /// - /// Retrieves the notification Xml content as a WinRT Xml document. - /// - /// The notification Xml content as a WinRT Xml document. - public XmlDocument GetXml() - { - XmlDocument xml = new XmlDocument(); - xml.LoadXml(GetContent()); - return xml; - } + /// + /// Retrieves the notification Xml content as a string. + /// + /// The notification Xml content as a string. + public override string ToString() + { + return GetContent(); + } - private uint _number = 0; + /// + /// Retrieves the notification Xml content as a WinRT Xml document. + /// + /// The notification Xml content as a WinRT Xml document. + public XmlDocument GetXml() + { + XmlDocument xml = new XmlDocument(); + xml.LoadXml(GetContent()); + return xml; } + + private uint _number = 0; } diff --git a/components/Notifications/src/Common/ArgumentValidator.cs b/components/Notifications/src/Common/ArgumentValidator.cs index c1f9c4d82..d9a15ed0d 100644 --- a/components/Notifications/src/Common/ArgumentValidator.cs +++ b/components/Notifications/src/Common/ArgumentValidator.cs @@ -4,27 +4,26 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal static class ArgumentValidator { - internal static class ArgumentValidator + public static void SetProperty(ref T property, T value, string propertyName, ArgumentValidatorOptions options) { - public static void SetProperty(ref T property, T value, string propertyName, ArgumentValidatorOptions options) + if (options.HasFlag(ArgumentValidatorOptions.NotNull)) { - if (options.HasFlag(ArgumentValidatorOptions.NotNull)) + if (value == null) { - if (value == null) - { - throw new ArgumentNullException(propertyName); - } + throw new ArgumentNullException(propertyName); } - - property = value; } - } - [Flags] - internal enum ArgumentValidatorOptions - { - NotNull + property = value; } +} + +[Flags] +internal enum ArgumentValidatorOptions +{ + NotNull } \ No newline at end of file diff --git a/components/Notifications/src/Common/BaseElement.cs b/components/Notifications/src/Common/BaseElement.cs index 809eca5c1..0b0db4be6 100644 --- a/components/Notifications/src/Common/BaseElement.cs +++ b/components/Notifications/src/Common/BaseElement.cs @@ -7,46 +7,45 @@ using Windows.Data.Xml.Dom; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal abstract class BaseElement { - internal abstract class BaseElement + /// + /// Retrieves the notification XML content as a string. + /// + /// The notification XML content as a string. + public string GetContent() { - /// - /// Retrieves the notification XML content as a string. - /// - /// The notification XML content as a string. - public string GetContent() + using (MemoryStream stream = new MemoryStream()) { - using (MemoryStream stream = new MemoryStream()) + using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(stream, new System.Xml.XmlWriterSettings() + { + Encoding = Encoding.UTF8, // Use UTF-8 encoding to save space (it defaults to UTF-16 which is 2x the size) + Indent = false, + NewLineOnAttributes = false + })) { - using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(stream, new System.Xml.XmlWriterSettings() - { - Encoding = Encoding.UTF8, // Use UTF-8 encoding to save space (it defaults to UTF-16 which is 2x the size) - Indent = false, - NewLineOnAttributes = false - })) - { - XmlWriterHelper.Write(writer, this); - } + XmlWriterHelper.Write(writer, this); + } - stream.Position = 0; + stream.Position = 0; - using (StreamReader reader = new StreamReader(stream)) - { - return reader.ReadToEnd(); - } + using (StreamReader reader = new StreamReader(stream)) + { + return reader.ReadToEnd(); } } + } - /// - /// Retrieves the notification XML content as a WinRT XML document. - /// - /// The notification XML content as a WinRT XML document. - public XmlDocument GetXml() - { - XmlDocument xml = new XmlDocument(); - xml.LoadXml(GetContent()); - return xml; - } + /// + /// Retrieves the notification XML content as a WinRT XML document. + /// + /// The notification XML content as a WinRT XML document. + public XmlDocument GetXml() + { + XmlDocument xml = new XmlDocument(); + xml.LoadXml(GetContent()); + return xml; } } diff --git a/components/Notifications/src/Common/EnumFormatter.cs b/components/Notifications/src/Common/EnumFormatter.cs index 117a98a4f..bd7b8c08c 100644 --- a/components/Notifications/src/Common/EnumFormatter.cs +++ b/components/Notifications/src/Common/EnumFormatter.cs @@ -6,52 +6,51 @@ #nullable enable -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A helper class that can be used to format values. +/// +internal static class EnumFormatter { /// - /// A helper class that can be used to format values. + /// Returns a representation of an enum value with pascal casing. /// - internal static class EnumFormatter + /// The type to format. + /// The value to format. + /// The pascal case representation of . + public static string? ToPascalCaseString(this T? value) + where T : unmanaged, Enum { - /// - /// Returns a representation of an enum value with pascal casing. - /// - /// The type to format. - /// The value to format. - /// The pascal case representation of . - public static string? ToPascalCaseString(this T? value) - where T : unmanaged, Enum + if (value is null) { - if (value is null) - { - return null; - } - - return ToPascalCaseString(value.Value); + return null; } - /// - /// Returns a representation of an enum value with pascal casing. - /// - /// The type to format. - /// The value to format. - /// The pascal case representation of . - public static string? ToPascalCaseString(this T value) - where T : unmanaged, Enum - { - string? text = value.ToString(); + return ToPascalCaseString(value.Value); + } - if (text is null or { Length: 0 }) - { - return text; - } + /// + /// Returns a representation of an enum value with pascal casing. + /// + /// The type to format. + /// The value to format. + /// The pascal case representation of . + public static string? ToPascalCaseString(this T value) + where T : unmanaged, Enum + { + string? text = value.ToString(); - if (text is { Length: 1 }) - { - return text.ToLowerInvariant(); - } + if (text is null or { Length: 0 }) + { + return text; + } - return $"{char.ToLowerInvariant(text[0])}{text.Substring(1)}"; + if (text is { Length: 1 }) + { + return text.ToLowerInvariant(); } + + return $"{char.ToLowerInvariant(text[0])}{text.Substring(1)}"; } } \ No newline at end of file diff --git a/components/Notifications/src/Common/INotificationContent.cs b/components/Notifications/src/Common/INotificationContent.cs index d84afe4a3..c4ccc84e6 100644 --- a/components/Notifications/src/Common/INotificationContent.cs +++ b/components/Notifications/src/Common/INotificationContent.cs @@ -4,23 +4,22 @@ using Windows.Data.Xml.Dom; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Base notification content interface to retrieve notification Xml as a string. +/// +public interface INotificationContent { /// - /// Base notification content interface to retrieve notification Xml as a string. + /// Retrieves the notification Xml content as a string. /// - public interface INotificationContent - { - /// - /// Retrieves the notification Xml content as a string. - /// - /// The notification Xml content as a string. - string GetContent(); + /// The notification Xml content as a string. + string GetContent(); - /// - /// Retrieves the notification Xml content as a WinRT Xml document. - /// - /// The notification Xml content as a WinRT Xml document. - XmlDocument GetXml(); - } + /// + /// Retrieves the notification Xml content as a WinRT Xml document. + /// + /// The notification Xml content as a WinRT Xml document. + XmlDocument GetXml(); } diff --git a/components/Notifications/src/Common/LimitedList{T}.cs b/components/Notifications/src/Common/LimitedList{T}.cs index 5ff4ac43b..6e2162199 100644 --- a/components/Notifications/src/Common/LimitedList{T}.cs +++ b/components/Notifications/src/Common/LimitedList{T}.cs @@ -6,108 +6,107 @@ using System.Collections; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class LimitedList : IList { - internal sealed class LimitedList : IList - { - private List _list; + private List _list; - public int Limit { get; private set; } + public int Limit { get; private set; } - public LimitedList(int limit) - { - _list = new List(limit); + public LimitedList(int limit) + { + _list = new List(limit); - Limit = limit; - } + Limit = limit; + } - public T this[int index] + public T this[int index] + { + get { - get - { - return _list[index]; - } - - set - { - _list[index] = value; - } + return _list[index]; } - public int Count + set { - get - { - return _list.Count; - } + _list[index] = value; } + } - public bool IsReadOnly + public int Count + { + get { - get - { - return false; - } + return _list.Count; } + } - public void Add(T item) + public bool IsReadOnly + { + get { - if (_list.Count >= Limit) - { - throw new Exception("This list is limited to " + Limit + " items. You cannot add more items."); - } - - _list.Add(item); + return false; } + } - public void Clear() + public void Add(T item) + { + if (_list.Count >= Limit) { - _list.Clear(); + throw new Exception("This list is limited to " + Limit + " items. You cannot add more items."); } - public bool Contains(T item) - { - return _list.Contains(item); - } + _list.Add(item); + } - public void CopyTo(T[] array, int arrayIndex) - { - _list.CopyTo(array, arrayIndex); - } + public void Clear() + { + _list.Clear(); + } - public IEnumerator GetEnumerator() - { - return _list.GetEnumerator(); - } + public bool Contains(T item) + { + return _list.Contains(item); + } - public int IndexOf(T item) - { - return _list.IndexOf(item); - } + public void CopyTo(T[] array, int arrayIndex) + { + _list.CopyTo(array, arrayIndex); + } - public void Insert(int index, T item) - { - _list.Insert(index, item); - } + public IEnumerator GetEnumerator() + { + return _list.GetEnumerator(); + } - public bool Remove(T item) - { - return _list.Remove(item); - } + public int IndexOf(T item) + { + return _list.IndexOf(item); + } - public void RemoveAt(int index) - { - _list.RemoveAt(index); - } + public void Insert(int index, T item) + { + _list.Insert(index, item); + } - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + public bool Remove(T item) + { + return _list.Remove(item); } - internal interface IElementWithDescendants + public void RemoveAt(int index) { - IEnumerable Descendants(); + _list.RemoveAt(index); } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } +} + +internal interface IElementWithDescendants +{ + IEnumerable Descendants(); } diff --git a/components/Notifications/src/Common/NotificationContentValidationException.cs b/components/Notifications/src/Common/NotificationContentValidationException.cs index 2963aa444..3156e1831 100644 --- a/components/Notifications/src/Common/NotificationContentValidationException.cs +++ b/components/Notifications/src/Common/NotificationContentValidationException.cs @@ -4,16 +4,15 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Exception returned when invalid notification content is provided. +/// +internal sealed class NotificationContentValidationException : Exception { - /// - /// Exception returned when invalid notification content is provided. - /// - internal sealed class NotificationContentValidationException : Exception + public NotificationContentValidationException(string message) + : base(message) { - public NotificationContentValidationException(string message) - : base(message) - { - } } } diff --git a/components/Notifications/src/Common/Serialization/IHaveXmlAdditionalProperties.cs b/components/Notifications/src/Common/Serialization/IHaveXmlAdditionalProperties.cs index 757d1f5d7..a4342b951 100644 --- a/components/Notifications/src/Common/Serialization/IHaveXmlAdditionalProperties.cs +++ b/components/Notifications/src/Common/Serialization/IHaveXmlAdditionalProperties.cs @@ -6,16 +6,15 @@ #nullable enable -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// An interface for a notification XML element with additional properties. +/// +internal interface IHaveXmlAdditionalProperties { /// - /// An interface for a notification XML element with additional properties. + /// Gets the mapping of additional properties. /// - internal interface IHaveXmlAdditionalProperties - { - /// - /// Gets the mapping of additional properties. - /// - IReadOnlyDictionary AdditionalProperties { get; } - } + IReadOnlyDictionary AdditionalProperties { get; } } diff --git a/components/Notifications/src/Common/Serialization/IHaveXmlChildren.cs b/components/Notifications/src/Common/Serialization/IHaveXmlChildren.cs index 12723a323..afc91a952 100644 --- a/components/Notifications/src/Common/Serialization/IHaveXmlChildren.cs +++ b/components/Notifications/src/Common/Serialization/IHaveXmlChildren.cs @@ -6,16 +6,15 @@ #nullable enable -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// An interface for a notification XML element with additional children. +/// +internal interface IHaveXmlChildren { /// - /// An interface for a notification XML element with additional children. + /// Gets the children of the current element. /// - internal interface IHaveXmlChildren - { - /// - /// Gets the children of the current element. - /// - IEnumerable Children { get; } - } + IEnumerable Children { get; } } \ No newline at end of file diff --git a/components/Notifications/src/Common/Serialization/IHaveXmlName.cs b/components/Notifications/src/Common/Serialization/IHaveXmlName.cs index f9e96c99d..07f8dd09c 100644 --- a/components/Notifications/src/Common/Serialization/IHaveXmlName.cs +++ b/components/Notifications/src/Common/Serialization/IHaveXmlName.cs @@ -2,16 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// An interface for a notification XML element with a name. +/// +internal interface IHaveXmlName { /// - /// An interface for a notification XML element with a name. + /// Gets the name of the current element. /// - internal interface IHaveXmlName - { - /// - /// Gets the name of the current element. - /// - string Name { get; } - } + string Name { get; } } diff --git a/components/Notifications/src/Common/Serialization/IHaveXmlNamedProperties.cs b/components/Notifications/src/Common/Serialization/IHaveXmlNamedProperties.cs index 29c7e17b5..b69f88eeb 100644 --- a/components/Notifications/src/Common/Serialization/IHaveXmlNamedProperties.cs +++ b/components/Notifications/src/Common/Serialization/IHaveXmlNamedProperties.cs @@ -6,18 +6,17 @@ #nullable enable -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// An interface for a notification XML element with named properties. +/// +internal interface IHaveXmlNamedProperties { /// - /// An interface for a notification XML element with named properties. + /// Enumerates the available named properties for the element. /// - internal interface IHaveXmlNamedProperties - { - /// - /// Enumerates the available named properties for the element. - /// - /// A sequence of named properties for the element. - /// The returned values must be valid XML values when is called on them. - IEnumerable> EnumerateNamedProperties(); - } + /// A sequence of named properties for the element. + /// The returned values must be valid XML values when is called on them. + IEnumerable> EnumerateNamedProperties(); } diff --git a/components/Notifications/src/Common/Serialization/IHaveXmlText.cs b/components/Notifications/src/Common/Serialization/IHaveXmlText.cs index 358afa31b..27d3afa29 100644 --- a/components/Notifications/src/Common/Serialization/IHaveXmlText.cs +++ b/components/Notifications/src/Common/Serialization/IHaveXmlText.cs @@ -2,16 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// An interface for a notification XML element with an explicit XML text content. +/// +internal interface IHaveXmlText { /// - /// An interface for a notification XML element with an explicit XML text content. + /// Gets the text content of the current element. /// - internal interface IHaveXmlText - { - /// - /// Gets the text content of the current element. - /// - string Text { get; } - } + string Text { get; } } diff --git a/components/Notifications/src/Common/XmlWriterHelper.cs b/components/Notifications/src/Common/XmlWriterHelper.cs index 6111d2bda..4de5e19b3 100644 --- a/components/Notifications/src/Common/XmlWriterHelper.cs +++ b/components/Notifications/src/Common/XmlWriterHelper.cs @@ -7,81 +7,80 @@ using System.Linq; using System.Xml; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal static class XmlWriterHelper { - internal static class XmlWriterHelper + public static void Write(XmlWriter writer, object element) { - public static void Write(XmlWriter writer, object element) + // If it isn't an XML element, don't write anything + if (element is not IHaveXmlName xmlElement) { - // If it isn't an XML element, don't write anything - if (element is not IHaveXmlName xmlElement) - { - return; - } - - writer.WriteStartElement(xmlElement.Name); - - // Write all named properties - foreach (var property in (element as IHaveXmlNamedProperties)?.EnumerateNamedProperties() ?? Enumerable.Empty>()) - { - if (property.Value is not null) - { - writer.WriteAttributeString(property.Key, PropertyValueToString(property.Value)); - } - } + return; + } - // Write all additional properties - foreach (var property in (element as IHaveXmlAdditionalProperties)?.AdditionalProperties ?? Enumerable.Empty>()) - { - writer.WriteAttributeString(property.Key, property.Value); - } + writer.WriteStartElement(xmlElement.Name); - // Write the inner text, if any - if ((element as IHaveXmlText)?.Text is string { Length: > 0 } text) + // Write all named properties + foreach (var property in (element as IHaveXmlNamedProperties)?.EnumerateNamedProperties() ?? Enumerable.Empty>()) + { + if (property.Value is not null) { - writer.WriteString(text); + writer.WriteAttributeString(property.Key, PropertyValueToString(property.Value)); } + } - // Write all children, if any - foreach (var child in (element as IHaveXmlChildren)?.Children ?? Enumerable.Empty()) - { - Write(writer, child); - } + // Write all additional properties + foreach (var property in (element as IHaveXmlAdditionalProperties)?.AdditionalProperties ?? Enumerable.Empty>()) + { + writer.WriteAttributeString(property.Key, property.Value); + } - writer.WriteEndElement(); + // Write the inner text, if any + if ((element as IHaveXmlText)?.Text is string { Length: > 0 } text) + { + writer.WriteString(text); } - private static string PropertyValueToString(object propertyValue) + // Write all children, if any + foreach (var child in (element as IHaveXmlChildren)?.Children ?? Enumerable.Empty()) { - return propertyValue switch - { - true => "true", - false => "false", - DateTimeOffset dateTime => XmlConvert.ToString(dateTime), // ISO 8601 format - { } value => value.ToString(), - _ => null - }; + Write(writer, child); } - /// - /// Gets the provided binding value, if it exists. Otherwise, falls back to the absolute value. - /// - /// The type of the enum of the class properties. - /// The collection of data-bound values. - /// The property to obtain. - /// The absolute value, if any. - /// The provided binding value, if it exists. Otherwise, falls back to the absolute value. - internal static string GetBindingOrAbsoluteXmlValue(IDictionary bindings, T bindableProperty, string absoluteValue) + writer.WriteEndElement(); + } + + private static string PropertyValueToString(object propertyValue) + { + return propertyValue switch { - // If a binding is provided, use the binding value - string bindingValue; - if (bindings.TryGetValue(bindableProperty, out bindingValue)) - { - return "{" + bindingValue + "}"; - } + true => "true", + false => "false", + DateTimeOffset dateTime => XmlConvert.ToString(dateTime), // ISO 8601 format + { } value => value.ToString(), + _ => null + }; + } - // Otherwise fallback to the absolute value - return absoluteValue; + /// + /// Gets the provided binding value, if it exists. Otherwise, falls back to the absolute value. + /// + /// The type of the enum of the class properties. + /// The collection of data-bound values. + /// The property to obtain. + /// The absolute value, if any. + /// The provided binding value, if it exists. Otherwise, falls back to the absolute value. + internal static string GetBindingOrAbsoluteXmlValue(IDictionary bindings, T bindableProperty, string absoluteValue) + { + // If a binding is provided, use the binding value + string bindingValue; + if (bindings.TryGetValue(bindableProperty, out bindingValue)) + { + return "{" + bindingValue + "}"; } + + // Otherwise fallback to the absolute value + return absoluteValue; } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/Builder/TileContentBuilder.SpecialTiles.cs b/components/Notifications/src/Tiles/Builder/TileContentBuilder.SpecialTiles.cs index a706c5b56..a2f0e34cb 100644 --- a/components/Notifications/src/Tiles/Builder/TileContentBuilder.SpecialTiles.cs +++ b/components/Notifications/src/Tiles/Builder/TileContentBuilder.SpecialTiles.cs @@ -7,155 +7,155 @@ using System.Linq; using System.Text; -namespace CommunityToolkit.Notifications -{ +namespace CommunityToolkit.Notifications; + #pragma warning disable SA1008 #pragma warning disable SA1009 +/// +/// Builder class used to create +/// +public partial class TileContentBuilder +{ /// - /// Builder class used to create + /// Helper method for creating a tile notification content for using Contact tile template. /// - public partial class TileContentBuilder + /// Source for the contact picture + /// Name of the contact + /// A description of the contact image, for users of assistive technologies. + /// Indicating whether Windows should append a query string to the image URI supplied in the Tile notification. + /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. + /// An instance of represent a payload of a tile notification. + public static TileBindingContentContact CreateContactTileContent(Uri contactImageUri, string contactName, string contactImageAltText = default(string), bool? contactImageAddImageQuery = default(bool?), string textLanguage = default(string)) { - /// - /// Helper method for creating a tile notification content for using Contact tile template. - /// - /// Source for the contact picture - /// Name of the contact - /// A description of the contact image, for users of assistive technologies. - /// Indicating whether Windows should append a query string to the image URI supplied in the Tile notification. - /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. - /// An instance of represent a payload of a tile notification. - public static TileBindingContentContact CreateContactTileContent(Uri contactImageUri, string contactName, string contactImageAltText = default(string), bool? contactImageAddImageQuery = default(bool?), string textLanguage = default(string)) - { - var contactTileContent = new TileBindingContentContact(); - contactTileContent.Image = CreateTileBasicImage(contactImageUri, contactImageAltText, contactImageAddImageQuery); + var contactTileContent = new TileBindingContentContact(); + contactTileContent.Image = CreateTileBasicImage(contactImageUri, contactImageAltText, contactImageAddImageQuery); - contactTileContent.Text = new TileBasicText(); - contactTileContent.Text.Text = contactName; + contactTileContent.Text = new TileBasicText(); + contactTileContent.Text.Text = contactName; - if (textLanguage != default(string)) - { - contactTileContent.Text.Lang = textLanguage; - } - - return contactTileContent; + if (textLanguage != default(string)) + { + contactTileContent.Text.Lang = textLanguage; } - /// - /// Helper method for creating a tile notification content for using Iconic tile template. - /// - /// Source of the icon image. - /// A description of the icon image, for users of assistive technologies. - /// Indicating whether Windows should append a query string to the image URI supplied in the Tile notification. - /// An instance of represent a payload of a tile notification. - public static TileBindingContentIconic CreateIconicTileContent(Uri iconImageUri, string iconImageAltText = default(string), bool? iconImageAddImageQuery = default(bool?)) - { - var iconicTileContent = new TileBindingContentIconic(); - iconicTileContent.Icon = CreateTileBasicImage(iconImageUri, iconImageAltText, iconImageAddImageQuery); + return contactTileContent; + } - return iconicTileContent; - } + /// + /// Helper method for creating a tile notification content for using Iconic tile template. + /// + /// Source of the icon image. + /// A description of the icon image, for users of assistive technologies. + /// Indicating whether Windows should append a query string to the image URI supplied in the Tile notification. + /// An instance of represent a payload of a tile notification. + public static TileBindingContentIconic CreateIconicTileContent(Uri iconImageUri, string iconImageAltText = default(string), bool? iconImageAddImageQuery = default(bool?)) + { + var iconicTileContent = new TileBindingContentIconic(); + iconicTileContent.Icon = CreateTileBasicImage(iconImageUri, iconImageAltText, iconImageAddImageQuery); - /// - /// Helper method for creating a tile notification content for using People tile template. - /// - /// Sources of pictures that will be used on the people tile. - /// An instance of represent a payload of a tile notification. - public static TileBindingContentPeople CreatePeopleTileContent(params Uri[] peoplePictureSources) - { - IEnumerable images = peoplePictureSources.Select(u => CreateTileBasicImage(u, default(string), default(bool?))); + return iconicTileContent; + } - return CreatePeopleTileContent(images); - } + /// + /// Helper method for creating a tile notification content for using People tile template. + /// + /// Sources of pictures that will be used on the people tile. + /// An instance of represent a payload of a tile notification. + public static TileBindingContentPeople CreatePeopleTileContent(params Uri[] peoplePictureSources) + { + IEnumerable images = peoplePictureSources.Select(u => CreateTileBasicImage(u, default(string), default(bool?))); - /// - /// Helper method for creating a tile notification content for using People tile template. - /// - /// Sources of pictures with description and image query indicator that will be used on the people tile. - /// An instance of represent a payload of a tile notification. - public static TileBindingContentPeople CreatePeopleTileContent(params (Uri source, string imageAltText, bool? addImageQuery)[] peoplePictures) - { - IEnumerable images = peoplePictures.Select(t => CreateTileBasicImage(t.source, t.imageAltText, t.addImageQuery)); + return CreatePeopleTileContent(images); + } - return CreatePeopleTileContent(images); - } + /// + /// Helper method for creating a tile notification content for using People tile template. + /// + /// Sources of pictures with description and image query indicator that will be used on the people tile. + /// An instance of represent a payload of a tile notification. + public static TileBindingContentPeople CreatePeopleTileContent(params (Uri source, string imageAltText, bool? addImageQuery)[] peoplePictures) + { + IEnumerable images = peoplePictures.Select(t => CreateTileBasicImage(t.source, t.imageAltText, t.addImageQuery)); - /// - /// Helper method for creating a tile notification content for using People tile template. - /// - /// Pictures that will be used on the people tile. - /// An instance of represent a payload of a tile notification. - public static TileBindingContentPeople CreatePeopleTileContent(IEnumerable peoplePictures) - { - var peopleTileContent = new TileBindingContentPeople(); + return CreatePeopleTileContent(images); + } - foreach (var image in peoplePictures) - { - peopleTileContent.Images.Add(image); - } + /// + /// Helper method for creating a tile notification content for using People tile template. + /// + /// Pictures that will be used on the people tile. + /// An instance of represent a payload of a tile notification. + public static TileBindingContentPeople CreatePeopleTileContent(IEnumerable peoplePictures) + { + var peopleTileContent = new TileBindingContentPeople(); - return peopleTileContent; + foreach (var image in peoplePictures) + { + peopleTileContent.Images.Add(image); } - /// - /// Helper method for creating a tile notification content for using Photos tile template. - /// - /// Sources of pictures that will be used on the photos tile. - /// An instance of represent a payload of a tile notification. - public static TileBindingContentPhotos CreatePhotosTileContent(params Uri[] photoSources) - { - IEnumerable images = photoSources.Select(u => CreateTileBasicImage(u, default(string), default(bool?))); + return peopleTileContent; + } - return CreatePhotosTileContent(images); - } + /// + /// Helper method for creating a tile notification content for using Photos tile template. + /// + /// Sources of pictures that will be used on the photos tile. + /// An instance of represent a payload of a tile notification. + public static TileBindingContentPhotos CreatePhotosTileContent(params Uri[] photoSources) + { + IEnumerable images = photoSources.Select(u => CreateTileBasicImage(u, default(string), default(bool?))); - /// - /// Helper method for creating a tile notification content for using Photos tile template. - /// - /// Sources of pictures with description and addImageQuery indicator that will be used for the photos tile. - /// An instance of represent a payload of a tile notification. - public static TileBindingContentPhotos CreatePhotosTileContent(params (Uri source, string imageAltText, bool? addImageQuery)[] photos) - { - IEnumerable images = photos.Select(t => CreateTileBasicImage(t.source, t.imageAltText, t.addImageQuery)); + return CreatePhotosTileContent(images); + } - return CreatePhotosTileContent(images); - } + /// + /// Helper method for creating a tile notification content for using Photos tile template. + /// + /// Sources of pictures with description and addImageQuery indicator that will be used for the photos tile. + /// An instance of represent a payload of a tile notification. + public static TileBindingContentPhotos CreatePhotosTileContent(params (Uri source, string imageAltText, bool? addImageQuery)[] photos) + { + IEnumerable images = photos.Select(t => CreateTileBasicImage(t.source, t.imageAltText, t.addImageQuery)); - /// - /// Helper method for creating a tile notification content for using Photos tile template. - /// - /// Pictures that will be used for the photos tile. - /// An instance of represent a payload of a tile notification. - public static TileBindingContentPhotos CreatePhotosTileContent(IEnumerable photos) - { - var photoTileContent = new TileBindingContentPhotos(); + return CreatePhotosTileContent(images); + } - foreach (var image in photos) - { - photoTileContent.Images.Add(image); - } + /// + /// Helper method for creating a tile notification content for using Photos tile template. + /// + /// Pictures that will be used for the photos tile. + /// An instance of represent a payload of a tile notification. + public static TileBindingContentPhotos CreatePhotosTileContent(IEnumerable photos) + { + var photoTileContent = new TileBindingContentPhotos(); - return photoTileContent; + foreach (var image in photos) + { + photoTileContent.Images.Add(image); } - private static TileBasicImage CreateTileBasicImage(Uri imageUri, string imageAltText, bool? addImageQuery) - { - var tileImage = new TileBasicImage(); - tileImage.Source = imageUri.OriginalString; + return photoTileContent; + } - if (imageAltText != default(string)) - { - tileImage.AlternateText = imageAltText; - } + private static TileBasicImage CreateTileBasicImage(Uri imageUri, string imageAltText, bool? addImageQuery) + { + var tileImage = new TileBasicImage(); + tileImage.Source = imageUri.OriginalString; - if (addImageQuery != default(bool?)) - { - tileImage.AddImageQuery = addImageQuery; - } + if (imageAltText != default(string)) + { + tileImage.AlternateText = imageAltText; + } - return tileImage; + if (addImageQuery != default(bool?)) + { + tileImage.AddImageQuery = addImageQuery; } + + return tileImage; } +} #pragma warning restore SA1008 #pragma warning restore SA1009 -} + diff --git a/components/Notifications/src/Tiles/Builder/TileContentBuilder.cs b/components/Notifications/src/Tiles/Builder/TileContentBuilder.cs index e8e2cb71c..f6ca87b4c 100644 --- a/components/Notifications/src/Tiles/Builder/TileContentBuilder.cs +++ b/components/Notifications/src/Tiles/Builder/TileContentBuilder.cs @@ -4,524 +4,523 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Builder class used to create +/// +public partial class TileContentBuilder { /// - /// Builder class used to create + /// Flag used to create all tile size (Small , Medium, Large and Wide) /// - public partial class TileContentBuilder - { - /// - /// Flag used to create all tile size (Small , Medium, Large and Wide) - /// - public const TileSize AllSize = TileSize.Small | TileSize.Medium | TileSize.Large | TileSize.Wide; + public const TileSize AllSize = TileSize.Small | TileSize.Medium | TileSize.Large | TileSize.Wide; - /// - /// Gets internal instance of . This is equivalent to the call to . - /// - public TileContent Content - { - get; private set; - } + /// + /// Gets internal instance of . This is equivalent to the call to . + /// + public TileContent Content + { + get; private set; + } - private TileVisual Visual + private TileVisual Visual + { + get { - get + if (Content.Visual == null) { - if (Content.Visual == null) - { - Content.Visual = new TileVisual(); - } - - return Content.Visual; + Content.Visual = new TileVisual(); } + + return Content.Visual; } + } - private TileBinding SmallTile + private TileBinding SmallTile + { + get { - get - { - return Visual.TileSmall; - } - - set - { - Visual.TileSmall = value; - } + return Visual.TileSmall; } - private TileBinding MediumTile + set { - get - { - return Visual.TileMedium; - } - - set - { - Visual.TileMedium = value; - } + Visual.TileSmall = value; } + } - private TileBinding WideTile + private TileBinding MediumTile + { + get { - get - { - return Visual.TileWide; - } - - set - { - Visual.TileWide = value; - } + return Visual.TileMedium; } - private TileBinding LargeTile + set { - get - { - return Visual.TileLarge; - } + Visual.TileMedium = value; + } + } - set - { - Visual.TileLarge = value; - } + private TileBinding WideTile + { + get + { + return Visual.TileWide; } - /// - /// Initializes a new instance of the class. - /// - public TileContentBuilder() + set { - Content = new TileContent(); + Visual.TileWide = value; } + } - /// - /// Add a tile layout size that the notification will be displayed on. - /// - /// The size of tile that the notification will be displayed on. - /// Specialized tile content. Use for special tile template. Default to NULL. - /// The current instance of - public TileContentBuilder AddTile(TileSize size, ITileBindingContent tileContent = null) + private TileBinding LargeTile + { + get { - if (size.HasFlag(TileSize.Small)) - { - SmallTile = new TileBinding(); - SmallTile.Content = tileContent ?? new TileBindingContentAdaptive(); - } + return Visual.TileLarge; + } - if (size.HasFlag(TileSize.Medium)) - { - MediumTile = new TileBinding(); - MediumTile.Content = tileContent ?? new TileBindingContentAdaptive(); - } + set + { + Visual.TileLarge = value; + } + } - if (size.HasFlag(TileSize.Wide)) - { - WideTile = new TileBinding(); - WideTile.Content = tileContent ?? new TileBindingContentAdaptive(); - } + /// + /// Initializes a new instance of the class. + /// + public TileContentBuilder() + { + Content = new TileContent(); + } - if (size.HasFlag(TileSize.Large)) - { - LargeTile = new TileBinding(); - LargeTile.Content = tileContent ?? new TileBindingContentAdaptive(); - } + /// + /// Add a tile layout size that the notification will be displayed on. + /// + /// The size of tile that the notification will be displayed on. + /// Specialized tile content. Use for special tile template. Default to NULL. + /// The current instance of + public TileContentBuilder AddTile(TileSize size, ITileBindingContent tileContent = null) + { + if (size.HasFlag(TileSize.Small)) + { + SmallTile = new TileBinding(); + SmallTile.Content = tileContent ?? new TileBindingContentAdaptive(); + } - return this; + if (size.HasFlag(TileSize.Medium)) + { + MediumTile = new TileBinding(); + MediumTile.Content = tileContent ?? new TileBindingContentAdaptive(); } - /// - /// Set how the tile notification should display the application branding. - /// - /// How branding should appear on the tile - /// The tile size that the parameter should be applied to. Default to all currently supported tile size. - /// The current instance of - public TileContentBuilder SetBranding(TileBranding branding, TileSize size = AllSize) + if (size.HasFlag(TileSize.Wide)) { - if (size == AllSize) - { - // Set on visual. - Visual.Branding = branding; - } - else - { - if (size.HasFlag(TileSize.Small) && SmallTile != null) - { - SmallTile.Branding = branding; - } - - if (size.HasFlag(TileSize.Medium) && MediumTile != null) - { - MediumTile.Branding = branding; - } - - if (size.HasFlag(TileSize.Wide) && WideTile != null) - { - WideTile.Branding = branding; - } - - if (size.HasFlag(TileSize.Large) && LargeTile != null) - { - LargeTile.Branding = branding; - } - } + WideTile = new TileBinding(); + WideTile.Content = tileContent ?? new TileBindingContentAdaptive(); + } - return this; + if (size.HasFlag(TileSize.Large)) + { + LargeTile = new TileBinding(); + LargeTile.Content = tileContent ?? new TileBindingContentAdaptive(); } - /// - /// Set the name that will be used to override the application's name on the tile notification. - /// - /// Custom name to display on the tile in place of the application's name - /// The tile size that parameter should be applied to. Default to all currently supported tile size. - /// The current instance of - public TileContentBuilder SetDisplayName(string displayName, TileSize size = AllSize) + return this; + } + + /// + /// Set how the tile notification should display the application branding. + /// + /// How branding should appear on the tile + /// The tile size that the parameter should be applied to. Default to all currently supported tile size. + /// The current instance of + public TileContentBuilder SetBranding(TileBranding branding, TileSize size = AllSize) + { + if (size == AllSize) { - if (size == AllSize) - { - // Set on visual. - Visual.DisplayName = displayName; - } - else + // Set on visual. + Visual.Branding = branding; + } + else + { + if (size.HasFlag(TileSize.Small) && SmallTile != null) { - if (size.HasFlag(TileSize.Small) && SmallTile != null) - { - SmallTile.DisplayName = displayName; - } - - if (size.HasFlag(TileSize.Medium) && MediumTile != null) - { - MediumTile.DisplayName = displayName; - } - - if (size.HasFlag(TileSize.Wide) && WideTile != null) - { - WideTile.DisplayName = displayName; - } - - if (size.HasFlag(TileSize.Large) && LargeTile != null) - { - LargeTile.DisplayName = displayName; - } + SmallTile.Branding = branding; } - return this; - } - - /// - /// Set the optional background image that stays behind the tile notification. - /// - /// Source of the background image - /// The tile size that the background image should be applied to. Default to all currently supported tile size. - /// Description of the background image, for user of assistance technology - /// - /// Indicating whether Windows should append a query string to the image URI supplied in the Tile notification. - /// Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. - /// This query string specifies scale, contrast setting, and language. - /// - /// The opacity of the black overlay on the background image. - /// Desired cropping of the image. - /// The current instance of - public TileContentBuilder SetBackgroundImage(Uri imageUri, TileSize size = AllSize, string alternateText = default(string), bool? addImageQuery = default(bool?), int? hintOverlay = default(int?), TileBackgroundImageCrop hintCrop = TileBackgroundImageCrop.Default) - { - TileBackgroundImage backgroundImage = new TileBackgroundImage(); - backgroundImage.Source = imageUri.OriginalString; - backgroundImage.HintCrop = hintCrop; - - if (alternateText != default(string)) + if (size.HasFlag(TileSize.Medium) && MediumTile != null) { - backgroundImage.AlternateText = alternateText; + MediumTile.Branding = branding; } - if (addImageQuery != default(bool?)) + if (size.HasFlag(TileSize.Wide) && WideTile != null) { - backgroundImage.AddImageQuery = addImageQuery; + WideTile.Branding = branding; } - if (hintOverlay != default(int?)) + if (size.HasFlag(TileSize.Large) && LargeTile != null) { - backgroundImage.HintOverlay = hintOverlay; + LargeTile.Branding = branding; } - - return SetBackgroundImage(backgroundImage, size); } - /// - /// Set the optional background image that stays behind the tile notification. - /// - /// An instance of as the background image for the tile. - /// The tile size that the background image should be applied to. Default to all currently supported tile size. - /// The current instance of - public TileContentBuilder SetBackgroundImage(TileBackgroundImage backgroundImage, TileSize size = AllSize) + return this; + } + + /// + /// Set the name that will be used to override the application's name on the tile notification. + /// + /// Custom name to display on the tile in place of the application's name + /// The tile size that parameter should be applied to. Default to all currently supported tile size. + /// The current instance of + public TileContentBuilder SetDisplayName(string displayName, TileSize size = AllSize) + { + if (size == AllSize) + { + // Set on visual. + Visual.DisplayName = displayName; + } + else { - // Set to any available tile at the moment of calling. if (size.HasFlag(TileSize.Small) && SmallTile != null) { - GetAdaptiveTileContent(SmallTile).BackgroundImage = backgroundImage; + SmallTile.DisplayName = displayName; } if (size.HasFlag(TileSize.Medium) && MediumTile != null) { - GetAdaptiveTileContent(MediumTile).BackgroundImage = backgroundImage; + MediumTile.DisplayName = displayName; } if (size.HasFlag(TileSize.Wide) && WideTile != null) { - GetAdaptiveTileContent(WideTile).BackgroundImage = backgroundImage; + WideTile.DisplayName = displayName; } if (size.HasFlag(TileSize.Large) && LargeTile != null) { - GetAdaptiveTileContent(LargeTile).BackgroundImage = backgroundImage; + LargeTile.DisplayName = displayName; } + } - return this; - } - - /// - /// Set the Tile's Peek Image that animate from the top of the tile notification. - /// - /// Source of the peek image - /// The tile size that the peek image should be applied to. Default to all currently supported tile size. - /// Description of the peek image, for user of assistance technology - /// - /// Indicating whether Windows should append a query string to the image URI supplied in the Tile notification. - /// Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. - /// This query string specifies scale, contrast setting, and language. - /// - /// The opacity of the black overlay on the peek image. - /// Desired cropping of the image. - /// The current instance of - public TileContentBuilder SetPeekImage(Uri imageUri, TileSize size = AllSize, string alternateText = default(string), bool? addImageQuery = default(bool?), int? hintOverlay = default(int?), TilePeekImageCrop hintCrop = TilePeekImageCrop.Default) - { - TilePeekImage peekImage = new TilePeekImage(); - peekImage.Source = imageUri.OriginalString; - peekImage.HintCrop = hintCrop; - - if (alternateText != default(string)) - { - peekImage.AlternateText = alternateText; - } + return this; + } - if (addImageQuery != default(bool?)) - { - peekImage.AddImageQuery = addImageQuery; - } + /// + /// Set the optional background image that stays behind the tile notification. + /// + /// Source of the background image + /// The tile size that the background image should be applied to. Default to all currently supported tile size. + /// Description of the background image, for user of assistance technology + /// + /// Indicating whether Windows should append a query string to the image URI supplied in the Tile notification. + /// Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. + /// This query string specifies scale, contrast setting, and language. + /// + /// The opacity of the black overlay on the background image. + /// Desired cropping of the image. + /// The current instance of + public TileContentBuilder SetBackgroundImage(Uri imageUri, TileSize size = AllSize, string alternateText = default(string), bool? addImageQuery = default(bool?), int? hintOverlay = default(int?), TileBackgroundImageCrop hintCrop = TileBackgroundImageCrop.Default) + { + TileBackgroundImage backgroundImage = new TileBackgroundImage(); + backgroundImage.Source = imageUri.OriginalString; + backgroundImage.HintCrop = hintCrop; - if (hintOverlay != default(int?)) - { - peekImage.HintOverlay = hintOverlay; - } + if (alternateText != default(string)) + { + backgroundImage.AlternateText = alternateText; + } - return SetPeekImage(peekImage, size); + if (addImageQuery != default(bool?)) + { + backgroundImage.AddImageQuery = addImageQuery; } - /// - /// Set the Tile's Peek Image that animate from the top of the tile notification. - /// - /// An instance of for the Tile's peek image - /// The tile size that the peek image should be applied to. Default to all currently supported tile size. - /// The current instance of - public TileContentBuilder SetPeekImage(TilePeekImage peekImage, TileSize size = AllSize) + if (hintOverlay != default(int?)) { - // Set to any available tile at the moment of calling. - if (size.HasFlag(TileSize.Small) && SmallTile != null) - { - GetAdaptiveTileContent(SmallTile).PeekImage = peekImage; - } + backgroundImage.HintOverlay = hintOverlay; + } - if (size.HasFlag(TileSize.Medium) && MediumTile != null) - { - GetAdaptiveTileContent(MediumTile).PeekImage = peekImage; - } + return SetBackgroundImage(backgroundImage, size); + } - if (size.HasFlag(TileSize.Wide) && WideTile != null) - { - GetAdaptiveTileContent(WideTile).PeekImage = peekImage; - } + /// + /// Set the optional background image that stays behind the tile notification. + /// + /// An instance of as the background image for the tile. + /// The tile size that the background image should be applied to. Default to all currently supported tile size. + /// The current instance of + public TileContentBuilder SetBackgroundImage(TileBackgroundImage backgroundImage, TileSize size = AllSize) + { + // Set to any available tile at the moment of calling. + if (size.HasFlag(TileSize.Small) && SmallTile != null) + { + GetAdaptiveTileContent(SmallTile).BackgroundImage = backgroundImage; + } - if (size.HasFlag(TileSize.Large) && LargeTile != null) - { - GetAdaptiveTileContent(LargeTile).PeekImage = peekImage; - } + if (size.HasFlag(TileSize.Medium) && MediumTile != null) + { + GetAdaptiveTileContent(MediumTile).BackgroundImage = backgroundImage; + } - return this; + if (size.HasFlag(TileSize.Wide) && WideTile != null) + { + GetAdaptiveTileContent(WideTile).BackgroundImage = backgroundImage; } - /// - /// Set the text stacking (vertical alignment) of the entire binding element. - /// - /// Text Stacking Option - /// The tile size that the peek image should be applied to. Default to all currently supported tile size. - /// The current instance of - public TileContentBuilder SetTextStacking(TileTextStacking textStacking, TileSize size = AllSize) + if (size.HasFlag(TileSize.Large) && LargeTile != null) { - // Set to any available tile at the moment of calling. - if (size.HasFlag(TileSize.Small) && SmallTile != null) - { - GetAdaptiveTileContent(SmallTile).TextStacking = textStacking; - } + GetAdaptiveTileContent(LargeTile).BackgroundImage = backgroundImage; + } - if (size.HasFlag(TileSize.Medium) && MediumTile != null) - { - GetAdaptiveTileContent(MediumTile).TextStacking = textStacking; - } + return this; + } - if (size.HasFlag(TileSize.Wide) && WideTile != null) - { - GetAdaptiveTileContent(WideTile).TextStacking = textStacking; - } + /// + /// Set the Tile's Peek Image that animate from the top of the tile notification. + /// + /// Source of the peek image + /// The tile size that the peek image should be applied to. Default to all currently supported tile size. + /// Description of the peek image, for user of assistance technology + /// + /// Indicating whether Windows should append a query string to the image URI supplied in the Tile notification. + /// Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. + /// This query string specifies scale, contrast setting, and language. + /// + /// The opacity of the black overlay on the peek image. + /// Desired cropping of the image. + /// The current instance of + public TileContentBuilder SetPeekImage(Uri imageUri, TileSize size = AllSize, string alternateText = default(string), bool? addImageQuery = default(bool?), int? hintOverlay = default(int?), TilePeekImageCrop hintCrop = TilePeekImageCrop.Default) + { + TilePeekImage peekImage = new TilePeekImage(); + peekImage.Source = imageUri.OriginalString; + peekImage.HintCrop = hintCrop; - if (size.HasFlag(TileSize.Large) && LargeTile != null) - { - GetAdaptiveTileContent(LargeTile).TextStacking = textStacking; - } + if (alternateText != default(string)) + { + peekImage.AlternateText = alternateText; + } - return this; + if (addImageQuery != default(bool?)) + { + peekImage.AddImageQuery = addImageQuery; } - /// - /// Set the tile's activation arguments for tile notification. - /// - /// App-Defined custom arguments that will be passed in when the user click on the tile when this tile notification is being displayed. - /// The tile size that the custom argument should be applied to. Default to all currently supported tile size. - /// The current instance of - public TileContentBuilder SetActivationArgument(string args, TileSize size = AllSize) + if (hintOverlay != default(int?)) { - if (size == AllSize) - { - Visual.Arguments = args; - } - else - { - if (size.HasFlag(TileSize.Small) && SmallTile != null) - { - SmallTile.Arguments = args; - } - - if (size.HasFlag(TileSize.Medium) && MediumTile != null) - { - MediumTile.Arguments = args; - } - - if (size.HasFlag(TileSize.Wide) && WideTile != null) - { - WideTile.Arguments = args; - } - - if (size.HasFlag(TileSize.Large) && LargeTile != null) - { - LargeTile.Arguments = args; - } - } + peekImage.HintOverlay = hintOverlay; + } - return this; - } - - /// - /// Add a custom text that will appear on the tile notification. - /// - /// Custom text to display on the tile. - /// The tile size that the custom text would be added to. Default to all currently supported tile size. - /// Style that controls the text's font size, weight, and opacity. - /// Indicating whether text wrapping is enabled. For Tiles, this is false by default. - /// The maximum number of lines the text element is allowed to display. For Tiles, this is infinity by default - /// The minimum number of lines the text element must display. - /// The horizontal alignment of the text - /// - /// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. - /// - /// The current instance of - public TileContentBuilder AddText(string text, TileSize size = AllSize, AdaptiveTextStyle? hintStyle = null, bool? hintWrap = default(bool?), int? hintMaxLines = default(int?), int? hintMinLines = default(int?), AdaptiveTextAlign? hintAlign = null, string language = default(string)) - { - // Create the adaptive text. - AdaptiveText adaptive = new AdaptiveText() - { - Text = text - }; + return SetPeekImage(peekImage, size); + } - if (hintStyle != null) - { - adaptive.HintStyle = hintStyle.Value; - } + /// + /// Set the Tile's Peek Image that animate from the top of the tile notification. + /// + /// An instance of for the Tile's peek image + /// The tile size that the peek image should be applied to. Default to all currently supported tile size. + /// The current instance of + public TileContentBuilder SetPeekImage(TilePeekImage peekImage, TileSize size = AllSize) + { + // Set to any available tile at the moment of calling. + if (size.HasFlag(TileSize.Small) && SmallTile != null) + { + GetAdaptiveTileContent(SmallTile).PeekImage = peekImage; + } - if (hintAlign != null) - { - adaptive.HintAlign = hintAlign.Value; - } + if (size.HasFlag(TileSize.Medium) && MediumTile != null) + { + GetAdaptiveTileContent(MediumTile).PeekImage = peekImage; + } - if (hintWrap != default(bool?)) - { - adaptive.HintWrap = hintWrap; - } + if (size.HasFlag(TileSize.Wide) && WideTile != null) + { + GetAdaptiveTileContent(WideTile).PeekImage = peekImage; + } - if (hintMaxLines != default(int?)) - { - adaptive.HintMaxLines = hintMaxLines; - } + if (size.HasFlag(TileSize.Large) && LargeTile != null) + { + GetAdaptiveTileContent(LargeTile).PeekImage = peekImage; + } - if (hintMinLines != default(int?) && hintMinLines > 0) - { - adaptive.HintMinLines = hintMinLines; - } + return this; + } - if (language != default(string)) - { - adaptive.Language = language; - } + /// + /// Set the text stacking (vertical alignment) of the entire binding element. + /// + /// Text Stacking Option + /// The tile size that the peek image should be applied to. Default to all currently supported tile size. + /// The current instance of + public TileContentBuilder SetTextStacking(TileTextStacking textStacking, TileSize size = AllSize) + { + // Set to any available tile at the moment of calling. + if (size.HasFlag(TileSize.Small) && SmallTile != null) + { + GetAdaptiveTileContent(SmallTile).TextStacking = textStacking; + } - // Add to the tile content - return AddAdaptiveTileVisualChild(adaptive, size); + if (size.HasFlag(TileSize.Medium) && MediumTile != null) + { + GetAdaptiveTileContent(MediumTile).TextStacking = textStacking; } - /// - /// Add an adaptive child to the tile notification. - /// - /// An adaptive child to add - /// Tile size that the adaptive child should be added to. Default to all currently supported tile size. - /// The current instance of - /// - /// This can be used to add Group and Subgroup to the tile. - /// - public TileContentBuilder AddAdaptiveTileVisualChild(ITileBindingContentAdaptiveChild child, TileSize size = AllSize) + if (size.HasFlag(TileSize.Wide) && WideTile != null) { - if (size.HasFlag(TileSize.Small) && SmallTile != null && GetAdaptiveTileContent(SmallTile) != null) + GetAdaptiveTileContent(WideTile).TextStacking = textStacking; + } + + if (size.HasFlag(TileSize.Large) && LargeTile != null) + { + GetAdaptiveTileContent(LargeTile).TextStacking = textStacking; + } + + return this; + } + + /// + /// Set the tile's activation arguments for tile notification. + /// + /// App-Defined custom arguments that will be passed in when the user click on the tile when this tile notification is being displayed. + /// The tile size that the custom argument should be applied to. Default to all currently supported tile size. + /// The current instance of + public TileContentBuilder SetActivationArgument(string args, TileSize size = AllSize) + { + if (size == AllSize) + { + Visual.Arguments = args; + } + else + { + if (size.HasFlag(TileSize.Small) && SmallTile != null) { - GetAdaptiveTileContent(SmallTile).Children.Add(child); + SmallTile.Arguments = args; } - if (size.HasFlag(TileSize.Medium) && MediumTile != null && GetAdaptiveTileContent(MediumTile) != null) + if (size.HasFlag(TileSize.Medium) && MediumTile != null) { - GetAdaptiveTileContent(MediumTile).Children.Add(child); + MediumTile.Arguments = args; } - if (size.HasFlag(TileSize.Wide) && WideTile != null && GetAdaptiveTileContent(WideTile) != null) + if (size.HasFlag(TileSize.Wide) && WideTile != null) { - GetAdaptiveTileContent(WideTile).Children.Add(child); + WideTile.Arguments = args; } - if (size.HasFlag(TileSize.Large) && LargeTile != null && GetAdaptiveTileContent(LargeTile) != null) + if (size.HasFlag(TileSize.Large) && LargeTile != null) { - GetAdaptiveTileContent(LargeTile).Children.Add(child); + LargeTile.Arguments = args; } + } + + return this; + } + + /// + /// Add a custom text that will appear on the tile notification. + /// + /// Custom text to display on the tile. + /// The tile size that the custom text would be added to. Default to all currently supported tile size. + /// Style that controls the text's font size, weight, and opacity. + /// Indicating whether text wrapping is enabled. For Tiles, this is false by default. + /// The maximum number of lines the text element is allowed to display. For Tiles, this is infinity by default + /// The minimum number of lines the text element must display. + /// The horizontal alignment of the text + /// + /// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. + /// + /// The current instance of + public TileContentBuilder AddText(string text, TileSize size = AllSize, AdaptiveTextStyle? hintStyle = null, bool? hintWrap = default(bool?), int? hintMaxLines = default(int?), int? hintMinLines = default(int?), AdaptiveTextAlign? hintAlign = null, string language = default(string)) + { + // Create the adaptive text. + AdaptiveText adaptive = new AdaptiveText() + { + Text = text + }; + + if (hintStyle != null) + { + adaptive.HintStyle = hintStyle.Value; + } + + if (hintAlign != null) + { + adaptive.HintAlign = hintAlign.Value; + } - return this; + if (hintWrap != default(bool?)) + { + adaptive.HintWrap = hintWrap; + } + + if (hintMaxLines != default(int?)) + { + adaptive.HintMaxLines = hintMaxLines; + } + + if (hintMinLines != default(int?) && hintMinLines > 0) + { + adaptive.HintMinLines = hintMinLines; + } + + if (language != default(string)) + { + adaptive.Language = language; + } + + // Add to the tile content + return AddAdaptiveTileVisualChild(adaptive, size); + } + + /// + /// Add an adaptive child to the tile notification. + /// + /// An adaptive child to add + /// Tile size that the adaptive child should be added to. Default to all currently supported tile size. + /// The current instance of + /// + /// This can be used to add Group and Subgroup to the tile. + /// + public TileContentBuilder AddAdaptiveTileVisualChild(ITileBindingContentAdaptiveChild child, TileSize size = AllSize) + { + if (size.HasFlag(TileSize.Small) && SmallTile != null && GetAdaptiveTileContent(SmallTile) != null) + { + GetAdaptiveTileContent(SmallTile).Children.Add(child); + } + + if (size.HasFlag(TileSize.Medium) && MediumTile != null && GetAdaptiveTileContent(MediumTile) != null) + { + GetAdaptiveTileContent(MediumTile).Children.Add(child); } - /// - /// Get the instance of that has been built by the builder with specified configuration so far. - /// - /// An instance of that can be used to create tile notification. - public TileContent GetTileContent() + if (size.HasFlag(TileSize.Wide) && WideTile != null && GetAdaptiveTileContent(WideTile) != null) { - return Content; + GetAdaptiveTileContent(WideTile).Children.Add(child); } - private TileBindingContentAdaptive GetAdaptiveTileContent(TileBinding binding) + if (size.HasFlag(TileSize.Large) && LargeTile != null && GetAdaptiveTileContent(LargeTile) != null) { - return binding.Content as TileBindingContentAdaptive; + GetAdaptiveTileContent(LargeTile).Children.Add(child); } + + return this; + } + + /// + /// Get the instance of that has been built by the builder with specified configuration so far. + /// + /// An instance of that can be used to create tile notification. + public TileContent GetTileContent() + { + return Content; + } + + private TileBindingContentAdaptive GetAdaptiveTileContent(TileBinding binding) + { + return binding.Content as TileBindingContentAdaptive; } } diff --git a/components/Notifications/src/Tiles/Elements/Element_Tile.cs b/components/Notifications/src/Tiles/Elements/Element_Tile.cs index de1db439c..3cacc013b 100644 --- a/components/Notifications/src/Tiles/Elements/Element_Tile.cs +++ b/components/Notifications/src/Tiles/Elements/Element_Tile.cs @@ -4,16 +4,15 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_Tile : BaseElement, IHaveXmlName, IHaveXmlChildren { - internal sealed class Element_Tile : BaseElement, IHaveXmlName, IHaveXmlChildren - { - public Element_TileVisual Visual { get; set; } + public Element_TileVisual Visual { get; set; } - /// - string IHaveXmlName.Name => "tile"; + /// + string IHaveXmlName.Name => "tile"; - /// - IEnumerable IHaveXmlChildren.Children => new[] { Visual }; - } + /// + IEnumerable IHaveXmlChildren.Children => new[] { Visual }; } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/Elements/Element_TileBinding.cs b/components/Notifications/src/Tiles/Elements/Element_TileBinding.cs index 1125354e7..7250b294a 100644 --- a/components/Notifications/src/Tiles/Elements/Element_TileBinding.cs +++ b/components/Notifications/src/Tiles/Elements/Element_TileBinding.cs @@ -5,142 +5,141 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_TileBinding : IElementWithDescendants, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren { - internal sealed class Element_TileBinding : IElementWithDescendants, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren + internal const TileBranding DEFAULT_BRANDING = TileBranding.Auto; + internal const TileTextStacking DEFAULT_TEXT_STACKING = TileTextStacking.Top; + internal const int DEFAULT_OVERLAY = 20; + + public Element_TileBinding(TileTemplateNameV3 template) { - internal const TileBranding DEFAULT_BRANDING = TileBranding.Auto; - internal const TileTextStacking DEFAULT_TEXT_STACKING = TileTextStacking.Top; - internal const int DEFAULT_OVERLAY = 20; + Template = template; + } - public Element_TileBinding(TileTemplateNameV3 template) + public TileTemplateNameV3 Template { get; private set; } + + /// + /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of + /// + /// "www.website.com/images/hello.png" + /// + /// included in the notification becomes + /// + /// "www.website.com/images/hello.png?ms-scale=100&ms-contrast=standard&ms-lang=en-us" + /// + public bool? AddImageQuery { get; set; } + + /// + /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. + /// + public Uri BaseUri { get; set; } + + /// + /// Gets or sets the form that the Tile should use to display the app's brand. + /// + public TileBranding Branding { get; set; } = DEFAULT_BRANDING; + + /// + /// Gets or sets a sender-defined string that uniquely identifies the content of the notification. This prevents duplicates in the situation where a large Tile template is displaying the last three wide Tile notifications. + /// + /// Required: NO + /// + public string ContentId { get; set; } + + /// + /// Gets or sets an optional string to override the Tile's display name while showing this notification. + /// + public string DisplayName { get; set; } + + /// + /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides that in visual, but can be overridden by that in text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. See Remarks for when this value isn't specified. + /// + public string Language { get; set; } + + public string LockDetailedStatus1 { get; set; } + + public string LockDetailedStatus2 { get; set; } + + public string LockDetailedStatus3 { get; set; } + + public string Arguments { get; set; } + + /// + /// Throws exception if value is invalid + /// + /// Overlay value (0-100) + internal static void CheckOverlayValue(int value) + { + if (value < 0 || value > 100) { - Template = template; - } - - public TileTemplateNameV3 Template { get; private set; } - - /// - /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of - /// - /// "www.website.com/images/hello.png" - /// - /// included in the notification becomes - /// - /// "www.website.com/images/hello.png?ms-scale=100&ms-contrast=standard&ms-lang=en-us" - /// - public bool? AddImageQuery { get; set; } - - /// - /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. - /// - public Uri BaseUri { get; set; } - - /// - /// Gets or sets the form that the Tile should use to display the app's brand. - /// - public TileBranding Branding { get; set; } = DEFAULT_BRANDING; - - /// - /// Gets or sets a sender-defined string that uniquely identifies the content of the notification. This prevents duplicates in the situation where a large Tile template is displaying the last three wide Tile notifications. - /// - /// Required: NO - /// - public string ContentId { get; set; } - - /// - /// Gets or sets an optional string to override the Tile's display name while showing this notification. - /// - public string DisplayName { get; set; } - - /// - /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides that in visual, but can be overridden by that in text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. See Remarks for when this value isn't specified. - /// - public string Language { get; set; } - - public string LockDetailedStatus1 { get; set; } - - public string LockDetailedStatus2 { get; set; } - - public string LockDetailedStatus3 { get; set; } - - public string Arguments { get; set; } - - /// - /// Throws exception if value is invalid - /// - /// Overlay value (0-100) - internal static void CheckOverlayValue(int value) - { - if (value < 0 || value > 100) - { - throw new ArgumentOutOfRangeException("Overlay must be between 0 and 100, inclusive."); - } + throw new ArgumentOutOfRangeException("Overlay must be between 0 and 100, inclusive."); } + } - public TilePresentation? Presentation { get; set; } + public TilePresentation? Presentation { get; set; } - public TileTextStacking TextStacking { get; set; } = DEFAULT_TEXT_STACKING; + public TileTextStacking TextStacking { get; set; } = DEFAULT_TEXT_STACKING; - public IList Children { get; private set; } = new List(); + public IList Children { get; private set; } = new List(); - /// - /// Generates an enumerable collection of children and all those children's children - /// - /// Enumerable collection of children and all those children's children. - public IEnumerable Descendants() + /// + /// Generates an enumerable collection of children and all those children's children + /// + /// Enumerable collection of children and all those children's children. + public IEnumerable Descendants() + { + foreach (IElement_TileBindingChild child in Children) { - foreach (IElement_TileBindingChild child in Children) - { - // Return the child - yield return child; + // Return the child + yield return child; - // And if it has descendants, return the descendants - if (child is IElementWithDescendants) + // And if it has descendants, return the descendants + if (child is IElementWithDescendants) + { + foreach (object descendant in (child as IElementWithDescendants).Descendants()) { - foreach (object descendant in (child as IElementWithDescendants).Descendants()) - { - yield return descendant; - } + yield return descendant; } } } + } - /// - string IHaveXmlName.Name => "binding"; + /// + string IHaveXmlName.Name => "binding"; - /// - IEnumerable IHaveXmlChildren.Children => Children; + /// + IEnumerable IHaveXmlChildren.Children => Children; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("template", Template); - yield return new("addImageQuery", AddImageQuery); - yield return new("baseUri", BaseUri); + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("template", Template); + yield return new("addImageQuery", AddImageQuery); + yield return new("baseUri", BaseUri); - if (Branding != DEFAULT_BRANDING) - { - yield return new("branding", Branding); - } + if (Branding != DEFAULT_BRANDING) + { + yield return new("branding", Branding); + } - yield return new("contentId", ContentId); - yield return new("displayName", DisplayName); - yield return new("lang", Language); - yield return new("hint-lockDetailedStatus1", LockDetailedStatus1); - yield return new("hint-lockDetailedStatus2", LockDetailedStatus2); - yield return new("hint-lockDetailedStatus3", LockDetailedStatus3); - yield return new("arguments", Arguments); - yield return new("hint-presentation", Presentation.ToPascalCaseString()); + yield return new("contentId", ContentId); + yield return new("displayName", DisplayName); + yield return new("lang", Language); + yield return new("hint-lockDetailedStatus1", LockDetailedStatus1); + yield return new("hint-lockDetailedStatus2", LockDetailedStatus2); + yield return new("hint-lockDetailedStatus3", LockDetailedStatus3); + yield return new("arguments", Arguments); + yield return new("hint-presentation", Presentation.ToPascalCaseString()); - if (TextStacking != DEFAULT_TEXT_STACKING) - { - yield return new("hint-textStacking", TextStacking.ToPascalCaseString()); - } + if (TextStacking != DEFAULT_TEXT_STACKING) + { + yield return new("hint-textStacking", TextStacking.ToPascalCaseString()); } } +} - internal interface IElement_TileBindingChild - { - } +internal interface IElement_TileBindingChild +{ } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/Elements/Element_TileVisual.cs b/components/Notifications/src/Tiles/Elements/Element_TileVisual.cs index d4a59a30f..71dfc5726 100644 --- a/components/Notifications/src/Tiles/Elements/Element_TileVisual.cs +++ b/components/Notifications/src/Tiles/Elements/Element_TileVisual.cs @@ -5,50 +5,49 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_TileVisual : IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren { - internal sealed class Element_TileVisual : IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren - { - internal const TileBranding DEFAULT_BRANDING = TileBranding.Auto; - internal const bool DEFAULT_ADD_IMAGE_QUERY = false; + internal const TileBranding DEFAULT_BRANDING = TileBranding.Auto; + internal const bool DEFAULT_ADD_IMAGE_QUERY = false; - public bool? AddImageQuery { get; set; } + public bool? AddImageQuery { get; set; } - public Uri BaseUri { get; set; } + public Uri BaseUri { get; set; } - public TileBranding Branding { get; set; } = DEFAULT_BRANDING; + public TileBranding Branding { get; set; } = DEFAULT_BRANDING; - public string ContentId { get; set; } + public string ContentId { get; set; } - public string DisplayName { get; set; } + public string DisplayName { get; set; } - public string Language { get; set; } + public string Language { get; set; } - public string Arguments { get; set; } + public string Arguments { get; set; } - public IList Bindings { get; private set; } = new List(); + public IList Bindings { get; private set; } = new List(); - /// - string IHaveXmlName.Name => "visual"; + /// + string IHaveXmlName.Name => "visual"; - /// - IEnumerable IHaveXmlChildren.Children => Bindings; + /// + IEnumerable IHaveXmlChildren.Children => Bindings; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("addImageQuery", AddImageQuery); + yield return new("baseUri", BaseUri); + + if (Branding != DEFAULT_BRANDING) { - yield return new("addImageQuery", AddImageQuery); - yield return new("baseUri", BaseUri); - - if (Branding != DEFAULT_BRANDING) - { - yield return new("branding", Branding.ToPascalCaseString()); - } - - yield return new("contentId", ContentId); - yield return new("displayName", DisplayName); - yield return new("lang", Language); - yield return new("arguments", Arguments); + yield return new("branding", Branding.ToPascalCaseString()); } + + yield return new("contentId", ContentId); + yield return new("displayName", DisplayName); + yield return new("lang", Language); + yield return new("arguments", Arguments); } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/Elements/TileElementsCommon.cs b/components/Notifications/src/Tiles/Elements/TileElementsCommon.cs index f5b808fdd..e7c63cbed 100644 --- a/components/Notifications/src/Tiles/Elements/TileElementsCommon.cs +++ b/components/Notifications/src/Tiles/Elements/TileElementsCommon.cs @@ -2,19 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal enum TilePresentation { - internal enum TilePresentation - { - People, - Photos, - Contact - } + People, + Photos, + Contact +} - internal enum TileImagePlacement - { - Inline, - Background, - Peek - } +internal enum TileImagePlacement +{ + Inline, + Background, + Peek } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/ITileBindingContentAdaptiveChild.cs b/components/Notifications/src/Tiles/ITileBindingContentAdaptiveChild.cs index 5c9ad93e8..e5ec0eb5a 100644 --- a/components/Notifications/src/Tiles/ITileBindingContentAdaptiveChild.cs +++ b/components/Notifications/src/Tiles/ITileBindingContentAdaptiveChild.cs @@ -2,13 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Elements that can be direct children of , including (, , and ). +/// +public interface ITileBindingContentAdaptiveChild { - /// - /// Elements that can be direct children of , including (, , and ). - /// - public interface ITileBindingContentAdaptiveChild - { - // Blank interface simply for compile-enforcing the child types in the list. - } + // Blank interface simply for compile-enforcing the child types in the list. } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentContact.cs b/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentContact.cs index 865bb849e..9af5c5f6b 100644 --- a/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentContact.cs +++ b/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentContact.cs @@ -2,42 +2,41 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Phone-only. Supported on Small, Medium, and Wide. +/// +public sealed class TileBindingContentContact : ITileBindingContent { /// - /// Phone-only. Supported on Small, Medium, and Wide. + /// Gets or sets the image to display. /// - public sealed class TileBindingContentContact : ITileBindingContent + public TileBasicImage Image { get; set; } + + /// + /// Gets or sets a line of text that is displayed. Not displayed on Small Tile. + /// + public TileBasicText Text { get; set; } + + internal TileTemplateNameV3 GetTemplateName(TileSize size) { - /// - /// Gets or sets the image to display. - /// - public TileBasicImage Image { get; set; } + return TileSizeToAdaptiveTemplateConverter.Convert(size); + } - /// - /// Gets or sets a line of text that is displayed. Not displayed on Small Tile. - /// - public TileBasicText Text { get; set; } + internal void PopulateElement(Element_TileBinding binding, TileSize size) + { + binding.Presentation = TilePresentation.Contact; - internal TileTemplateNameV3 GetTemplateName(TileSize size) + // Small size doesn't display the text, so no reason to include it in the payload + if (Text != null && size != TileSize.Small) { - return TileSizeToAdaptiveTemplateConverter.Convert(size); + binding.Children.Add(Text.ConvertToElement()); } - internal void PopulateElement(Element_TileBinding binding, TileSize size) + if (Image != null) { - binding.Presentation = TilePresentation.Contact; - - // Small size doesn't display the text, so no reason to include it in the payload - if (Text != null && size != TileSize.Small) - { - binding.Children.Add(Text.ConvertToElement()); - } - - if (Image != null) - { - binding.Children.Add(Image.ConvertToElement()); - } + binding.Children.Add(Image.ConvertToElement()); } } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentIconic.cs b/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentIconic.cs index 686278736..d4ea949d6 100644 --- a/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentIconic.cs +++ b/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentIconic.cs @@ -4,41 +4,40 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Supported on Small and Medium. Enables an iconic Tile template, where you can have an icon and badge display next to each other on the Tile, in true classic Windows Phone style. The number next to the icon is achieved through a separate badge notification. +/// +public sealed class TileBindingContentIconic : ITileBindingContent { /// - /// Supported on Small and Medium. Enables an iconic Tile template, where you can have an icon and badge display next to each other on the Tile, in true classic Windows Phone style. The number next to the icon is achieved through a separate badge notification. + /// Gets or sets, at minimum, to support both Desktop and Phone, Small and Medium tiles, a square aspect ratio image with a resolution of 200x200, PNG format, with transparency and no color other than white. For more info see: http://blogs.msdn.com/b/tiles_and_toasts/archive/2015/07/31/iconic-tile-template-for-windows-10.aspx /// - public sealed class TileBindingContentIconic : ITileBindingContent - { - /// - /// Gets or sets, at minimum, to support both Desktop and Phone, Small and Medium tiles, a square aspect ratio image with a resolution of 200x200, PNG format, with transparency and no color other than white. For more info see: http://blogs.msdn.com/b/tiles_and_toasts/archive/2015/07/31/iconic-tile-template-for-windows-10.aspx - /// - public TileBasicImage Icon { get; set; } + public TileBasicImage Icon { get; set; } - internal TileTemplateNameV3 GetTemplateName(TileSize size) + internal TileTemplateNameV3 GetTemplateName(TileSize size) + { + switch (size) { - switch (size) - { - case TileSize.Small: - return TileTemplateNameV3.TileSquare71x71IconWithBadge; + case TileSize.Small: + return TileTemplateNameV3.TileSquare71x71IconWithBadge; - case TileSize.Medium: - return TileTemplateNameV3.TileSquare150x150IconWithBadge; + case TileSize.Medium: + return TileTemplateNameV3.TileSquare150x150IconWithBadge; - default: - throw new ArgumentException("The Iconic template is only supported on Small and Medium tiles."); - } + default: + throw new ArgumentException("The Iconic template is only supported on Small and Medium tiles."); } + } - internal void PopulateElement(Element_TileBinding binding, TileSize size) + internal void PopulateElement(Element_TileBinding binding, TileSize size) + { + if (Icon != null) { - if (Icon != null) - { - var element = Icon.ConvertToElement(); - element.Id = 1; - binding.Children.Add(element); - } + var element = Icon.ConvertToElement(); + element.Id = 1; + binding.Children.Add(element); } } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentPeople.cs b/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentPeople.cs index 4f5fdcd42..46eab82b3 100644 --- a/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentPeople.cs +++ b/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentPeople.cs @@ -4,32 +4,31 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// New in 1511: Supported on Medium, Wide, and Large (Desktop and Mobile). +/// Previously for RTM: Phone-only. Supported on Medium and Wide. +/// +public sealed class TileBindingContentPeople : ITileBindingContent { /// - /// New in 1511: Supported on Medium, Wide, and Large (Desktop and Mobile). - /// Previously for RTM: Phone-only. Supported on Medium and Wide. + /// Gets images that will roll around as circles. /// - public sealed class TileBindingContentPeople : ITileBindingContent + public IList Images { get; private set; } = new List(); + + internal TileTemplateNameV3 GetTemplateName(TileSize size) { - /// - /// Gets images that will roll around as circles. - /// - public IList Images { get; private set; } = new List(); + return TileSizeToAdaptiveTemplateConverter.Convert(size); + } - internal TileTemplateNameV3 GetTemplateName(TileSize size) - { - return TileSizeToAdaptiveTemplateConverter.Convert(size); - } + internal void PopulateElement(Element_TileBinding binding, TileSize size) + { + binding.Presentation = TilePresentation.People; - internal void PopulateElement(Element_TileBinding binding, TileSize size) + foreach (var img in Images) { - binding.Presentation = TilePresentation.People; - - foreach (var img in Images) - { - binding.Children.Add(img.ConvertToElement()); - } + binding.Children.Add(img.ConvertToElement()); } } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentPhotos.cs b/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentPhotos.cs index baa5de892..0774bef81 100644 --- a/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentPhotos.cs +++ b/components/Notifications/src/Tiles/SpecialTemplates/TileBindingContentPhotos.cs @@ -4,31 +4,30 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Animates through a slide show of photos. Supported on all sizes. +/// +public sealed class TileBindingContentPhotos : ITileBindingContent { /// - /// Animates through a slide show of photos. Supported on all sizes. + /// Gets the collection of slide show images. Up to 12 images can be provided (Mobile will only display up to 9), which will be used for the slide show. Adding more than 12 will throw an exception. /// - public sealed class TileBindingContentPhotos : ITileBindingContent + public IList Images { get; private set; } = new LimitedList(12); + + internal TileTemplateNameV3 GetTemplateName(TileSize size) { - /// - /// Gets the collection of slide show images. Up to 12 images can be provided (Mobile will only display up to 9), which will be used for the slide show. Adding more than 12 will throw an exception. - /// - public IList Images { get; private set; } = new LimitedList(12); + return TileSizeToAdaptiveTemplateConverter.Convert(size); + } - internal TileTemplateNameV3 GetTemplateName(TileSize size) - { - return TileSizeToAdaptiveTemplateConverter.Convert(size); - } + internal void PopulateElement(Element_TileBinding binding, TileSize size) + { + binding.Presentation = TilePresentation.Photos; - internal void PopulateElement(Element_TileBinding binding, TileSize size) + foreach (var img in Images) { - binding.Presentation = TilePresentation.Photos; - - foreach (var img in Images) - { - binding.Children.Add(img.ConvertToElement()); - } + binding.Children.Add(img.ConvertToElement()); } } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileBackgroundImage.cs b/components/Notifications/src/Tiles/TileBackgroundImage.cs index b326d2825..556cbe523 100644 --- a/components/Notifications/src/Tiles/TileBackgroundImage.cs +++ b/components/Notifications/src/Tiles/TileBackgroundImage.cs @@ -4,87 +4,86 @@ using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A full-bleed background image that appears beneath the Tile content. +/// +public sealed class TileBackgroundImage : IBaseImage { + private string _source; + /// - /// A full-bleed background image that appears beneath the Tile content. + /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. /// - public sealed class TileBackgroundImage : IBaseImage + public string Source { - private string _source; + get { return _source; } + set { BaseImageHelper.SetSource(ref _source, value); } + } - /// - /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. - /// - public string Source - { - get { return _source; } - set { BaseImageHelper.SetSource(ref _source, value); } - } + /// + /// Gets or sets a description of the image, for users of assistive technologies. + /// + public string AlternateText { get; set; } - /// - /// Gets or sets a description of the image, for users of assistive technologies. - /// - public string AlternateText { get; set; } + /// + /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. + /// + public bool? AddImageQuery { get; set; } - /// - /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. - /// - public bool? AddImageQuery { get; set; } + private int? _hintOverlay; - private int? _hintOverlay; + /// + /// Gets or sets a black overlay on the background image. This value controls the opacity of the black overlay, with 0 being no overlay and 100 being completely black. Defaults to 20. + /// + public int? HintOverlay + { + get + { + return _hintOverlay; + } - /// - /// Gets or sets a black overlay on the background image. This value controls the opacity of the black overlay, with 0 being no overlay and 100 being completely black. Defaults to 20. - /// - public int? HintOverlay + set { - get + if (value != null) { - return _hintOverlay; + Element_TileBinding.CheckOverlayValue(value.Value); } - set - { - if (value != null) - { - Element_TileBinding.CheckOverlayValue(value.Value); - } - - _hintOverlay = value; - } + _hintOverlay = value; } + } - /// - /// Gets or sets the desired cropping of the image. - /// Previously for RTM: Did not exist, value will be ignored and background image will be displayed without any cropping. - /// - public TileBackgroundImageCrop HintCrop { get; set; } + /// + /// Gets or sets the desired cropping of the image. + /// Previously for RTM: Did not exist, value will be ignored and background image will be displayed without any cropping. + /// + public TileBackgroundImageCrop HintCrop { get; set; } - internal Element_AdaptiveImage ConvertToElement() - { - Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this); + internal Element_AdaptiveImage ConvertToElement() + { + Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this); - image.Placement = AdaptiveImagePlacement.Background; - image.Crop = GetAdaptiveImageCrop(); - image.Overlay = HintOverlay; + image.Placement = AdaptiveImagePlacement.Background; + image.Crop = GetAdaptiveImageCrop(); + image.Overlay = HintOverlay; - return image; - } + return image; + } - private AdaptiveImageCrop GetAdaptiveImageCrop() + private AdaptiveImageCrop GetAdaptiveImageCrop() + { + switch (HintCrop) { - switch (HintCrop) - { - case TileBackgroundImageCrop.Circle: - return AdaptiveImageCrop.Circle; + case TileBackgroundImageCrop.Circle: + return AdaptiveImageCrop.Circle; - case TileBackgroundImageCrop.None: - return AdaptiveImageCrop.None; + case TileBackgroundImageCrop.None: + return AdaptiveImageCrop.None; - default: - return AdaptiveImageCrop.Default; - } + default: + return AdaptiveImageCrop.Default; } } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileBasicImage.cs b/components/Notifications/src/Tiles/TileBasicImage.cs index c3b57b815..b784a877b 100644 --- a/components/Notifications/src/Tiles/TileBasicImage.cs +++ b/components/Notifications/src/Tiles/TileBasicImage.cs @@ -4,39 +4,38 @@ using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// An image used on various special templates for the Tile. +/// +public sealed class TileBasicImage : IBaseImage { + private string _source; + + /// + /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. + /// + public string Source + { + get { return _source; } + set { BaseImageHelper.SetSource(ref _source, value); } + } + + /// + /// Gets or sets a description of the image, for users of assistive technologies. + /// + public string AlternateText { get; set; } + /// - /// An image used on various special templates for the Tile. + /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. /// - public sealed class TileBasicImage : IBaseImage + public bool? AddImageQuery { get; set; } + + internal Element_AdaptiveImage ConvertToElement() { - private string _source; - - /// - /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. - /// - public string Source - { - get { return _source; } - set { BaseImageHelper.SetSource(ref _source, value); } - } - - /// - /// Gets or sets a description of the image, for users of assistive technologies. - /// - public string AlternateText { get; set; } - - /// - /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. - /// - public bool? AddImageQuery { get; set; } - - internal Element_AdaptiveImage ConvertToElement() - { - Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this); - - return image; - } + Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this); + + return image; } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileBasicText.cs b/components/Notifications/src/Tiles/TileBasicText.cs index 465d1dd44..ec1f94b97 100644 --- a/components/Notifications/src/Tiles/TileBasicText.cs +++ b/components/Notifications/src/Tiles/TileBasicText.cs @@ -4,39 +4,38 @@ using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A text element on the Tile. +/// +public sealed class TileBasicText { /// - /// A text element on the Tile. + /// Gets or sets the text value that will be shown in the text field. /// - public sealed class TileBasicText - { - /// - /// Gets or sets the text value that will be shown in the text field. - /// - public string Text { get; set; } + public string Text { get; set; } - /// - /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. - /// - public string Lang { get; set; } + /// + /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. + /// + public string Lang { get; set; } - internal Element_AdaptiveText ConvertToElement() + internal Element_AdaptiveText ConvertToElement() + { + return new Element_AdaptiveText() { - return new Element_AdaptiveText() - { - Text = Text, - Lang = Lang - }; - } + Text = Text, + Lang = Lang + }; + } - /// - /// Returns the Text property's value. - /// - /// The Text property's value. - public override string ToString() - { - return Text; - } + /// + /// Returns the Text property's value. + /// + /// The Text property's value. + public override string ToString() + { + return Text; } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileBinding.cs b/components/Notifications/src/Tiles/TileBinding.cs index 1290f47b2..78faaddc3 100644 --- a/components/Notifications/src/Tiles/TileBinding.cs +++ b/components/Notifications/src/Tiles/TileBinding.cs @@ -4,165 +4,164 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// The binding element contains the visual content for a specific Tile size. +/// +public sealed class TileBinding { /// - /// The binding element contains the visual content for a specific Tile size. + /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides that in visual, but can be overridden by that in text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. See Remarks for when this value isn't specified. + /// + public string Language { get; set; } + + /// + /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. Defaults to null. + /// + public Uri BaseUri { get; set; } + + /// + /// Gets or sets the form that the Tile should use to display the app's brand.. + /// + public TileBranding Branding { get; set; } = Element_TileBinding.DEFAULT_BRANDING; + + /// + /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of + /// + /// "www.website.com/images/hello.png" + /// + /// included in the notification becomes + /// + /// "www.website.com/images/hello.png?ms-scale=100&ms-contrast=standard&ms-lang=en-us" + /// + public bool? AddImageQuery { get; set; } + + /// + /// Gets or sets a sender-defined string that uniquely identifies the content of the notification. This prevents duplicates in the situation where a large Tile template is displaying the last three wide Tile notifications. + /// + public string ContentId { get; set; } + + /// + /// Gets or sets an optional string to override the Tile's display name while showing this notification. /// - public sealed class TileBinding + public string DisplayName { get; set; } + + /// + /// Gets or sets an app-defined data that is passed back to your app via the TileActivatedInfo property on + /// LaunchActivatedEventArgs when the user launches your app from the Live Tile. This allows you to know + /// which Tile notifications your user saw when they tapped your Live Tile. On devices without the Anniversary Update, + /// this will simply be ignored. + /// + public string Arguments { get; set; } + + /// + /// Gets or sets the actual content to be displayed. One of , , , , or + /// + public ITileBindingContent Content { get; set; } + + internal Element_TileBinding ConvertToElement(TileSize size) { - /// - /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides that in visual, but can be overridden by that in text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. See Remarks for when this value isn't specified. - /// - public string Language { get; set; } - - /// - /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. Defaults to null. - /// - public Uri BaseUri { get; set; } - - /// - /// Gets or sets the form that the Tile should use to display the app's brand.. - /// - public TileBranding Branding { get; set; } = Element_TileBinding.DEFAULT_BRANDING; - - /// - /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of - /// - /// "www.website.com/images/hello.png" - /// - /// included in the notification becomes - /// - /// "www.website.com/images/hello.png?ms-scale=100&ms-contrast=standard&ms-lang=en-us" - /// - public bool? AddImageQuery { get; set; } - - /// - /// Gets or sets a sender-defined string that uniquely identifies the content of the notification. This prevents duplicates in the situation where a large Tile template is displaying the last three wide Tile notifications. - /// - public string ContentId { get; set; } - - /// - /// Gets or sets an optional string to override the Tile's display name while showing this notification. - /// - public string DisplayName { get; set; } - - /// - /// Gets or sets an app-defined data that is passed back to your app via the TileActivatedInfo property on - /// LaunchActivatedEventArgs when the user launches your app from the Live Tile. This allows you to know - /// which Tile notifications your user saw when they tapped your Live Tile. On devices without the Anniversary Update, - /// this will simply be ignored. - /// - public string Arguments { get; set; } - - /// - /// Gets or sets the actual content to be displayed. One of , , , , or - /// - public ITileBindingContent Content { get; set; } - - internal Element_TileBinding ConvertToElement(TileSize size) + TileTemplateNameV3 templateName = GetTemplateName(Content, size); + + Element_TileBinding binding = new Element_TileBinding(templateName) { - TileTemplateNameV3 templateName = GetTemplateName(Content, size); + Language = Language, + BaseUri = BaseUri, + Branding = Branding, + AddImageQuery = AddImageQuery, + DisplayName = DisplayName, + ContentId = ContentId, + Arguments = Arguments - Element_TileBinding binding = new Element_TileBinding(templateName) - { - Language = Language, - BaseUri = BaseUri, - Branding = Branding, - AddImageQuery = AddImageQuery, - DisplayName = DisplayName, - ContentId = ContentId, - Arguments = Arguments + // LockDetailedStatus gets populated by TileVisual + }; - // LockDetailedStatus gets populated by TileVisual - }; + PopulateElement(Content, binding, size); - PopulateElement(Content, binding, size); + return binding; + } - return binding; + private static void PopulateElement(ITileBindingContent bindingContent, Element_TileBinding binding, TileSize size) + { + if (bindingContent == null) + { + return; } - private static void PopulateElement(ITileBindingContent bindingContent, Element_TileBinding binding, TileSize size) + if (bindingContent is TileBindingContentAdaptive) { - if (bindingContent == null) - { - return; - } - - if (bindingContent is TileBindingContentAdaptive) - { - (bindingContent as TileBindingContentAdaptive).PopulateElement(binding, size); - } - else if (bindingContent is TileBindingContentContact) - { - (bindingContent as TileBindingContentContact).PopulateElement(binding, size); - } - else if (bindingContent is TileBindingContentIconic) - { - (bindingContent as TileBindingContentIconic).PopulateElement(binding, size); - } - else if (bindingContent is TileBindingContentPeople) - { - (bindingContent as TileBindingContentPeople).PopulateElement(binding, size); - } - else if (bindingContent is TileBindingContentPhotos) - { - (bindingContent as TileBindingContentPhotos).PopulateElement(binding, size); - } - else - { - throw new NotImplementedException("Unknown binding content type: " + bindingContent.GetType()); - } + (bindingContent as TileBindingContentAdaptive).PopulateElement(binding, size); } - - private static TileTemplateNameV3 GetTemplateName(ITileBindingContent bindingContent, TileSize size) + else if (bindingContent is TileBindingContentContact) + { + (bindingContent as TileBindingContentContact).PopulateElement(binding, size); + } + else if (bindingContent is TileBindingContentIconic) + { + (bindingContent as TileBindingContentIconic).PopulateElement(binding, size); + } + else if (bindingContent is TileBindingContentPeople) + { + (bindingContent as TileBindingContentPeople).PopulateElement(binding, size); + } + else if (bindingContent is TileBindingContentPhotos) + { + (bindingContent as TileBindingContentPhotos).PopulateElement(binding, size); + } + else { - if (bindingContent == null) - { - return TileSizeToAdaptiveTemplateConverter.Convert(size); - } - - if (bindingContent is TileBindingContentAdaptive) - { - return (bindingContent as TileBindingContentAdaptive).GetTemplateName(size); - } - - if (bindingContent is TileBindingContentContact) - { - return (bindingContent as TileBindingContentContact).GetTemplateName(size); - } - - if (bindingContent is TileBindingContentIconic) - { - return (bindingContent as TileBindingContentIconic).GetTemplateName(size); - } - - if (bindingContent is TileBindingContentPeople) - { - return (bindingContent as TileBindingContentPeople).GetTemplateName(size); - } - - if (bindingContent is TileBindingContentPhotos) - { - return (bindingContent as TileBindingContentPhotos).GetTemplateName(size); - } - throw new NotImplementedException("Unknown binding content type: " + bindingContent.GetType()); } } - /// - /// Visual Tile content. One of , , , , or . - /// - public interface ITileBindingContent + private static TileTemplateNameV3 GetTemplateName(ITileBindingContent bindingContent, TileSize size) { - } + if (bindingContent == null) + { + return TileSizeToAdaptiveTemplateConverter.Convert(size); + } - internal enum TileTemplate - { - TileSmall, - TileMedium, - TileWide, - TileLarge + if (bindingContent is TileBindingContentAdaptive) + { + return (bindingContent as TileBindingContentAdaptive).GetTemplateName(size); + } + + if (bindingContent is TileBindingContentContact) + { + return (bindingContent as TileBindingContentContact).GetTemplateName(size); + } + + if (bindingContent is TileBindingContentIconic) + { + return (bindingContent as TileBindingContentIconic).GetTemplateName(size); + } + + if (bindingContent is TileBindingContentPeople) + { + return (bindingContent as TileBindingContentPeople).GetTemplateName(size); + } + + if (bindingContent is TileBindingContentPhotos) + { + return (bindingContent as TileBindingContentPhotos).GetTemplateName(size); + } + + throw new NotImplementedException("Unknown binding content type: " + bindingContent.GetType()); } +} + +/// +/// Visual Tile content. One of , , , , or . +/// +public interface ITileBindingContent +{ +} + +internal enum TileTemplate +{ + TileSmall, + TileMedium, + TileWide, + TileLarge } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileBindingContentAdaptive.cs b/components/Notifications/src/Tiles/TileBindingContentAdaptive.cs index 3b970165e..f75284f47 100644 --- a/components/Notifications/src/Tiles/TileBindingContentAdaptive.cs +++ b/components/Notifications/src/Tiles/TileBindingContentAdaptive.cs @@ -5,68 +5,67 @@ using System.Collections.Generic; using CommunityToolkit.Notifications.Adaptive; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Supported on all sizes. This is the recommended way of specifying your Tile content. Adaptive Tile templates are the de-facto choice for Windows 10, and you can create a wide variety of custom Tiles through adaptive. +/// +public sealed class TileBindingContentAdaptive : ITileBindingContent { /// - /// Supported on all sizes. This is the recommended way of specifying your Tile content. Adaptive Tile templates are the de-facto choice for Windows 10, and you can create a wide variety of custom Tiles through adaptive. + /// Gets , , and objects that can be added as children. The children are displayed in a vertical StackPanel fashion. /// - public sealed class TileBindingContentAdaptive : ITileBindingContent - { - /// - /// Gets , , and objects that can be added as children. The children are displayed in a vertical StackPanel fashion. - /// - public IList Children { get; private set; } = new List(); + public IList Children { get; private set; } = new List(); - /// - /// Gets or sets an optional background image that gets displayed behind all the Tile content, full bleed. - /// - public TileBackgroundImage BackgroundImage { get; set; } + /// + /// Gets or sets an optional background image that gets displayed behind all the Tile content, full bleed. + /// + public TileBackgroundImage BackgroundImage { get; set; } - /// - /// Gets or sets an optional peek image that animates in from the top of the Tile. - /// - public TilePeekImage PeekImage { get; set; } + /// + /// Gets or sets an optional peek image that animates in from the top of the Tile. + /// + public TilePeekImage PeekImage { get; set; } - /// - /// Gets or sets the text stacking (vertical alignment) of the entire binding element. - /// - public TileTextStacking TextStacking { get; set; } = Element_TileBinding.DEFAULT_TEXT_STACKING; + /// + /// Gets or sets the text stacking (vertical alignment) of the entire binding element. + /// + public TileTextStacking TextStacking { get; set; } = Element_TileBinding.DEFAULT_TEXT_STACKING; - internal TileTemplateNameV3 GetTemplateName(TileSize size) + internal TileTemplateNameV3 GetTemplateName(TileSize size) + { + return TileSizeToAdaptiveTemplateConverter.Convert(size); + } + + internal void PopulateElement(Element_TileBinding binding, TileSize size) + { + // Assign properties + binding.TextStacking = TextStacking; + + // Add the background image if there's one + if (BackgroundImage != null) { - return TileSizeToAdaptiveTemplateConverter.Convert(size); + // And add it as a child + binding.Children.Add(BackgroundImage.ConvertToElement()); } - internal void PopulateElement(Element_TileBinding binding, TileSize size) + // Add the peek image if there's one + if (PeekImage != null) { - // Assign properties - binding.TextStacking = TextStacking; - - // Add the background image if there's one - if (BackgroundImage != null) - { - // And add it as a child - binding.Children.Add(BackgroundImage.ConvertToElement()); - } - - // Add the peek image if there's one - if (PeekImage != null) - { - var el = PeekImage.ConvertToElement(); + var el = PeekImage.ConvertToElement(); - binding.Children.Add(el); - } - - // And then add all the children - foreach (var child in Children) - { - binding.Children.Add(ConvertToBindingChildElement(child)); - } + binding.Children.Add(el); } - private static IElement_TileBindingChild ConvertToBindingChildElement(ITileBindingContentAdaptiveChild child) + // And then add all the children + foreach (var child in Children) { - return (IElement_TileBindingChild)AdaptiveHelper.ConvertToElement(child); + binding.Children.Add(ConvertToBindingChildElement(child)); } } + + private static IElement_TileBindingChild ConvertToBindingChildElement(ITileBindingContentAdaptiveChild child) + { + return (IElement_TileBindingChild)AdaptiveHelper.ConvertToElement(child); + } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileBranding.cs b/components/Notifications/src/Tiles/TileBranding.cs index c70a50c0b..2e0f6c86c 100644 --- a/components/Notifications/src/Tiles/TileBranding.cs +++ b/components/Notifications/src/Tiles/TileBranding.cs @@ -2,36 +2,35 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// The form that the Tile should use to display the app's brand. +/// +public enum TileBranding { /// - /// The form that the Tile should use to display the app's brand. + /// The default choice. If ShowNameOn___ is true for the Tile size being displayed, then branding will be "Name". Otherwise it will be "None". /// - public enum TileBranding - { - /// - /// The default choice. If ShowNameOn___ is true for the Tile size being displayed, then branding will be "Name". Otherwise it will be "None". - /// - Auto, + Auto, - /// - /// No branding will be displayed. - /// - None, + /// + /// No branding will be displayed. + /// + None, - /// - /// The DisplayName will be shown. - /// - Name, + /// + /// The DisplayName will be shown. + /// + Name, - /// - /// Desktop-only. The Square44x44Logo will be shown. On Mobile, this will fallback to Name. - /// - Logo, + /// + /// Desktop-only. The Square44x44Logo will be shown. On Mobile, this will fallback to Name. + /// + Logo, - /// - /// Desktop-only. Both the DisplayName and Square44x44Logo will be shown. On Mobile, this will fallback to Name. - /// - NameAndLogo - } + /// + /// Desktop-only. Both the DisplayName and Square44x44Logo will be shown. On Mobile, this will fallback to Name. + /// + NameAndLogo } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileCommon.cs b/components/Notifications/src/Tiles/TileCommon.cs index 96544d3c9..666995106 100644 --- a/components/Notifications/src/Tiles/TileCommon.cs +++ b/components/Notifications/src/Tiles/TileCommon.cs @@ -4,32 +4,31 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Represent the all tile sizes that are available. +/// +[Flags] +public enum TileSize { /// - /// Represent the all tile sizes that are available. + /// Small Square Tile /// - [Flags] - public enum TileSize - { - /// - /// Small Square Tile - /// - Small = 1, + Small = 1, - /// - /// Medium Square Tile - /// - Medium = 2, + /// + /// Medium Square Tile + /// + Medium = 2, - /// - /// Wide Rectangle Tile - /// - Wide = 4, + /// + /// Wide Rectangle Tile + /// + Wide = 4, - /// - /// Large Square Tile - /// - Large = 8 - } + /// + /// Large Square Tile + /// + Large = 8 } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileContent.cs b/components/Notifications/src/Tiles/TileContent.cs index 0f4608809..c86068743 100644 --- a/components/Notifications/src/Tiles/TileContent.cs +++ b/components/Notifications/src/Tiles/TileContent.cs @@ -5,49 +5,48 @@ using Windows.Data.Xml.Dom; using Windows.UI.Notifications; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Base Tile element, which contains a single visual element. +/// +public sealed class TileContent { /// - /// Base Tile element, which contains a single visual element. + /// Gets or sets the visual element. Required. /// - public sealed class TileContent - { - /// - /// Gets or sets the visual element. Required. - /// - public TileVisual Visual { get; set; } - - /// - /// Retrieves the notification XML content as a string, so that it can be sent with a HTTP POST in a push notification. - /// - /// The notification XML content as a string. - public string GetContent() - { - return ConvertToElement().GetContent(); - } + public TileVisual Visual { get; set; } - /// - /// Retrieves the notification XML content as a WinRT XmlDocument, so that it can be used with a local Tile notification's constructor on either or . - /// - /// The notification XML content as a WinRT XmlDocument. - public XmlDocument GetXml() - { - XmlDocument doc = new XmlDocument(); - doc.LoadXml(GetContent()); + /// + /// Retrieves the notification XML content as a string, so that it can be sent with a HTTP POST in a push notification. + /// + /// The notification XML content as a string. + public string GetContent() + { + return ConvertToElement().GetContent(); + } - return doc; - } + /// + /// Retrieves the notification XML content as a WinRT XmlDocument, so that it can be used with a local Tile notification's constructor on either or . + /// + /// The notification XML content as a WinRT XmlDocument. + public XmlDocument GetXml() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(GetContent()); - internal Element_Tile ConvertToElement() - { - var tile = new Element_Tile(); + return doc; + } - if (Visual != null) - { - tile.Visual = Visual.ConvertToElement(); - } + internal Element_Tile ConvertToElement() + { + var tile = new Element_Tile(); - return tile; + if (Visual != null) + { + tile.Visual = Visual.ConvertToElement(); } + + return tile; } } diff --git a/components/Notifications/src/Tiles/TileImages.cs b/components/Notifications/src/Tiles/TileImages.cs index 6ac9407f1..a6f5faabe 100644 --- a/components/Notifications/src/Tiles/TileImages.cs +++ b/components/Notifications/src/Tiles/TileImages.cs @@ -2,47 +2,46 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Specify the desired cropping of the image. +/// +public enum TileBackgroundImageCrop { /// - /// Specify the desired cropping of the image. + /// Cropping style automatically determined by renderer. /// - public enum TileBackgroundImageCrop - { - /// - /// Cropping style automatically determined by renderer. - /// - Default, + Default, - /// - /// Default value. Image is not cropped. - /// - None, + /// + /// Default value. Image is not cropped. + /// + None, - /// - /// Image is cropped to a circle shape. - /// - Circle - } + /// + /// Image is cropped to a circle shape. + /// + Circle +} +/// +/// Specify the desired cropping of the image. +/// +public enum TilePeekImageCrop +{ /// - /// Specify the desired cropping of the image. + /// Cropping style automatically determined by renderer. /// - public enum TilePeekImageCrop - { - /// - /// Cropping style automatically determined by renderer. - /// - Default, + Default, - /// - /// Default value. Image is not cropped. - /// - None, + /// + /// Default value. Image is not cropped. + /// + None, - /// - /// Image is cropped to a circle shape. - /// - Circle - } + /// + /// Image is cropped to a circle shape. + /// + Circle } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TilePeekImage.cs b/components/Notifications/src/Tiles/TilePeekImage.cs index e8e75f309..eaa85b2f0 100644 --- a/components/Notifications/src/Tiles/TilePeekImage.cs +++ b/components/Notifications/src/Tiles/TilePeekImage.cs @@ -4,88 +4,87 @@ using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A peek image that animates in from the top of the Tile. +/// +public sealed class TilePeekImage : IBaseImage { + private string _source; + /// - /// A peek image that animates in from the top of the Tile. + /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. /// - public sealed class TilePeekImage : IBaseImage + public string Source { - private string _source; + get { return _source; } + set { BaseImageHelper.SetSource(ref _source, value); } + } - /// - /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. - /// - public string Source - { - get { return _source; } - set { BaseImageHelper.SetSource(ref _source, value); } - } + /// + /// Gets or sets a description of the image, for users of assistive technologies. + /// + public string AlternateText { get; set; } - /// - /// Gets or sets a description of the image, for users of assistive technologies. - /// - public string AlternateText { get; set; } + /// + /// Gets or sets set a value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. + /// + public bool? AddImageQuery { get; set; } - /// - /// Gets or sets set a value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. - /// - public bool? AddImageQuery { get; set; } + private int? _hintOverlay; - private int? _hintOverlay; + /// + /// Gets or sets a black overlay on the peek image. This value controls the opacity of the black overlay, with 0 being no overlay and 100 being completely black. Defaults to 0. + /// Previously for RTM: Did not exist, value will be ignored and peek image will be displayed with 0 overlay. + /// + public int? HintOverlay + { + get + { + return _hintOverlay; + } - /// - /// Gets or sets a black overlay on the peek image. This value controls the opacity of the black overlay, with 0 being no overlay and 100 being completely black. Defaults to 0. - /// Previously for RTM: Did not exist, value will be ignored and peek image will be displayed with 0 overlay. - /// - public int? HintOverlay + set { - get + if (value != null) { - return _hintOverlay; + Element_TileBinding.CheckOverlayValue(value.Value); } - set - { - if (value != null) - { - Element_TileBinding.CheckOverlayValue(value.Value); - } - - _hintOverlay = value; - } + _hintOverlay = value; } + } - /// - /// Gets or sets the desired cropping of the image. - /// Previously for RTM: Did not exist, value will be ignored and peek image will be displayed without any cropping. - /// - public TilePeekImageCrop HintCrop { get; set; } + /// + /// Gets or sets the desired cropping of the image. + /// Previously for RTM: Did not exist, value will be ignored and peek image will be displayed without any cropping. + /// + public TilePeekImageCrop HintCrop { get; set; } - internal Element_AdaptiveImage ConvertToElement() - { - Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this); + internal Element_AdaptiveImage ConvertToElement() + { + Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this); - image.Placement = AdaptiveImagePlacement.Peek; - image.Crop = GetAdaptiveImageCrop(); - image.Overlay = HintOverlay; + image.Placement = AdaptiveImagePlacement.Peek; + image.Crop = GetAdaptiveImageCrop(); + image.Overlay = HintOverlay; - return image; - } + return image; + } - private AdaptiveImageCrop GetAdaptiveImageCrop() + private AdaptiveImageCrop GetAdaptiveImageCrop() + { + switch (HintCrop) { - switch (HintCrop) - { - case TilePeekImageCrop.Circle: - return AdaptiveImageCrop.Circle; + case TilePeekImageCrop.Circle: + return AdaptiveImageCrop.Circle; - case TilePeekImageCrop.None: - return AdaptiveImageCrop.None; + case TilePeekImageCrop.None: + return AdaptiveImageCrop.None; - default: - return AdaptiveImageCrop.Default; - } + default: + return AdaptiveImageCrop.Default; } } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileSizeToAdaptiveTemplateConverter.cs b/components/Notifications/src/Tiles/TileSizeToAdaptiveTemplateConverter.cs index 86b19981d..0e35c183f 100644 --- a/components/Notifications/src/Tiles/TileSizeToAdaptiveTemplateConverter.cs +++ b/components/Notifications/src/Tiles/TileSizeToAdaptiveTemplateConverter.cs @@ -4,29 +4,28 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal static class TileSizeToAdaptiveTemplateConverter { - internal static class TileSizeToAdaptiveTemplateConverter + public static TileTemplateNameV3 Convert(TileSize size) { - public static TileTemplateNameV3 Convert(TileSize size) + switch (size) { - switch (size) - { - case TileSize.Small: - return TileTemplateNameV3.TileSmall; + case TileSize.Small: + return TileTemplateNameV3.TileSmall; - case TileSize.Medium: - return TileTemplateNameV3.TileMedium; + case TileSize.Medium: + return TileTemplateNameV3.TileMedium; - case TileSize.Wide: - return TileTemplateNameV3.TileWide; + case TileSize.Wide: + return TileTemplateNameV3.TileWide; - case TileSize.Large: - return TileTemplateNameV3.TileLarge; + case TileSize.Large: + return TileTemplateNameV3.TileLarge; - default: - throw new NotImplementedException(); - } + default: + throw new NotImplementedException(); } } } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileTemplateNameV3.cs b/components/Notifications/src/Tiles/TileTemplateNameV3.cs index 1cdd685aa..932a5a5f2 100644 --- a/components/Notifications/src/Tiles/TileTemplateNameV3.cs +++ b/components/Notifications/src/Tiles/TileTemplateNameV3.cs @@ -2,91 +2,90 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal enum TileTemplateNameV3 { - internal enum TileTemplateNameV3 - { - TileMedium, - TileSmall, - TileWide, - TileLarge, + TileMedium, + TileSmall, + TileWide, + TileLarge, - TileSquare150x150Block, - TileSquare150x150Image, - TileSquare150x150PeekImageAndText01, - TileSquare150x150PeekImageAndText02, - TileSquare150x150PeekImageAndText03, - TileSquare150x150PeekImageAndText04, - TileSquare150x150Text01, - TileSquare150x150Text02, - TileSquare150x150Text03, - TileSquare150x150Text04, - TileSquare310x310BlockAndText01, - TileSquare310x310BlockAndText02, - TileSquare310x310Image, - TileSquare310x310ImageAndText01, - TileSquare310x310ImageAndText02, - TileSquare310x310ImageAndTextOverlay01, - TileSquare310x310ImageAndTextOverlay02, - TileSquare310x310ImageAndTextOverlay03, - TileSquare310x310ImageCollection, - TileSquare310x310ImageCollectionAndText01, - TileSquare310x310ImageCollectionAndText02, - TileSquare310x310SmallImagesAndTextList01, - TileSquare310x310SmallImagesAndTextList02, - TileSquare310x310SmallImagesAndTextList03, - TileSquare310x310SmallImagesAndTextList04, - TileSquare310x310Text01, - TileSquare310x310Text02, - TileSquare310x310Text03, - TileSquare310x310Text04, - TileSquare310x310Text05, - TileSquare310x310Text06, - TileSquare310x310Text07, - TileSquare310x310Text08, - TileSquare310x310TextList01, - TileSquare310x310TextList02, - TileSquare310x310TextList03, - TileWide310x150BlockAndText01, - TileWide310x150BlockAndText02, - TileWide310x150Image, - TileWide310x150ImageAndText01, - TileWide310x150ImageAndText02, - TileWide310x150ImageCollection, - TileWide310x150PeekImage01, - TileWide310x150PeekImage02, - TileWide310x150PeekImage03, - TileWide310x150PeekImage04, - TileWide310x150PeekImage05, - TileWide310x150PeekImage06, - TileWide310x150PeekImageAndText01, - TileWide310x150PeekImageAndText02, - TileWide310x150PeekImageCollection01, - TileWide310x150PeekImageCollection02, - TileWide310x150PeekImageCollection03, - TileWide310x150PeekImageCollection04, - TileWide310x150PeekImageCollection05, - TileWide310x150PeekImageCollection06, - TileWide310x150SmallImageAndText01, - TileWide310x150SmallImageAndText02, - TileWide310x150SmallImageAndText03, - TileWide310x150SmallImageAndText04, - TileWide310x150SmallImageAndText05, - TileWide310x150Text01, - TileWide310x150Text02, - TileWide310x150Text03, - TileWide310x150Text04, - TileWide310x150Text05, - TileWide310x150Text06, - TileWide310x150Text07, - TileWide310x150Text08, - TileWide310x150Text09, - TileWide310x150Text10, - TileWide310x150Text11, + TileSquare150x150Block, + TileSquare150x150Image, + TileSquare150x150PeekImageAndText01, + TileSquare150x150PeekImageAndText02, + TileSquare150x150PeekImageAndText03, + TileSquare150x150PeekImageAndText04, + TileSquare150x150Text01, + TileSquare150x150Text02, + TileSquare150x150Text03, + TileSquare150x150Text04, + TileSquare310x310BlockAndText01, + TileSquare310x310BlockAndText02, + TileSquare310x310Image, + TileSquare310x310ImageAndText01, + TileSquare310x310ImageAndText02, + TileSquare310x310ImageAndTextOverlay01, + TileSquare310x310ImageAndTextOverlay02, + TileSquare310x310ImageAndTextOverlay03, + TileSquare310x310ImageCollection, + TileSquare310x310ImageCollectionAndText01, + TileSquare310x310ImageCollectionAndText02, + TileSquare310x310SmallImagesAndTextList01, + TileSquare310x310SmallImagesAndTextList02, + TileSquare310x310SmallImagesAndTextList03, + TileSquare310x310SmallImagesAndTextList04, + TileSquare310x310Text01, + TileSquare310x310Text02, + TileSquare310x310Text03, + TileSquare310x310Text04, + TileSquare310x310Text05, + TileSquare310x310Text06, + TileSquare310x310Text07, + TileSquare310x310Text08, + TileSquare310x310TextList01, + TileSquare310x310TextList02, + TileSquare310x310TextList03, + TileWide310x150BlockAndText01, + TileWide310x150BlockAndText02, + TileWide310x150Image, + TileWide310x150ImageAndText01, + TileWide310x150ImageAndText02, + TileWide310x150ImageCollection, + TileWide310x150PeekImage01, + TileWide310x150PeekImage02, + TileWide310x150PeekImage03, + TileWide310x150PeekImage04, + TileWide310x150PeekImage05, + TileWide310x150PeekImage06, + TileWide310x150PeekImageAndText01, + TileWide310x150PeekImageAndText02, + TileWide310x150PeekImageCollection01, + TileWide310x150PeekImageCollection02, + TileWide310x150PeekImageCollection03, + TileWide310x150PeekImageCollection04, + TileWide310x150PeekImageCollection05, + TileWide310x150PeekImageCollection06, + TileWide310x150SmallImageAndText01, + TileWide310x150SmallImageAndText02, + TileWide310x150SmallImageAndText03, + TileWide310x150SmallImageAndText04, + TileWide310x150SmallImageAndText05, + TileWide310x150Text01, + TileWide310x150Text02, + TileWide310x150Text03, + TileWide310x150Text04, + TileWide310x150Text05, + TileWide310x150Text06, + TileWide310x150Text07, + TileWide310x150Text08, + TileWide310x150Text09, + TileWide310x150Text10, + TileWide310x150Text11, - TileSquare71x71Image, - TileSquare71x71IconWithBadge, - TileSquare150x150IconWithBadge, - TileWide310x150IconWithBadgeAndText - } + TileSquare71x71Image, + TileSquare71x71IconWithBadge, + TileSquare150x150IconWithBadge, + TileWide310x150IconWithBadgeAndText } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileTextStacking.cs b/components/Notifications/src/Tiles/TileTextStacking.cs index 4b4e352dd..9c7ad284f 100644 --- a/components/Notifications/src/Tiles/TileTextStacking.cs +++ b/components/Notifications/src/Tiles/TileTextStacking.cs @@ -2,26 +2,25 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// TextStacking specifies the vertical alignment of content. +/// +public enum TileTextStacking { /// - /// TextStacking specifies the vertical alignment of content. + /// Vertical align to the top. /// - public enum TileTextStacking - { - /// - /// Vertical align to the top. - /// - Top, + Top, - /// - /// Vertical align to the center. - /// - Center, + /// + /// Vertical align to the center. + /// + Center, - /// - /// Vertical align to the bottom. - /// - Bottom - } + /// + /// Vertical align to the bottom. + /// + Bottom } \ No newline at end of file diff --git a/components/Notifications/src/Tiles/TileVisual.cs b/components/Notifications/src/Tiles/TileVisual.cs index 123a785c3..c4380d5e8 100644 --- a/components/Notifications/src/Tiles/TileVisual.cs +++ b/components/Notifications/src/Tiles/TileVisual.cs @@ -6,214 +6,213 @@ using System.Linq; using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Contains multiple binding child elements, each of which defines a Tile. +/// +public sealed class TileVisual { /// - /// Contains multiple binding child elements, each of which defines a Tile. + /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". This locale is overridden by any locale specified in binding or text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. /// - public sealed class TileVisual - { - /// - /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". This locale is overridden by any locale specified in binding or text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. - /// - public string Language { get; set; } - - /// - /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. - /// - public Uri BaseUri { get; set; } - - /// - /// Gets or sets the form that the Tile should use to display the app's brand. - /// - public TileBranding Branding { get; set; } = Element_TileVisual.DEFAULT_BRANDING; - - /// - /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of - /// - /// "www.website.com/images/hello.png" - /// - /// included in the notification becomes - /// - /// "www.website.com/images/hello.png?ms-scale=100&ms-contrast=standard&ms-lang=en-us" - /// - public bool? AddImageQuery { get; set; } - - /// - /// Gets or sets a sender-defined string that uniquely identifies the content of the notification. This prevents duplicates in the situation where a large Tile template is displaying the last three wide Tile notifications. - /// - public string ContentId { get; set; } - - /// - /// Gets or sets an optional string to override the Tile's display name while showing this notification. - /// - public string DisplayName { get; set; } - - /// - /// Gets or sets the first line of text that will be displayed on the lock screen if the user has selected - /// your Tile as their detailed status app. Ff you specify this, you must also provide a Wide Tile binding. - /// - public string LockDetailedStatus1 { get; set; } - - /// - /// Gets or sets the second line of text that will be displayed on the lock screen if the user has selected - /// your Tile as their detailed status app. If you specify this, you must also provide a Wide Tile binding. - /// - public string LockDetailedStatus2 { get; set; } - - /// - /// Gets or sets the third line of text that will be displayed on the lock screen if the user has selected your - /// Tile as their detailed status app. If you specify this, you must also provide a Wide Tile binding. - /// - public string LockDetailedStatus3 { get; set; } - - /// - /// Gets or sets app-defined data that is passed back to your app via the TileActivatedInfo property on LaunchActivatedEventArgs when the user launches your app from the Live Tile. This allows you to know which Tile notifications your user saw when they tapped your Live Tile. On devices without the Anniversary Update, this will simply be ignored. - /// - public string Arguments { get; set; } - - /// - /// Gets or sets an optional small binding to specify content for the small Tile size. - /// - public TileBinding TileSmall { get; set; } - - /// - /// Gets or sets an optional medium binding to specify content for the medium Tile size. - /// - public TileBinding TileMedium { get; set; } - - /// - /// Gets or sets an optional wide binding to specify content for the wide Tile size. - /// - public TileBinding TileWide { get; set; } - - /// - /// Gets or sets an optional large binding to specify content for the large Tile size. Desktop-only - /// - public TileBinding TileLarge { get; set; } - - /// - /// Attempts to find and re-use an existing text element inside the binding. Returns true if it could. Otherwise returns false, and the caller will have to specify the detailed status using the lock hint attribute. - /// - /// The lock screen line number. - /// The lock screen line text. - /// The binding to look in for matches. - /// True if could re-use existing text element, otherwise false. - private static bool TryReuseTextElementForLockDetailedText(int lineNumber, string lockText, Element_TileBinding binding) - { - if (lockText == null) - { - throw new ArgumentNullException("lockText cannot be null"); - } + public string Language { get; set; } - if (binding == null) - { - throw new ArgumentNullException("binding cannot be null"); - } + /// + /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. + /// + public Uri BaseUri { get; set; } - // If a text element already has an id with the line number (only look at immediate children, since the lock screen will ignore things under groups/subgroups) - Element_AdaptiveText matchingIdTextElement = binding.Children.OfType().FirstOrDefault(i => i.Id != null && i.Id.Equals(lineNumber.ToString())); + /// + /// Gets or sets the form that the Tile should use to display the app's brand. + /// + public TileBranding Branding { get; set; } = Element_TileVisual.DEFAULT_BRANDING; - if (matchingIdTextElement != null) - { - // If the text in the element matches the lock text, then we're good, don't need to assign anything else! - if (matchingIdTextElement.Text != null && matchingIdTextElement.Text.Equals(lockText)) - { - return true; - } + /// + /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of + /// + /// "www.website.com/images/hello.png" + /// + /// included in the notification becomes + /// + /// "www.website.com/images/hello.png?ms-scale=100&ms-contrast=standard&ms-lang=en-us" + /// + public bool? AddImageQuery { get; set; } - // Otherwise, we need to specify the lock text in the hint attribute, so we return false - return false; - } + /// + /// Gets or sets a sender-defined string that uniquely identifies the content of the notification. This prevents duplicates in the situation where a large Tile template is displaying the last three wide Tile notifications. + /// + public string ContentId { get; set; } - // Otherwise no text elements use that ID, so we could assign one if we find a text element that doesn't have an ID assigned and matches the lock text - Element_AdaptiveText matchingTextTextElement = binding.Children.OfType().FirstOrDefault(i => i.Id == null && i.Text != null && i.Text.Equals(lockText)); + /// + /// Gets or sets an optional string to override the Tile's display name while showing this notification. + /// + public string DisplayName { get; set; } + + /// + /// Gets or sets the first line of text that will be displayed on the lock screen if the user has selected + /// your Tile as their detailed status app. Ff you specify this, you must also provide a Wide Tile binding. + /// + public string LockDetailedStatus1 { get; set; } + + /// + /// Gets or sets the second line of text that will be displayed on the lock screen if the user has selected + /// your Tile as their detailed status app. If you specify this, you must also provide a Wide Tile binding. + /// + public string LockDetailedStatus2 { get; set; } + + /// + /// Gets or sets the third line of text that will be displayed on the lock screen if the user has selected your + /// Tile as their detailed status app. If you specify this, you must also provide a Wide Tile binding. + /// + public string LockDetailedStatus3 { get; set; } + + /// + /// Gets or sets app-defined data that is passed back to your app via the TileActivatedInfo property on LaunchActivatedEventArgs when the user launches your app from the Live Tile. This allows you to know which Tile notifications your user saw when they tapped your Live Tile. On devices without the Anniversary Update, this will simply be ignored. + /// + public string Arguments { get; set; } + + /// + /// Gets or sets an optional small binding to specify content for the small Tile size. + /// + public TileBinding TileSmall { get; set; } + + /// + /// Gets or sets an optional medium binding to specify content for the medium Tile size. + /// + public TileBinding TileMedium { get; set; } + + /// + /// Gets or sets an optional wide binding to specify content for the wide Tile size. + /// + public TileBinding TileWide { get; set; } + + /// + /// Gets or sets an optional large binding to specify content for the large Tile size. Desktop-only + /// + public TileBinding TileLarge { get; set; } - // If we found text that matched, we'll assign the id so it gets re-used for lock! - if (matchingTextTextElement != null) + /// + /// Attempts to find and re-use an existing text element inside the binding. Returns true if it could. Otherwise returns false, and the caller will have to specify the detailed status using the lock hint attribute. + /// + /// The lock screen line number. + /// The lock screen line text. + /// The binding to look in for matches. + /// True if could re-use existing text element, otherwise false. + private static bool TryReuseTextElementForLockDetailedText(int lineNumber, string lockText, Element_TileBinding binding) + { + if (lockText == null) + { + throw new ArgumentNullException("lockText cannot be null"); + } + + if (binding == null) + { + throw new ArgumentNullException("binding cannot be null"); + } + + // If a text element already has an id with the line number (only look at immediate children, since the lock screen will ignore things under groups/subgroups) + Element_AdaptiveText matchingIdTextElement = binding.Children.OfType().FirstOrDefault(i => i.Id != null && i.Id.Equals(lineNumber.ToString())); + + if (matchingIdTextElement != null) + { + // If the text in the element matches the lock text, then we're good, don't need to assign anything else! + if (matchingIdTextElement.Text != null && matchingIdTextElement.Text.Equals(lockText)) { - matchingTextTextElement.Id = lineNumber; return true; } - // Otherwise we'll need to specify lock text in hint attribute, so return false + // Otherwise, we need to specify the lock text in the hint attribute, so we return false return false; } - internal Element_TileVisual ConvertToElement() + // Otherwise no text elements use that ID, so we could assign one if we find a text element that doesn't have an ID assigned and matches the lock text + Element_AdaptiveText matchingTextTextElement = binding.Children.OfType().FirstOrDefault(i => i.Id == null && i.Text != null && i.Text.Equals(lockText)); + + // If we found text that matched, we'll assign the id so it gets re-used for lock! + if (matchingTextTextElement != null) { - var visual = new Element_TileVisual() - { - Language = Language, - BaseUri = BaseUri, - Branding = Branding, - AddImageQuery = AddImageQuery, - ContentId = ContentId, - DisplayName = DisplayName, - Arguments = Arguments - }; - - if (TileSmall != null) - { - visual.Bindings.Add(TileSmall.ConvertToElement(TileSize.Small)); - } + matchingTextTextElement.Id = lineNumber; + return true; + } - if (TileMedium != null) - { - visual.Bindings.Add(TileMedium.ConvertToElement(TileSize.Medium)); - } + // Otherwise we'll need to specify lock text in hint attribute, so return false + return false; + } - if (TileWide != null) - { - Element_TileBinding wideBindingElement = TileWide.ConvertToElement(TileSize.Wide); + internal Element_TileVisual ConvertToElement() + { + var visual = new Element_TileVisual() + { + Language = Language, + BaseUri = BaseUri, + Branding = Branding, + AddImageQuery = AddImageQuery, + ContentId = ContentId, + DisplayName = DisplayName, + Arguments = Arguments + }; + + if (TileSmall != null) + { + visual.Bindings.Add(TileSmall.ConvertToElement(TileSize.Small)); + } - // If lock detailed status was specified, add them - if (LockDetailedStatus1 != null) - { - // If we can't reuse existing text element, we'll have to use the hints - if (!TryReuseTextElementForLockDetailedText(1, LockDetailedStatus1, wideBindingElement)) - { - wideBindingElement.LockDetailedStatus1 = LockDetailedStatus1; - } - } + if (TileMedium != null) + { + visual.Bindings.Add(TileMedium.ConvertToElement(TileSize.Medium)); + } - if (LockDetailedStatus2 != null) - { - if (!TryReuseTextElementForLockDetailedText(2, LockDetailedStatus2, wideBindingElement)) - { - wideBindingElement.LockDetailedStatus2 = LockDetailedStatus2; - } - } + if (TileWide != null) + { + Element_TileBinding wideBindingElement = TileWide.ConvertToElement(TileSize.Wide); - if (LockDetailedStatus3 != null) + // If lock detailed status was specified, add them + if (LockDetailedStatus1 != null) + { + // If we can't reuse existing text element, we'll have to use the hints + if (!TryReuseTextElementForLockDetailedText(1, LockDetailedStatus1, wideBindingElement)) { - if (!TryReuseTextElementForLockDetailedText(3, LockDetailedStatus3, wideBindingElement)) - { - wideBindingElement.LockDetailedStatus3 = LockDetailedStatus3; - } + wideBindingElement.LockDetailedStatus1 = LockDetailedStatus1; } - - visual.Bindings.Add(wideBindingElement); } - // Otherwise if they specified lock values, throw an exception since lock values require wide - else if (HasLockDetailedStatusValues()) + if (LockDetailedStatus2 != null) { - throw new Exception("To provide lock detailed status text strings, you must also provide a TileWide binding. Either provide a TileWide binding, or leave the detailed status values null."); + if (!TryReuseTextElementForLockDetailedText(2, LockDetailedStatus2, wideBindingElement)) + { + wideBindingElement.LockDetailedStatus2 = LockDetailedStatus2; + } } - if (TileLarge != null) + if (LockDetailedStatus3 != null) { - visual.Bindings.Add(TileLarge.ConvertToElement(TileSize.Large)); + if (!TryReuseTextElementForLockDetailedText(3, LockDetailedStatus3, wideBindingElement)) + { + wideBindingElement.LockDetailedStatus3 = LockDetailedStatus3; + } } - // TODO: If a BaseUri wasn't provided, we can potentially optimize the payload size by calculating the best BaseUri - return visual; + visual.Bindings.Add(wideBindingElement); } - private bool HasLockDetailedStatusValues() + // Otherwise if they specified lock values, throw an exception since lock values require wide + else if (HasLockDetailedStatusValues()) { - return LockDetailedStatus1 != null && LockDetailedStatus2 != null && LockDetailedStatus3 != null; + throw new Exception("To provide lock detailed status text strings, you must also provide a TileWide binding. Either provide a TileWide binding, or leave the detailed status values null."); } + + if (TileLarge != null) + { + visual.Bindings.Add(TileLarge.ConvertToElement(TileSize.Large)); + } + + // TODO: If a BaseUri wasn't provided, we can potentially optimize the payload size by calculating the best BaseUri + return visual; + } + + private bool HasLockDetailedStatusValues() + { + return LockDetailedStatus1 != null && LockDetailedStatus2 != null && LockDetailedStatus3 != null; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Builder/CustomizeToast.cs b/components/Notifications/src/Toasts/Builder/CustomizeToast.cs index 1f4bf30bb..db7abed5c 100644 --- a/components/Notifications/src/Toasts/Builder/CustomizeToast.cs +++ b/components/Notifications/src/Toasts/Builder/CustomizeToast.cs @@ -5,31 +5,30 @@ using Windows.Foundation; using Windows.UI.Notifications; -namespace CommunityToolkit.Notifications -{ - /// - /// Allows you to set additional properties on the object before the toast is displayed. - /// - /// The toast to modify that will be displayed. - public delegate void CustomizeToast(ToastNotification toast); +namespace CommunityToolkit.Notifications; - /// - /// Allows you to set additional properties on the object before the toast is displayed. - /// - /// The toast to modify that will be displayed. - /// An operation. - public delegate IAsyncAction CustomizeToastAsync(ToastNotification toast); +/// +/// Allows you to set additional properties on the object before the toast is displayed. +/// +/// The toast to modify that will be displayed. +public delegate void CustomizeToast(ToastNotification toast); - /// - /// Allows you to set additional properties on the object before the toast is scheduled. - /// - /// The scheduled toast to modify that will be scheduled. - public delegate void CustomizeScheduledToast(ScheduledToastNotification toast); +/// +/// Allows you to set additional properties on the object before the toast is displayed. +/// +/// The toast to modify that will be displayed. +/// An operation. +public delegate IAsyncAction CustomizeToastAsync(ToastNotification toast); - /// - /// Allows you to set additional properties on the object before the toast is scheduled. - /// - /// The scheduled toast to modify that will be scheduled. - /// An operation. - public delegate IAsyncAction CustomizeScheduledToastAsync(ScheduledToastNotification toast); -} +/// +/// Allows you to set additional properties on the object before the toast is scheduled. +/// +/// The scheduled toast to modify that will be scheduled. +public delegate void CustomizeScheduledToast(ScheduledToastNotification toast); + +/// +/// Allows you to set additional properties on the object before the toast is scheduled. +/// +/// The scheduled toast to modify that will be scheduled. +/// An operation. +public delegate IAsyncAction CustomizeScheduledToastAsync(ScheduledToastNotification toast); diff --git a/components/Notifications/src/Toasts/Builder/ToastContentBuilder.Actions.cs b/components/Notifications/src/Toasts/Builder/ToastContentBuilder.Actions.cs index 2bfc96d06..c286e0d80 100644 --- a/components/Notifications/src/Toasts/Builder/ToastContentBuilder.Actions.cs +++ b/components/Notifications/src/Toasts/Builder/ToastContentBuilder.Actions.cs @@ -6,277 +6,277 @@ using System.Collections.Generic; using System.Linq; -namespace CommunityToolkit.Notifications -{ +namespace CommunityToolkit.Notifications; + #pragma warning disable SA1008 #pragma warning disable SA1009 - /// - /// Builder class used to create - /// - public partial class ToastContentBuilder +/// +/// Builder class used to create +/// +public partial class ToastContentBuilder +{ + private IToastActions Actions { - private IToastActions Actions + get { - get + if (Content.Actions == null) { - if (Content.Actions == null) - { - Content.Actions = new ToastActionsCustom(); - } - - return Content.Actions; + Content.Actions = new ToastActionsCustom(); } - } - private IList ButtonList - { - get - { - return ((ToastActionsCustom)Actions).Buttons; - } + return Content.Actions; } + } - private IList InputList + private IList ButtonList + { + get { - get - { - return ((ToastActionsCustom)Actions).Inputs; - } + return ((ToastActionsCustom)Actions).Buttons; } + } - private string SerializeArgumentsIncludingGeneric(ToastArguments arguments) + private IList InputList + { + get { - if (_genericArguments.Count == 0) - { - return arguments.ToString(); - } - - foreach (var genericArg in _genericArguments) - { - if (!arguments.Contains(genericArg.Key)) - { - arguments.Add(genericArg.Key, genericArg.Value); - } - } - - return arguments.ToString(); + return ((ToastActionsCustom)Actions).Inputs; } + } - /// - /// Add a button to the current toast. - /// - /// Text to display on the button. - /// Type of activation this button will use when clicked. Defaults to Foreground. - /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button. - /// The current instance of - public ToastContentBuilder AddButton(string content, ToastActivationType activationType, string arguments) + private string SerializeArgumentsIncludingGeneric(ToastArguments arguments) + { + if (_genericArguments.Count == 0) { - return AddButton(content, activationType, arguments, default); + return arguments.ToString(); } - /// - /// Add a button to the current toast. - /// - /// Text to display on the button. - /// Type of activation this button will use when clicked. Defaults to Foreground. - /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button. - /// Optional image icon for the button to display (required for buttons adjacent to inputs like quick reply). - /// The current instance of - public ToastContentBuilder AddButton(string content, ToastActivationType activationType, string arguments, Uri imageUri) + foreach (var genericArg in _genericArguments) { - // Add new button - ToastButton button = new ToastButton(content, arguments) + if (!arguments.Contains(genericArg.Key)) { - ActivationType = activationType - }; - - if (imageUri != default) - { - button.ImageUri = imageUri.OriginalString; + arguments.Add(genericArg.Key, genericArg.Value); } - - return AddButton(button); } - /// - /// Add a button to the current toast. - /// - /// An instance of class that implement for the button that will be used on the toast. - /// The current instance of - public ToastContentBuilder AddButton(IToastButton button) - { - if (button is ToastButton toastButton && toastButton.Content == null && toastButton.NeedsContent()) - { - throw new InvalidOperationException("Content is required on button."); - } - - // List has max 5 buttons - if (ButtonList.Count == 5) - { - throw new InvalidOperationException("A toast can't have more than 5 buttons"); - } + return arguments.ToString(); + } - if (button is ToastButton b && b.CanAddArguments()) - { - foreach (var arg in _genericArguments) - { - if (!b.ContainsArgument(arg.Key)) - { - b.AddArgument(arg.Key, arg.Value); - } - } - } + /// + /// Add a button to the current toast. + /// + /// Text to display on the button. + /// Type of activation this button will use when clicked. Defaults to Foreground. + /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button. + /// The current instance of + public ToastContentBuilder AddButton(string content, ToastActivationType activationType, string arguments) + { + return AddButton(content, activationType, arguments, default); + } - ButtonList.Add(button); + /// + /// Add a button to the current toast. + /// + /// Text to display on the button. + /// Type of activation this button will use when clicked. Defaults to Foreground. + /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button. + /// Optional image icon for the button to display (required for buttons adjacent to inputs like quick reply). + /// The current instance of + public ToastContentBuilder AddButton(string content, ToastActivationType activationType, string arguments, Uri imageUri) + { + // Add new button + ToastButton button = new ToastButton(content, arguments) + { + ActivationType = activationType + }; - return this; + if (imageUri != default) + { + button.ImageUri = imageUri.OriginalString; } - /// - /// Add an button to the toast that will be display to the right of the input text box, achieving a quick reply scenario. - /// - /// ID of an existing in order to have this button display to the right of the input, achieving a quick reply scenario. - /// Text to display on the button. - /// Type of activation this button will use when clicked. Defaults to Foreground. - /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button. - /// The current instance of - public ToastContentBuilder AddButton(string textBoxId, string content, ToastActivationType activationType, string arguments) + return AddButton(button); + } + + /// + /// Add a button to the current toast. + /// + /// An instance of class that implement for the button that will be used on the toast. + /// The current instance of + public ToastContentBuilder AddButton(IToastButton button) + { + if (button is ToastButton toastButton && toastButton.Content == null && toastButton.NeedsContent()) { - return AddButton(textBoxId, content, activationType, arguments, default); + throw new InvalidOperationException("Content is required on button."); } - /// - /// Add an button to the toast that will be display to the right of the input text box, achieving a quick reply scenario. - /// - /// ID of an existing in order to have this button display to the right of the input, achieving a quick reply scenario. - /// Text to display on the button. - /// Type of activation this button will use when clicked. Defaults to Foreground. - /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button. - /// An optional image icon for the button to display (required for buttons adjacent to inputs like quick reply) - /// The current instance of - public ToastContentBuilder AddButton(string textBoxId, string content, ToastActivationType activationType, string arguments, Uri imageUri) + // List has max 5 buttons + if (ButtonList.Count == 5) { - // Add new button - ToastButton button = new ToastButton(content, arguments) - { - ActivationType = activationType, - TextBoxId = textBoxId - }; + throw new InvalidOperationException("A toast can't have more than 5 buttons"); + } - if (imageUri != default) + if (button is ToastButton b && b.CanAddArguments()) + { + foreach (var arg in _genericArguments) { - button.ImageUri = imageUri.OriginalString; + if (!b.ContainsArgument(arg.Key)) + { + b.AddArgument(arg.Key, arg.Value); + } } - - return AddButton(button); } - /// - /// Add an input text box that the user can type into. - /// - /// Required ID property so that developers can retrieve user input once the app is activated. - /// Placeholder text to be displayed on the text box when the user hasn't typed any text yet. - /// Title text to display above the text box. - /// The current instance of - public ToastContentBuilder AddInputTextBox( - string id, - string placeHolderContent = default, - string title = default) - { - var inputTextBox = new ToastTextBox(id); + ButtonList.Add(button); - if (placeHolderContent != default) - { - inputTextBox.PlaceholderContent = placeHolderContent; - } + return this; + } - if (title != default) - { - inputTextBox.Title = title; - } + /// + /// Add an button to the toast that will be display to the right of the input text box, achieving a quick reply scenario. + /// + /// ID of an existing in order to have this button display to the right of the input, achieving a quick reply scenario. + /// Text to display on the button. + /// Type of activation this button will use when clicked. Defaults to Foreground. + /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button. + /// The current instance of + public ToastContentBuilder AddButton(string textBoxId, string content, ToastActivationType activationType, string arguments) + { + return AddButton(textBoxId, content, activationType, arguments, default); + } - return AddToastInput(inputTextBox); - } + /// + /// Add an button to the toast that will be display to the right of the input text box, achieving a quick reply scenario. + /// + /// ID of an existing in order to have this button display to the right of the input, achieving a quick reply scenario. + /// Text to display on the button. + /// Type of activation this button will use when clicked. Defaults to Foreground. + /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button. + /// An optional image icon for the button to display (required for buttons adjacent to inputs like quick reply) + /// The current instance of + public ToastContentBuilder AddButton(string textBoxId, string content, ToastActivationType activationType, string arguments, Uri imageUri) + { + // Add new button + ToastButton button = new ToastButton(content, arguments) + { + ActivationType = activationType, + TextBoxId = textBoxId + }; - /// - /// Add a combo box / drop-down menu that contain options for user to select. - /// - /// Required ID property used so that developers can retrieve user input once the app is activated. - /// List of choices that will be available for user to select. - /// The current instance of - public ToastContentBuilder AddComboBox(string id, params (string comboBoxItemId, string comboBoxItemContent)[] choices) + if (imageUri != default) { - return AddComboBox(id, default, choices); + button.ImageUri = imageUri.OriginalString; } - /// - /// Add a combo box / drop-down menu that contain options for user to select. - /// - /// Required ID property used so that developers can retrieve user input once the app is activated. - /// Sets which item is selected by default, and refers to the Id property of . If you do not provide this or null, the default selection will be empty (user sees nothing). - /// List of choices that will be available for user to select. - /// The current instance of - public ToastContentBuilder AddComboBox(string id, string defaultSelectionBoxItemId, params (string comboBoxItemId, string comboBoxItemContent)[] choices) + return AddButton(button); + } + + /// + /// Add an input text box that the user can type into. + /// + /// Required ID property so that developers can retrieve user input once the app is activated. + /// Placeholder text to be displayed on the text box when the user hasn't typed any text yet. + /// Title text to display above the text box. + /// The current instance of + public ToastContentBuilder AddInputTextBox( + string id, + string placeHolderContent = default, + string title = default) + { + var inputTextBox = new ToastTextBox(id); + + if (placeHolderContent != default) { - return AddComboBox(id, default, defaultSelectionBoxItemId, choices); + inputTextBox.PlaceholderContent = placeHolderContent; } - /// - /// Add a combo box / drop-down menu that contain options for user to select. - /// - /// Required ID property used so that developers can retrieve user input once the app is activated. - /// Title text to display above the Combo Box. - /// Sets which item is selected by default, and refers to the Id property of . If you do not provide this or null, the default selection will be empty (user sees nothing). - /// List of choices that will be available for user to select. - /// The current instance of - public ToastContentBuilder AddComboBox(string id, string title, string defaultSelectionBoxItemId, params (string comboBoxItemId, string comboBoxItemContent)[] choices) + if (title != default) { - return AddComboBox(id, title, defaultSelectionBoxItemId, choices as IEnumerable<(string, string)>); + inputTextBox.Title = title; } - /// - /// Add a combo box / drop-down menu that contain options for user to select. - /// - /// Required ID property used so that developers can retrieve user input once the app is activated. - /// Title text to display above the Combo Box. - /// Sets which item is selected by default, and refers to the Id property of . If you do not provide this or null, the default selection will be empty (user sees nothing). - /// List of choices that will be available for user to select. - /// The current instance of - public ToastContentBuilder AddComboBox(string id, string title, string defaultSelectionBoxItemId, IEnumerable<(string comboBoxItemId, string comboBoxItemContent)> choices) - { - var box = new ToastSelectionBox(id); + return AddToastInput(inputTextBox); + } - if (defaultSelectionBoxItemId != default) - { - box.DefaultSelectionBoxItemId = defaultSelectionBoxItemId; - } + /// + /// Add a combo box / drop-down menu that contain options for user to select. + /// + /// Required ID property used so that developers can retrieve user input once the app is activated. + /// List of choices that will be available for user to select. + /// The current instance of + public ToastContentBuilder AddComboBox(string id, params (string comboBoxItemId, string comboBoxItemContent)[] choices) + { + return AddComboBox(id, default, choices); + } - if (title != default) - { - box.Title = title; - } + /// + /// Add a combo box / drop-down menu that contain options for user to select. + /// + /// Required ID property used so that developers can retrieve user input once the app is activated. + /// Sets which item is selected by default, and refers to the Id property of . If you do not provide this or null, the default selection will be empty (user sees nothing). + /// List of choices that will be available for user to select. + /// The current instance of + public ToastContentBuilder AddComboBox(string id, string defaultSelectionBoxItemId, params (string comboBoxItemId, string comboBoxItemContent)[] choices) + { + return AddComboBox(id, default, defaultSelectionBoxItemId, choices); + } - for (int i = 0; i < choices.Count(); i++) - { - var (comboBoxItemId, comboBoxItemContent) = choices.ElementAt(i); - box.Items.Add(new ToastSelectionBoxItem(comboBoxItemId, comboBoxItemContent)); - } + /// + /// Add a combo box / drop-down menu that contain options for user to select. + /// + /// Required ID property used so that developers can retrieve user input once the app is activated. + /// Title text to display above the Combo Box. + /// Sets which item is selected by default, and refers to the Id property of . If you do not provide this or null, the default selection will be empty (user sees nothing). + /// List of choices that will be available for user to select. + /// The current instance of + public ToastContentBuilder AddComboBox(string id, string title, string defaultSelectionBoxItemId, params (string comboBoxItemId, string comboBoxItemContent)[] choices) + { + return AddComboBox(id, title, defaultSelectionBoxItemId, choices as IEnumerable<(string, string)>); + } + + /// + /// Add a combo box / drop-down menu that contain options for user to select. + /// + /// Required ID property used so that developers can retrieve user input once the app is activated. + /// Title text to display above the Combo Box. + /// Sets which item is selected by default, and refers to the Id property of . If you do not provide this or null, the default selection will be empty (user sees nothing). + /// List of choices that will be available for user to select. + /// The current instance of + public ToastContentBuilder AddComboBox(string id, string title, string defaultSelectionBoxItemId, IEnumerable<(string comboBoxItemId, string comboBoxItemContent)> choices) + { + var box = new ToastSelectionBox(id); - return AddToastInput(box); + if (defaultSelectionBoxItemId != default) + { + box.DefaultSelectionBoxItemId = defaultSelectionBoxItemId; } - /// - /// Add an input option to the Toast. - /// - /// An instance of a class that implement that will be used on the toast. - /// The current instance of - public ToastContentBuilder AddToastInput(IToastInput input) + if (title != default) { - InputList.Add(input); + box.Title = title; + } - return this; + for (int i = 0; i < choices.Count(); i++) + { + var (comboBoxItemId, comboBoxItemContent) = choices.ElementAt(i); + box.Items.Add(new ToastSelectionBoxItem(comboBoxItemId, comboBoxItemContent)); } + + return AddToastInput(box); } + + /// + /// Add an input option to the Toast. + /// + /// An instance of a class that implement that will be used on the toast. + /// The current instance of + public ToastContentBuilder AddToastInput(IToastInput input) + { + InputList.Add(input); + + return this; + } +} #pragma warning restore SA1008 #pragma warning restore SA1009 -} + diff --git a/components/Notifications/src/Toasts/Builder/ToastContentBuilder.Visuals.cs b/components/Notifications/src/Toasts/Builder/ToastContentBuilder.Visuals.cs index 1e3ce72d9..849428b19 100644 --- a/components/Notifications/src/Toasts/Builder/ToastContentBuilder.Visuals.cs +++ b/components/Notifications/src/Toasts/Builder/ToastContentBuilder.Visuals.cs @@ -8,412 +8,411 @@ using System.Text; using Windows.UI.Notifications; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Builder class used to create +/// +public partial class ToastContentBuilder { - /// - /// Builder class used to create - /// - public partial class ToastContentBuilder + private ToastVisual Visual { - private ToastVisual Visual + get { - get + if (Content.Visual == null) { - if (Content.Visual == null) - { - Content.Visual = new ToastVisual(); - Content.Visual.BindingGeneric = new ToastBindingGeneric(); - } - - return Content.Visual; + Content.Visual = new ToastVisual(); + Content.Visual.BindingGeneric = new ToastBindingGeneric(); } + + return Content.Visual; } + } - private ToastGenericAppLogo AppLogoOverrideUri + private ToastGenericAppLogo AppLogoOverrideUri + { + get { - get - { - return Visual.BindingGeneric.AppLogoOverride; - } - - set - { - Visual.BindingGeneric.AppLogoOverride = value; - } + return Visual.BindingGeneric.AppLogoOverride; } - private ToastGenericAttributionText AttributionText + set { - get - { - return Visual.BindingGeneric.Attribution; - } - - set - { - Visual.BindingGeneric.Attribution = value; - } + Visual.BindingGeneric.AppLogoOverride = value; } + } - private ToastGenericHeroImage HeroImage + private ToastGenericAttributionText AttributionText + { + get { - get - { - return Visual.BindingGeneric.HeroImage; - } + return Visual.BindingGeneric.Attribution; + } - set - { - Visual.BindingGeneric.HeroImage = value; - } + set + { + Visual.BindingGeneric.Attribution = value; } + } - private IList VisualChildren + private ToastGenericHeroImage HeroImage + { + get { - get - { - return Visual.BindingGeneric.Children; - } + return Visual.BindingGeneric.HeroImage; } - /// - /// Create an instance of NotificationData that can be used to update toast that has a progress bar. - /// - /// Instance of ToastContent that contain progress bars that need to be updated - /// Index of the progress bar (0-based) that this notification data is updating in the case that toast has multiple progress bars. Default to 0. - /// Title of the progress bar. - /// Value of the progress bar. - /// An optional string to be displayed instead of the default percentage string. If this isn't provided, something like "70%" will be displayed. - /// A status string, which is displayed underneath the progress bar on the left. Default to empty. - /// A sequence number to prevent out-of-order updates, or assign 0 to indicate "always update". - /// An instance of NotificationData that can be used to update the toast. - public static NotificationData CreateProgressBarData(ToastContent toast, int index = 0, string title = default, double? value = default, string valueStringOverride = default, string status = default, uint sequence = 0) - { - var progressBar = toast.Visual.BindingGeneric.Children.Where(c => c is AdaptiveProgressBar).ElementAt(index) as AdaptiveProgressBar; - if (progressBar == null) - { - throw new ArgumentException(nameof(toast), "Given toast does not have any progress bar"); - } + set + { + Visual.BindingGeneric.HeroImage = value; + } + } - NotificationData data = new NotificationData(); - data.SequenceNumber = sequence; + private IList VisualChildren + { + get + { + return Visual.BindingGeneric.Children; + } + } - // Native C++ doesn't support BindableString - if (progressBar.Title is BindableString bindableTitle && title != default) - { - data.Values[bindableTitle.BindingName] = title; - } + /// + /// Create an instance of NotificationData that can be used to update toast that has a progress bar. + /// + /// Instance of ToastContent that contain progress bars that need to be updated + /// Index of the progress bar (0-based) that this notification data is updating in the case that toast has multiple progress bars. Default to 0. + /// Title of the progress bar. + /// Value of the progress bar. + /// An optional string to be displayed instead of the default percentage string. If this isn't provided, something like "70%" will be displayed. + /// A status string, which is displayed underneath the progress bar on the left. Default to empty. + /// A sequence number to prevent out-of-order updates, or assign 0 to indicate "always update". + /// An instance of NotificationData that can be used to update the toast. + public static NotificationData CreateProgressBarData(ToastContent toast, int index = 0, string title = default, double? value = default, string valueStringOverride = default, string status = default, uint sequence = 0) + { + var progressBar = toast.Visual.BindingGeneric.Children.Where(c => c is AdaptiveProgressBar).ElementAt(index) as AdaptiveProgressBar; + if (progressBar == null) + { + throw new ArgumentException(nameof(toast), "Given toast does not have any progress bar"); + } - if (progressBar.Value is BindableProgressBarValue bindableProgressValue && value != default) - { - data.Values[bindableProgressValue.BindingName] = value.ToString(); - } + NotificationData data = new NotificationData(); + data.SequenceNumber = sequence; - if (progressBar.ValueStringOverride is BindableString bindableValueStringOverride && valueStringOverride != default) - { - data.Values[bindableValueStringOverride.BindingName] = valueStringOverride; - } + // Native C++ doesn't support BindableString + if (progressBar.Title is BindableString bindableTitle && title != default) + { + data.Values[bindableTitle.BindingName] = title; + } - if (progressBar.Status is BindableString bindableStatus && status != default) - { - data.Values[bindableStatus.BindingName] = status; - } + if (progressBar.Value is BindableProgressBarValue bindableProgressValue && value != default) + { + data.Values[bindableProgressValue.BindingName] = value.ToString(); + } - return data; + if (progressBar.ValueStringOverride is BindableString bindableValueStringOverride && valueStringOverride != default) + { + data.Values[bindableValueStringOverride.BindingName] = valueStringOverride; } - /// - /// Add an Attribution Text to be displayed on the toast. - /// - /// Text to be displayed as Attribution Text - /// The current instance of - public ToastContentBuilder AddAttributionText(string text) + if (progressBar.Status is BindableString bindableStatus && status != default) { - return AddAttributionText(text, default); + data.Values[bindableStatus.BindingName] = status; } - /// - /// Add an Attribution Text to be displayed on the toast. - /// - /// Text to be displayed as Attribution Text - /// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". - /// The current instance of - public ToastContentBuilder AddAttributionText(string text, string language) + return data; + } + + /// + /// Add an Attribution Text to be displayed on the toast. + /// + /// Text to be displayed as Attribution Text + /// The current instance of + public ToastContentBuilder AddAttributionText(string text) + { + return AddAttributionText(text, default); + } + + /// + /// Add an Attribution Text to be displayed on the toast. + /// + /// Text to be displayed as Attribution Text + /// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". + /// The current instance of + public ToastContentBuilder AddAttributionText(string text, string language) + { + AttributionText = new ToastGenericAttributionText() + { + Text = text + }; + + if (language != default) { - AttributionText = new ToastGenericAttributionText() - { - Text = text - }; + AttributionText.Language = language; + } - if (language != default) - { - AttributionText.Language = language; - } + return this; + } + + /// + /// Override the app logo with custom image of choice that will be displayed on the toast. + /// + /// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. + /// Specify how the image should be cropped. + /// A description of the image, for users of assistive technologies. + /// A value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. + /// The current instance of + public ToastContentBuilder AddAppLogoOverride( + Uri uri, + ToastGenericAppLogoCrop? hintCrop = default, + string alternateText = default, + bool? addImageQuery = default) + { + AppLogoOverrideUri = new ToastGenericAppLogo() + { + Source = uri.OriginalString + }; - return this; + if (hintCrop != default) + { + AppLogoOverrideUri.HintCrop = hintCrop.Value; } - /// - /// Override the app logo with custom image of choice that will be displayed on the toast. - /// - /// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. - /// Specify how the image should be cropped. - /// A description of the image, for users of assistive technologies. - /// A value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. - /// The current instance of - public ToastContentBuilder AddAppLogoOverride( - Uri uri, - ToastGenericAppLogoCrop? hintCrop = default, - string alternateText = default, - bool? addImageQuery = default) + if (alternateText != default) { - AppLogoOverrideUri = new ToastGenericAppLogo() - { - Source = uri.OriginalString - }; + AppLogoOverrideUri.AlternateText = alternateText; + } - if (hintCrop != default) - { - AppLogoOverrideUri.HintCrop = hintCrop.Value; - } + if (addImageQuery != default) + { + AppLogoOverrideUri.AddImageQuery = addImageQuery; + } - if (alternateText != default) - { - AppLogoOverrideUri.AlternateText = alternateText; - } + return this; + } - if (addImageQuery != default) - { - AppLogoOverrideUri.AddImageQuery = addImageQuery; - } + /// + /// Add a hero image to the toast. + /// + /// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. + /// A description of the image, for users of assistive technologies. + /// A value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. + /// The current instance of + public ToastContentBuilder AddHeroImage( + Uri uri, + string alternateText = default, + bool? addImageQuery = default) + { + HeroImage = new ToastGenericHeroImage() + { + Source = uri.OriginalString + }; - return this; + if (alternateText != default) + { + HeroImage.AlternateText = alternateText; } - /// - /// Add a hero image to the toast. - /// - /// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. - /// A description of the image, for users of assistive technologies. - /// A value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. - /// The current instance of - public ToastContentBuilder AddHeroImage( - Uri uri, - string alternateText = default, - bool? addImageQuery = default) + if (addImageQuery != default) { - HeroImage = new ToastGenericHeroImage() - { - Source = uri.OriginalString - }; + HeroImage.AddImageQuery = addImageQuery; + } - if (alternateText != default) - { - HeroImage.AlternateText = alternateText; - } + return this; + } - if (addImageQuery != default) - { - HeroImage.AddImageQuery = addImageQuery; - } + /// + /// Add an image inline with other toast content. + /// + /// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. + /// A description of the image, for users of assistive technologies. + /// A value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. + /// A value whether a margin is removed. images have an 8px margin around them. + /// This property is not used. Setting this has no impact. + /// The current instance of + public ToastContentBuilder AddInlineImage( + Uri uri, + string alternateText = default, + bool? addImageQuery = default, + AdaptiveImageCrop? hintCrop = default, + bool? hintRemoveMargin = default) + { + var inlineImage = new AdaptiveImage() + { + Source = uri.OriginalString + }; - return this; - } - - /// - /// Add an image inline with other toast content. - /// - /// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. - /// A description of the image, for users of assistive technologies. - /// A value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. - /// A value whether a margin is removed. images have an 8px margin around them. - /// This property is not used. Setting this has no impact. - /// The current instance of - public ToastContentBuilder AddInlineImage( - Uri uri, - string alternateText = default, - bool? addImageQuery = default, - AdaptiveImageCrop? hintCrop = default, - bool? hintRemoveMargin = default) - { - var inlineImage = new AdaptiveImage() - { - Source = uri.OriginalString - }; + if (hintCrop != null) + { + inlineImage.HintCrop = hintCrop.Value; + } - if (hintCrop != null) - { - inlineImage.HintCrop = hintCrop.Value; - } + if (alternateText != default) + { + inlineImage.AlternateText = alternateText; + } - if (alternateText != default) - { - inlineImage.AlternateText = alternateText; - } + if (addImageQuery != default) + { + inlineImage.AddImageQuery = addImageQuery; + } - if (addImageQuery != default) - { - inlineImage.AddImageQuery = addImageQuery; - } + return AddVisualChild(inlineImage); + } - return AddVisualChild(inlineImage); - } + /// + /// Add a progress bar to the toast. + /// + /// Title of the progress bar. + /// Value of the progress bar. Default is 0 + /// Determine if the progress bar value should be indeterminate. Default to false. + /// An optional string to be displayed instead of the default percentage string. If this isn't provided, something like "70%" will be displayed. + /// A status string which is displayed underneath the progress bar. This string should reflect the status of the operation, like "Downloading..." or "Installing...". Default to empty. + /// The current instance of + /// More info at: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/toast-progress-bar + public ToastContentBuilder AddProgressBar(string title = default, double? value = null, bool isIndeterminate = false, string valueStringOverride = default, string status = default) + { + int index = VisualChildren.Count(c => c is AdaptiveProgressBar); - /// - /// Add a progress bar to the toast. - /// - /// Title of the progress bar. - /// Value of the progress bar. Default is 0 - /// Determine if the progress bar value should be indeterminate. Default to false. - /// An optional string to be displayed instead of the default percentage string. If this isn't provided, something like "70%" will be displayed. - /// A status string which is displayed underneath the progress bar. This string should reflect the status of the operation, like "Downloading..." or "Installing...". Default to empty. - /// The current instance of - /// More info at: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/toast-progress-bar - public ToastContentBuilder AddProgressBar(string title = default, double? value = null, bool isIndeterminate = false, string valueStringOverride = default, string status = default) + var progressBar = new AdaptiveProgressBar() { - int index = VisualChildren.Count(c => c is AdaptiveProgressBar); + }; - var progressBar = new AdaptiveProgressBar() - { - }; + if (title == default) + { + progressBar.Title = new BindableString($"progressBarTitle_{index}"); + } + else + { + progressBar.Title = title; + } - if (title == default) - { - progressBar.Title = new BindableString($"progressBarTitle_{index}"); - } - else - { - progressBar.Title = title; - } + if (isIndeterminate) + { + progressBar.Value = AdaptiveProgressBarValue.Indeterminate; + } + else if (value == null) + { + progressBar.Value = new BindableProgressBarValue($"progressValue_{index}"); + } + else + { + progressBar.Value = value.Value; + } - if (isIndeterminate) - { - progressBar.Value = AdaptiveProgressBarValue.Indeterminate; - } - else if (value == null) - { - progressBar.Value = new BindableProgressBarValue($"progressValue_{index}"); - } - else - { - progressBar.Value = value.Value; - } + if (valueStringOverride == default) + { + progressBar.ValueStringOverride = new BindableString($"progressValueString_{index}"); + } + else + { + progressBar.ValueStringOverride = valueStringOverride; + } - if (valueStringOverride == default) - { - progressBar.ValueStringOverride = new BindableString($"progressValueString_{index}"); - } - else - { - progressBar.ValueStringOverride = valueStringOverride; - } + if (status == default) + { + progressBar.Status = new BindableString($"progressStatus_{index}"); + } + else + { + progressBar.Status = status; + } - if (status == default) - { - progressBar.Status = new BindableString($"progressStatus_{index}"); - } - else - { - progressBar.Status = status; - } + return AddVisualChild(progressBar); + } - return AddVisualChild(progressBar); - } - - /// - /// Add text to the toast. - /// - /// Custom text to display on the tile. - /// This property is not used. Setting this has no effect. - /// This property is not used. Setting this has no effect. If you need to disable wrapping, set hintMaxLines to 1. - /// The maximum number of lines the text element is allowed to display. - /// hintMinLines is not used. Setting this has no effect. - /// hintAlign is not used. Setting this has no effect. - /// - /// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. - /// - /// The current instance of - /// Throws when attempting to add/reserve more than 4 lines on a single toast. - /// Throws when value is larger than 2. - /// More info at: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts#text-elements - public ToastContentBuilder AddText( - string text, - AdaptiveTextStyle? hintStyle = null, - bool? hintWrap = default, - int? hintMaxLines = default, - int? hintMinLines = default, - AdaptiveTextAlign? hintAlign = null, - string language = default) - { - int lineCount = GetCurrentTextLineCount(); - if (GetCurrentTextLineCount() == 4) - { - // Reached maximum, we can't go further. - throw new InvalidOperationException("We have reached max lines allowed (4) per toast"); - } + /// + /// Add text to the toast. + /// + /// Custom text to display on the tile. + /// This property is not used. Setting this has no effect. + /// This property is not used. Setting this has no effect. If you need to disable wrapping, set hintMaxLines to 1. + /// The maximum number of lines the text element is allowed to display. + /// hintMinLines is not used. Setting this has no effect. + /// hintAlign is not used. Setting this has no effect. + /// + /// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. + /// + /// The current instance of + /// Throws when attempting to add/reserve more than 4 lines on a single toast. + /// Throws when value is larger than 2. + /// More info at: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts#text-elements + public ToastContentBuilder AddText( + string text, + AdaptiveTextStyle? hintStyle = null, + bool? hintWrap = default, + int? hintMaxLines = default, + int? hintMinLines = default, + AdaptiveTextAlign? hintAlign = null, + string language = default) + { + int lineCount = GetCurrentTextLineCount(); + if (GetCurrentTextLineCount() == 4) + { + // Reached maximum, we can't go further. + throw new InvalidOperationException("We have reached max lines allowed (4) per toast"); + } - AdaptiveText adaptive = new AdaptiveText() - { - Text = text - }; + AdaptiveText adaptive = new AdaptiveText() + { + Text = text + }; - if (hintMaxLines != default) + if (hintMaxLines != default) + { + if (hintMaxLines > 2) { - if (hintMaxLines > 2) - { - throw new ArgumentOutOfRangeException(nameof(hintMaxLines), "max line can't go more than 2 lines."); - } - else if ((lineCount + hintMaxLines) > 4) - { - throw new InvalidOperationException($"Can't exceed more than 4 lines of text per toast. Current line count : {lineCount} | Requesting line count: {lineCount + hintMaxLines}"); - } - - adaptive.HintMaxLines = hintMaxLines; + throw new ArgumentOutOfRangeException(nameof(hintMaxLines), "max line can't go more than 2 lines."); } - - if (language != default) + else if ((lineCount + hintMaxLines) > 4) { - adaptive.Language = language; + throw new InvalidOperationException($"Can't exceed more than 4 lines of text per toast. Current line count : {lineCount} | Requesting line count: {lineCount + hintMaxLines}"); } - return AddVisualChild(adaptive); + adaptive.HintMaxLines = hintMaxLines; } - /// - /// Add a visual element to the toast. - /// - /// An instance of a class that implement . - /// The current instance of - public ToastContentBuilder AddVisualChild(IToastBindingGenericChild child) + if (language != default) { - VisualChildren.Add(child); - - return this; + adaptive.Language = language; } - private int GetCurrentTextLineCount() - { - if (!VisualChildren.Any(c => c is AdaptiveText)) - { - return 0; - } + return AddVisualChild(adaptive); + } - var textList = VisualChildren.Where(c => c is AdaptiveText).Select(c => c as AdaptiveText).ToList(); + /// + /// Add a visual element to the toast. + /// + /// An instance of a class that implement . + /// The current instance of + public ToastContentBuilder AddVisualChild(IToastBindingGenericChild child) + { + VisualChildren.Add(child); - // First one is already the header. - // https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts#text-elements - // The default (and maximum) is up to 2 lines of text for the title, and up to 4 lines (combined) for the two additional description elements (the second and third AdaptiveText). - AdaptiveText text = textList.First(); - int count = 0; - count += text.HintMaxLines ?? 2; + return this; + } - for (int i = 1; i < textList.Count; i++) - { - text = textList[i]; - count += text.HintMaxLines ?? 1; - } + private int GetCurrentTextLineCount() + { + if (!VisualChildren.Any(c => c is AdaptiveText)) + { + return 0; + } + + var textList = VisualChildren.Where(c => c is AdaptiveText).Select(c => c as AdaptiveText).ToList(); + + // First one is already the header. + // https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts#text-elements + // The default (and maximum) is up to 2 lines of text for the title, and up to 4 lines (combined) for the two additional description elements (the second and third AdaptiveText). + AdaptiveText text = textList.First(); + int count = 0; + count += text.HintMaxLines ?? 2; - return count; + for (int i = 1; i < textList.Count; i++) + { + text = textList[i]; + count += text.HintMaxLines ?? 1; } + + return count; } } diff --git a/components/Notifications/src/Toasts/Builder/ToastContentBuilder.cs b/components/Notifications/src/Toasts/Builder/ToastContentBuilder.cs index 2be548c84..793cd54ca 100644 --- a/components/Notifications/src/Toasts/Builder/ToastContentBuilder.cs +++ b/components/Notifications/src/Toasts/Builder/ToastContentBuilder.cs @@ -5,435 +5,434 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Builder class used to create +/// +public partial class ToastContentBuilder : IToastActivateableBuilder { + private Dictionary _genericArguments = new Dictionary(); + + private bool _customArgumentsUsedOnToastItself; + /// - /// Builder class used to create + /// Gets internal instance of . This is equivalent to the call to . /// - public partial class ToastContentBuilder : IToastActivateableBuilder + public ToastContent Content { - private Dictionary _genericArguments = new Dictionary(); + get; private set; + } - private bool _customArgumentsUsedOnToastItself; + /// + /// Initializes a new instance of the class. + /// + public ToastContentBuilder() + { + Content = new ToastContent(); + } - /// - /// Gets internal instance of . This is equivalent to the call to . - /// - public ToastContent Content - { - get; private set; - } + /// + /// Add custom time stamp on the toast to override the time display on the toast. + /// + /// Custom Time to be displayed on the toast + /// The current instance of + public ToastContentBuilder AddCustomTimeStamp(DateTime dateTime) + { + Content.DisplayTimestamp = dateTime; - /// - /// Initializes a new instance of the class. - /// - public ToastContentBuilder() - { - Content = new ToastContent(); - } + return this; + } - /// - /// Add custom time stamp on the toast to override the time display on the toast. - /// - /// Custom Time to be displayed on the toast - /// The current instance of - public ToastContentBuilder AddCustomTimeStamp(DateTime dateTime) - { - Content.DisplayTimestamp = dateTime; + /// + /// Add a header to a toast. + /// + /// 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. + /// A title for the header. + /// Developer-defined arguments that are returned to the app when the user clicks this header. + /// The current instance of + /// More info about toast header: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/toast-headers + public ToastContentBuilder AddHeader(string id, string title, ToastArguments arguments) + { + return AddHeader(id, title, arguments.ToString()); + } - return this; - } + /// + /// Add a header to a toast. + /// + /// 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. + /// A title for the header. + /// A developer-defined string of arguments that is returned to the app when the user clicks this header. + /// The current instance of + /// More info about toast header: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/toast-headers + public ToastContentBuilder AddHeader(string id, string title, string arguments) + { + Content.Header = new ToastHeader(id, title, arguments); - /// - /// Add a header to a toast. - /// - /// 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. - /// A title for the header. - /// Developer-defined arguments that are returned to the app when the user clicks this header. - /// The current instance of - /// More info about toast header: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/toast-headers - public ToastContentBuilder AddHeader(string id, string title, ToastArguments arguments) - { - return AddHeader(id, title, arguments.ToString()); - } + return this; + } - /// - /// Add a header to a toast. - /// - /// 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. - /// A title for the header. - /// A developer-defined string of arguments that is returned to the app when the user clicks this header. - /// The current instance of - /// More info about toast header: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/toast-headers - public ToastContentBuilder AddHeader(string id, string title, string arguments) - { - Content.Header = new ToastHeader(id, title, arguments); + /// + /// Adds a key (without value) to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key. + /// The current instance of + public ToastContentBuilder AddArgument(string key) + { + return AddArgumentHelper(key, null); + } - return this; - } + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of + public ToastContentBuilder AddArgument(string key, string value) + { + return AddArgumentHelper(key, value); + } - /// - /// Adds a key (without value) to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key. - /// The current instance of - public ToastContentBuilder AddArgument(string key) - { - return AddArgumentHelper(key, null); - } + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of + public ToastContentBuilder AddArgument(string key, int value) + { + return AddArgumentHelper(key, value.ToString()); + } - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of - public ToastContentBuilder AddArgument(string key, string value) - { - return AddArgumentHelper(key, value); - } + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of + public ToastContentBuilder AddArgument(string key, double value) + { + return AddArgumentHelper(key, value.ToString()); + } - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of - public ToastContentBuilder AddArgument(string key, int value) - { - return AddArgumentHelper(key, value.ToString()); - } + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of + public ToastContentBuilder AddArgument(string key, float value) + { + return AddArgumentHelper(key, value.ToString()); + } - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of - public ToastContentBuilder AddArgument(string key, double value) - { - return AddArgumentHelper(key, value.ToString()); - } + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of + public ToastContentBuilder AddArgument(string key, bool value) + { + return AddArgumentHelper(key, value ? "1" : "0"); // Encode as 1 or 0 to save string space + } - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of - public ToastContentBuilder AddArgument(string key, float value) - { - return AddArgumentHelper(key, value.ToString()); - } + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this 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. + /// The current instance of + public ToastContentBuilder AddArgument(string key, Enum value) + { + return AddArgumentHelper(key, ((int)(object)value).ToString()); + } - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of - public ToastContentBuilder AddArgument(string key, bool value) + private ToastContentBuilder AddArgumentHelper(string key, string value) + { + if (key == null) { - return AddArgumentHelper(key, value ? "1" : "0"); // Encode as 1 or 0 to save string space + throw new ArgumentNullException(nameof(key)); } - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this 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. - /// The current instance of - public ToastContentBuilder AddArgument(string key, Enum value) + bool alreadyExists = _genericArguments.ContainsKey(key); + + _genericArguments[key] = value; + + if (Content.ActivationType != ToastActivationType.Protocol && !_customArgumentsUsedOnToastItself) { - return AddArgumentHelper(key, ((int)(object)value).ToString()); + Content.Launch = alreadyExists ? SerializeArgumentsHelper(_genericArguments) : AddArgumentHelper(Content.Launch, key, value); } - private ToastContentBuilder AddArgumentHelper(string key, string value) + if (Content.Actions is ToastActionsCustom actions) { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - bool alreadyExists = _genericArguments.ContainsKey(key); - - _genericArguments[key] = value; - - if (Content.ActivationType != ToastActivationType.Protocol && !_customArgumentsUsedOnToastItself) - { - Content.Launch = alreadyExists ? SerializeArgumentsHelper(_genericArguments) : AddArgumentHelper(Content.Launch, key, value); - } - - if (Content.Actions is ToastActionsCustom actions) + foreach (var button in actions.Buttons) { - foreach (var button in actions.Buttons) + if (button is ToastButton b && b.CanAddArguments() && !b.ContainsArgument(key)) { - if (button is ToastButton b && b.CanAddArguments() && !b.ContainsArgument(key)) - { - b.AddArgument(key, value); - } + b.AddArgument(key, value); } } - - return this; } - private string SerializeArgumentsHelper(IDictionary arguments) - { - var args = new ToastArguments(); + return this; + } - foreach (var a in arguments) - { - args.Add(a.Key, a.Value); - } + private string SerializeArgumentsHelper(IDictionary arguments) + { + var args = new ToastArguments(); - return args.ToString(); + foreach (var a in arguments) + { + args.Add(a.Key, a.Value); } - private string AddArgumentHelper(string existing, string key, string value) - { - string pair = ToastArguments.EncodePair(key, value); + return args.ToString(); + } - if (existing == null) - { - return pair; - } - else - { - return existing + ToastArguments.Separator + pair; - } - } + private string AddArgumentHelper(string existing, string key, string value) + { + string pair = ToastArguments.EncodePair(key, value); - /// - /// Configures the toast notification to launch the specified url when the toast body is clicked. - /// - /// The protocol to launch. - /// The current instance of - public ToastContentBuilder SetProtocolActivation(Uri protocol) + if (existing == null) { - return SetProtocolActivation(protocol, default); + return pair; } - - /// - /// Configures the toast notification to launch the specified url when the toast body is clicked. - /// - /// The protocol to launch. - /// New in Creators Update: The target PFN, so that regardless of whether multiple apps are registered to handle the same protocol uri, your desired app will always be launched. - /// The current instance of - public ToastContentBuilder SetProtocolActivation(Uri protocol, string targetApplicationPfn) + else { - Content.Launch = protocol.ToString(); - Content.ActivationType = ToastActivationType.Protocol; - - if (targetApplicationPfn != null) - { - if (Content.ActivationOptions == null) - { - Content.ActivationOptions = new ToastActivationOptions(); - } - - Content.ActivationOptions.ProtocolActivationTargetApplicationPfn = targetApplicationPfn; - } - - return this; + return existing + ToastArguments.Separator + pair; } + } - /// - /// Configures the toast notification to use background activation when the toast body is clicked. - /// - /// The current instance of - public ToastContentBuilder SetBackgroundActivation() - { - Content.ActivationType = ToastActivationType.Background; - return this; - } + /// + /// Configures the toast notification to launch the specified url when the toast body is clicked. + /// + /// The protocol to launch. + /// The current instance of + public ToastContentBuilder SetProtocolActivation(Uri protocol) + { + return SetProtocolActivation(protocol, default); + } - /// - /// Instead of this method, for foreground/background activation, it is suggested to use and optionally . For protocol activation, you should use . Add info that can be used by the application when the app was activated/launched by the toast. - /// - /// Custom app-defined launch arguments to be passed along on toast activation - /// Set the activation type that will be used when the user click on this toast - /// The current instance of - public ToastContentBuilder AddToastActivationInfo(string launchArgs, ToastActivationType activationType) - { - Content.Launch = launchArgs; - Content.ActivationType = activationType; - _customArgumentsUsedOnToastItself = true; - return this; - } + /// + /// Configures the toast notification to launch the specified url when the toast body is clicked. + /// + /// The protocol to launch. + /// New in Creators Update: The target PFN, so that regardless of whether multiple apps are registered to handle the same protocol uri, your desired app will always be launched. + /// The current instance of + public ToastContentBuilder SetProtocolActivation(Uri protocol, string targetApplicationPfn) + { + Content.Launch = protocol.ToString(); + Content.ActivationType = ToastActivationType.Protocol; - /// - /// Sets the amount of time the Toast should display. You typically should use the - /// Scenario attribute instead, which impacts how long a Toast stays on screen. - /// - /// Duration of the toast - /// The current instance of - public ToastContentBuilder SetToastDuration(ToastDuration duration) + if (targetApplicationPfn != null) { - Content.Duration = duration; - return this; - } + if (Content.ActivationOptions == null) + { + Content.ActivationOptions = new ToastActivationOptions(); + } - /// - /// Sets the scenario, to make the Toast behave like an alarm, reminder, or more. - /// - /// Scenario to be used for the toast's behavior - /// The current instance of - public ToastContentBuilder SetToastScenario(ToastScenario scenario) - { - Content.Scenario = scenario; - return this; + Content.ActivationOptions.ProtocolActivationTargetApplicationPfn = targetApplicationPfn; } - /// - /// Set custom audio to go along with the toast. - /// - /// Source to the media that will be played when the toast is pop - /// Indicating whether sound should repeat as long as the Toast is shown; false to play only once (default). - /// Indicating whether sound is muted; false to allow the Toast notification sound to play (default). - /// The current instance of - public ToastContentBuilder AddAudio( - Uri src, - bool? loop = default, - bool? silent = default) - { - var audio = new ToastAudio(); - audio.Src = src; + return this; + } - if (loop != default) - { - audio.Loop = loop.Value; - } + /// + /// Configures the toast notification to use background activation when the toast body is clicked. + /// + /// The current instance of + public ToastContentBuilder SetBackgroundActivation() + { + Content.ActivationType = ToastActivationType.Background; + return this; + } - if (silent != default) - { - audio.Silent = silent.Value; - } + /// + /// Instead of this method, for foreground/background activation, it is suggested to use and optionally . For protocol activation, you should use . Add info that can be used by the application when the app was activated/launched by the toast. + /// + /// Custom app-defined launch arguments to be passed along on toast activation + /// Set the activation type that will be used when the user click on this toast + /// The current instance of + public ToastContentBuilder AddToastActivationInfo(string launchArgs, ToastActivationType activationType) + { + Content.Launch = launchArgs; + Content.ActivationType = activationType; + _customArgumentsUsedOnToastItself = true; + return this; + } - return AddAudio(audio); - } + /// + /// Sets the amount of time the Toast should display. You typically should use the + /// Scenario attribute instead, which impacts how long a Toast stays on screen. + /// + /// Duration of the toast + /// The current instance of + public ToastContentBuilder SetToastDuration(ToastDuration duration) + { + Content.Duration = duration; + return this; + } - /// - /// Set custom audio to go along with the toast. - /// - /// The to set. - /// The current instance of - public ToastContentBuilder AddAudio(ToastAudio audio) - { - if (audio.Src != null && !audio.Src.IsFile && audio.Src.Scheme != "ms-appx" && audio.Src.Scheme != "ms-winsoundevent") - { - throw new InvalidOperationException("Audio Source must either be a ms-appx file, absolute file, or ms-winsoundevent."); - } + /// + /// Sets the scenario, to make the Toast behave like an alarm, reminder, or more. + /// + /// Scenario to be used for the toast's behavior + /// The current instance of + public ToastContentBuilder SetToastScenario(ToastScenario scenario) + { + Content.Scenario = scenario; + return this; + } - Content.Audio = audio; - return this; - } + /// + /// Set custom audio to go along with the toast. + /// + /// Source to the media that will be played when the toast is pop + /// Indicating whether sound should repeat as long as the Toast is shown; false to play only once (default). + /// Indicating whether sound is muted; false to allow the Toast notification sound to play (default). + /// The current instance of + public ToastContentBuilder AddAudio( + Uri src, + bool? loop = default, + bool? silent = default) + { + var audio = new ToastAudio(); + audio.Src = src; - /// - /// Get the instance of that has been built by the builder with specified configuration so far. - /// - /// An instance of that can be used to create tile notification. - public ToastContent GetToastContent() + if (loop != default) { - return Content; + audio.Loop = loop.Value; } - /// - /// Retrieves the notification XML content as a WinRT XmlDocument, so that it can be used with a local Toast notification's constructor on either or . - /// - /// The notification XML content as a WinRT XmlDocument. - public Windows.Data.Xml.Dom.XmlDocument GetXml() + if (silent != default) { - return GetToastContent().GetXml(); + audio.Silent = silent.Value; } - /// - /// Shows a new toast notification with the current content. - /// - public void Show() + return AddAudio(audio); + } + + /// + /// Set custom audio to go along with the toast. + /// + /// The to set. + /// The current instance of + public ToastContentBuilder AddAudio(ToastAudio audio) + { + if (audio.Src != null && !audio.Src.IsFile && audio.Src.Scheme != "ms-appx" && audio.Src.Scheme != "ms-winsoundevent") { - CustomizeToast customize = null; - Show(customize); + throw new InvalidOperationException("Audio Source must either be a ms-appx file, absolute file, or ms-winsoundevent."); } - /// - /// Shows a new toast notification with the current content. - /// - /// Allows you to set additional properties on the object. - public void Show(CustomizeToast customize) - { - var notif = new Windows.UI.Notifications.ToastNotification(GetToastContent().GetXml()); - customize?.Invoke(notif); + Content.Audio = audio; + return this; + } - ToastNotificationManagerCompat.CreateToastNotifier().Show(notif); - } + /// + /// Get the instance of that has been built by the builder with specified configuration so far. + /// + /// An instance of that can be used to create tile notification. + public ToastContent GetToastContent() + { + return Content; + } - /// - /// Shows a new toast notification with the current content. - /// - /// Allows you to set additional properties on the object. - /// An operation that completes after your async customizations have completed. - public Windows.Foundation.IAsyncAction Show(CustomizeToastAsync customize) - { - return ShowAsyncHelper(customize).AsAsyncAction(); - } + /// + /// Retrieves the notification XML content as a WinRT XmlDocument, so that it can be used with a local Toast notification's constructor on either or . + /// + /// The notification XML content as a WinRT XmlDocument. + public Windows.Data.Xml.Dom.XmlDocument GetXml() + { + return GetToastContent().GetXml(); + } - private async System.Threading.Tasks.Task ShowAsyncHelper(CustomizeToastAsync customize) - { - var notif = new Windows.UI.Notifications.ToastNotification(GetToastContent().GetXml()); + /// + /// Shows a new toast notification with the current content. + /// + public void Show() + { + CustomizeToast customize = null; + Show(customize); + } - if (customize != null) - { - await customize.Invoke(notif); - } + /// + /// Shows a new toast notification with the current content. + /// + /// Allows you to set additional properties on the object. + public void Show(CustomizeToast customize) + { + var notif = new Windows.UI.Notifications.ToastNotification(GetToastContent().GetXml()); + customize?.Invoke(notif); - ToastNotificationManagerCompat.CreateToastNotifier().Show(notif); - } + ToastNotificationManagerCompat.CreateToastNotifier().Show(notif); + } + + /// + /// Shows a new toast notification with the current content. + /// + /// Allows you to set additional properties on the object. + /// An operation that completes after your async customizations have completed. + public Windows.Foundation.IAsyncAction Show(CustomizeToastAsync customize) + { + return ShowAsyncHelper(customize).AsAsyncAction(); + } - /// - /// Schedules the notification. - /// - /// The date and time that Windows should display the toast notification. This time must be in the future. - public void Schedule(DateTimeOffset deliveryTime) + private async System.Threading.Tasks.Task ShowAsyncHelper(CustomizeToastAsync customize) + { + var notif = new Windows.UI.Notifications.ToastNotification(GetToastContent().GetXml()); + + if (customize != null) { - CustomizeScheduledToast customize = null; - Schedule(deliveryTime, customize); + await customize.Invoke(notif); } - /// - /// Schedules the notification. - /// - /// The date and time that Windows should display the toast notification. This time must be in the future. - /// Allows you to set additional properties on the object. - public void Schedule(DateTimeOffset deliveryTime, CustomizeScheduledToast customize) - { - var notif = new Windows.UI.Notifications.ScheduledToastNotification(GetToastContent().GetXml(), deliveryTime); - customize?.Invoke(notif); + ToastNotificationManagerCompat.CreateToastNotifier().Show(notif); + } - ToastNotificationManagerCompat.CreateToastNotifier().AddToSchedule(notif); - } + /// + /// Schedules the notification. + /// + /// The date and time that Windows should display the toast notification. This time must be in the future. + public void Schedule(DateTimeOffset deliveryTime) + { + CustomizeScheduledToast customize = null; + Schedule(deliveryTime, customize); + } - /// - /// Schedules the notification. - /// - /// The date and time that Windows should display the toast notification. This time must be in the future. - /// Allows you to set additional properties on the object. - /// An operation that completes after your async customizations have completed. - public Windows.Foundation.IAsyncAction Schedule(DateTimeOffset deliveryTime, CustomizeScheduledToastAsync customize) - { - return ScheduleAsyncHelper(deliveryTime, customize).AsAsyncAction(); - } + /// + /// Schedules the notification. + /// + /// The date and time that Windows should display the toast notification. This time must be in the future. + /// Allows you to set additional properties on the object. + public void Schedule(DateTimeOffset deliveryTime, CustomizeScheduledToast customize) + { + var notif = new Windows.UI.Notifications.ScheduledToastNotification(GetToastContent().GetXml(), deliveryTime); + customize?.Invoke(notif); - private async System.Threading.Tasks.Task ScheduleAsyncHelper(DateTimeOffset deliveryTime, CustomizeScheduledToastAsync customize = null) - { - var notif = new Windows.UI.Notifications.ScheduledToastNotification(GetToastContent().GetXml(), deliveryTime); + ToastNotificationManagerCompat.CreateToastNotifier().AddToSchedule(notif); + } - if (customize != null) - { - await customize.Invoke(notif); - } + /// + /// Schedules the notification. + /// + /// The date and time that Windows should display the toast notification. This time must be in the future. + /// Allows you to set additional properties on the object. + /// An operation that completes after your async customizations have completed. + public Windows.Foundation.IAsyncAction Schedule(DateTimeOffset deliveryTime, CustomizeScheduledToastAsync customize) + { + return ScheduleAsyncHelper(deliveryTime, customize).AsAsyncAction(); + } + + private async System.Threading.Tasks.Task ScheduleAsyncHelper(DateTimeOffset deliveryTime, CustomizeScheduledToastAsync customize = null) + { + var notif = new Windows.UI.Notifications.ScheduledToastNotification(GetToastContent().GetXml(), deliveryTime); - ToastNotificationManagerCompat.CreateToastNotifier().AddToSchedule(notif); + if (customize != null) + { + await customize.Invoke(notif); } + + ToastNotificationManagerCompat.CreateToastNotifier().AddToSchedule(notif); } } diff --git a/components/Notifications/src/Toasts/Compat/ToastNotificationHistoryCompat.cs b/components/Notifications/src/Toasts/Compat/ToastNotificationHistoryCompat.cs index f94a46ff2..6e0429ae4 100644 --- a/components/Notifications/src/Toasts/Compat/ToastNotificationHistoryCompat.cs +++ b/components/Notifications/src/Toasts/Compat/ToastNotificationHistoryCompat.cs @@ -5,86 +5,85 @@ using System.Collections.Generic; using Windows.UI.Notifications; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Manages the toast notifications for an app including the ability the clear all toast history and removing individual toasts. +/// +public class ToastNotificationHistoryCompat { + private string _aumid; + private ToastNotificationHistory _history; + + internal ToastNotificationHistoryCompat(string aumid) + { + _aumid = aumid; + _history = ToastNotificationManager.History; + } + /// - /// Manages the toast notifications for an app including the ability the clear all toast history and removing individual toasts. + /// Removes all notifications sent by this app from action center. /// - public class ToastNotificationHistoryCompat + public void Clear() { - private string _aumid; - private ToastNotificationHistory _history; - - internal ToastNotificationHistoryCompat(string aumid) + if (_aumid != null) { - _aumid = aumid; - _history = ToastNotificationManager.History; + _history.Clear(_aumid); } - - /// - /// Removes all notifications sent by this app from action center. - /// - public void Clear() + else { - if (_aumid != null) - { - _history.Clear(_aumid); - } - else - { - _history.Clear(); - } + _history.Clear(); } + } - /// - /// Gets all notifications sent by this app that are currently still in Action Center. - /// - /// A collection of toasts. - public IReadOnlyList GetHistory() + /// + /// Gets all notifications sent by this app that are currently still in Action Center. + /// + /// A collection of toasts. + public IReadOnlyList GetHistory() + { + return _aumid != null ? _history.GetHistory(_aumid) : _history.GetHistory(); + } + + /// + /// Removes an individual toast, with the specified tag label, from action center. + /// + /// The tag label of the toast notification to be removed. + public void Remove(string tag) + { + _history.Remove(tag); + } + + /// + /// Removes a toast notification from the action using the notification's tag and group labels. + /// + /// The tag label of the toast notification to be removed. + /// The group label of the toast notification to be removed. + public void Remove(string tag, string group) + { + if (_aumid != null) { - return _aumid != null ? _history.GetHistory(_aumid) : _history.GetHistory(); + _history.Remove(tag, group, _aumid); } - - /// - /// Removes an individual toast, with the specified tag label, from action center. - /// - /// The tag label of the toast notification to be removed. - public void Remove(string tag) + else { - _history.Remove(tag); + _history.Remove(tag, group); } + } - /// - /// Removes a toast notification from the action using the notification's tag and group labels. - /// - /// The tag label of the toast notification to be removed. - /// The group label of the toast notification to be removed. - public void Remove(string tag, string group) + /// + /// Removes a group of toast notifications, identified by the specified group label, from action center. + /// + /// The group label of the toast notifications to be removed. + public void RemoveGroup(string group) + { + if (_aumid != null) { - if (_aumid != null) - { - _history.Remove(tag, group, _aumid); - } - else - { - _history.Remove(tag, group); - } + _history.RemoveGroup(group, _aumid); } - - /// - /// Removes a group of toast notifications, identified by the specified group label, from action center. - /// - /// The group label of the toast notifications to be removed. - public void RemoveGroup(string group) + else { - if (_aumid != null) - { - _history.RemoveGroup(group, _aumid); - } - else - { - _history.RemoveGroup(group); - } + _history.RemoveGroup(group); } } } diff --git a/components/Notifications/src/Toasts/Compat/ToastNotificationManagerCompat.cs b/components/Notifications/src/Toasts/Compat/ToastNotificationManagerCompat.cs index 443e359fb..cd8f6f794 100644 --- a/components/Notifications/src/Toasts/Compat/ToastNotificationManagerCompat.cs +++ b/components/Notifications/src/Toasts/Compat/ToastNotificationManagerCompat.cs @@ -15,42 +15,41 @@ using Windows.Foundation.Collections; using Windows.UI.Notifications; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Provides access to sending and managing toast notifications. Works for all types of apps, even Win32 non-MSIX/sparse apps. +/// +public static class ToastNotificationManagerCompat { /// - /// Provides access to sending and managing toast notifications. Works for all types of apps, even Win32 non-MSIX/sparse apps. + /// Creates a toast notifier. /// - public static class ToastNotificationManagerCompat + /// An instance of the toast notifier. + public static ToastNotifierCompat CreateToastNotifier() { - /// - /// Creates a toast notifier. - /// - /// An instance of the toast notifier. - public static ToastNotifierCompat CreateToastNotifier() - { - return new ToastNotifierCompat(ToastNotificationManager.CreateToastNotifier()); - } + return new ToastNotifierCompat(ToastNotificationManager.CreateToastNotifier()); + } - /// - /// Gets the object. - /// - public static ToastNotificationHistoryCompat History + /// + /// Gets the object. + /// + public static ToastNotificationHistoryCompat History + { + get { - get - { - return new ToastNotificationHistoryCompat(null); - } + return new ToastNotificationHistoryCompat(null); } + } - /// - /// Gets a value indicating whether http images can be used within toasts. This is true if running with package identity (UWP, MSIX, or sparse package). - /// - public static bool CanUseHttpImages + /// + /// Gets a value indicating whether http images can be used within toasts. This is true if running with package identity (UWP, MSIX, or sparse package). + /// + public static bool CanUseHttpImages + { + get { - get - { - return true; - } + return true; } } } diff --git a/components/Notifications/src/Toasts/Compat/ToastNotifierCompat.cs b/components/Notifications/src/Toasts/Compat/ToastNotifierCompat.cs index a27ff19a5..a4637f76a 100644 --- a/components/Notifications/src/Toasts/Compat/ToastNotifierCompat.cs +++ b/components/Notifications/src/Toasts/Compat/ToastNotifierCompat.cs @@ -5,97 +5,96 @@ using System.Collections.Generic; using Windows.UI.Notifications; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Allows you to show and schedule toast notifications. +/// +public sealed class ToastNotifierCompat { + private ToastNotifier _notifier; + + internal ToastNotifierCompat(ToastNotifier notifier) + { + _notifier = notifier; + } + /// - /// Allows you to show and schedule toast notifications. + /// Displays the specified toast notification. /// - public sealed class ToastNotifierCompat + /// The object that contains the content of the toast notification to display. + public void Show(ToastNotification notification) { - private ToastNotifier _notifier; - - internal ToastNotifierCompat(ToastNotifier notifier) - { - _notifier = notifier; - } - - /// - /// Displays the specified toast notification. - /// - /// The object that contains the content of the toast notification to display. - public void Show(ToastNotification notification) - { - _notifier.Show(notification); - } + _notifier.Show(notification); + } - /// - /// Hides the specified toast notification from the screen (moves it into Action Center). - /// - /// The object that specifies the toast to hide. - public void Hide(ToastNotification notification) - { - _notifier.Hide(notification); - } + /// + /// Hides the specified toast notification from the screen (moves it into Action Center). + /// + /// The object that specifies the toast to hide. + public void Hide(ToastNotification notification) + { + _notifier.Hide(notification); + } - /// - /// Adds a ScheduledToastNotification for later display by Windows. - /// - /// The scheduled toast notification, which includes its content and timing instructions. - public void AddToSchedule(ScheduledToastNotification scheduledToast) - { - _notifier.AddToSchedule(scheduledToast); - } + /// + /// Adds a ScheduledToastNotification for later display by Windows. + /// + /// The scheduled toast notification, which includes its content and timing instructions. + public void AddToSchedule(ScheduledToastNotification scheduledToast) + { + _notifier.AddToSchedule(scheduledToast); + } - /// - /// Cancels the scheduled display of a specified ScheduledToastNotification. - /// - /// The notification to remove from the schedule. - public void RemoveFromSchedule(ScheduledToastNotification scheduledToast) - { - _notifier.RemoveFromSchedule(scheduledToast); - } + /// + /// Cancels the scheduled display of a specified ScheduledToastNotification. + /// + /// The notification to remove from the schedule. + public void RemoveFromSchedule(ScheduledToastNotification scheduledToast) + { + _notifier.RemoveFromSchedule(scheduledToast); + } - /// - /// Gets the collection of ScheduledToastNotification objects that this app has scheduled for display. - /// - /// The collection of scheduled toast notifications that the app bound to this notifier has scheduled for timed display. - public IReadOnlyList GetScheduledToastNotifications() - { - return _notifier.GetScheduledToastNotifications(); - } + /// + /// Gets the collection of ScheduledToastNotification objects that this app has scheduled for display. + /// + /// The collection of scheduled toast notifications that the app bound to this notifier has scheduled for timed display. + public IReadOnlyList GetScheduledToastNotifications() + { + return _notifier.GetScheduledToastNotifications(); + } - /// - /// Updates the existing toast notification that has the specified tag and belongs to the specified notification group. - /// - /// An object that contains the updated info. - /// The identifier of the toast notification to update. - /// The ID of the ToastCollection that contains the notification. - /// A value that indicates the result of the update (failure, success, etc). - public NotificationUpdateResult Update(NotificationData data, string tag, string group) - { - return _notifier.Update(data, tag, group); - } + /// + /// Updates the existing toast notification that has the specified tag and belongs to the specified notification group. + /// + /// An object that contains the updated info. + /// The identifier of the toast notification to update. + /// The ID of the ToastCollection that contains the notification. + /// A value that indicates the result of the update (failure, success, etc). + public NotificationUpdateResult Update(NotificationData data, string tag, string group) + { + return _notifier.Update(data, tag, group); + } - /// - /// Updates the existing toast notification that has the specified tag. - /// - /// An object that contains the updated info. - /// The identifier of the toast notification to update. - /// A value that indicates the result of the update (failure, success, etc). - public NotificationUpdateResult Update(NotificationData data, string tag) - { - return _notifier.Update(data, tag); - } + /// + /// Updates the existing toast notification that has the specified tag. + /// + /// An object that contains the updated info. + /// The identifier of the toast notification to update. + /// A value that indicates the result of the update (failure, success, etc). + public NotificationUpdateResult Update(NotificationData data, string tag) + { + return _notifier.Update(data, tag); + } - /// - /// Gets a value that tells you whether there is an app, user, or system block that prevents the display of a toast notification. - /// - public NotificationSetting Setting + /// + /// Gets a value that tells you whether there is an app, user, or system block that prevents the display of a toast notification. + /// + public NotificationSetting Setting + { + get { - get - { - return _notifier.Setting; - } + return _notifier.Setting; } } } diff --git a/components/Notifications/src/Toasts/Elements/Element_Toast.cs b/components/Notifications/src/Toasts/Elements/Element_Toast.cs index 1e158248c..6a895f476 100644 --- a/components/Notifications/src/Toasts/Elements/Element_Toast.cs +++ b/components/Notifications/src/Toasts/Elements/Element_Toast.cs @@ -5,152 +5,151 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_Toast : BaseElement, IElement_ToastActivatable, IHaveXmlAdditionalProperties, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren { - internal sealed class Element_Toast : BaseElement, IElement_ToastActivatable, IHaveXmlAdditionalProperties, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren - { - internal const ToastScenario DEFAULT_SCENARIO = ToastScenario.Default; - internal const Element_ToastActivationType DEFAULT_ACTIVATION_TYPE = Element_ToastActivationType.Foreground; - internal const ToastDuration DEFAULT_DURATION = ToastDuration.Short; + internal const ToastScenario DEFAULT_SCENARIO = ToastScenario.Default; + internal const Element_ToastActivationType DEFAULT_ACTIVATION_TYPE = Element_ToastActivationType.Foreground; + internal const ToastDuration DEFAULT_DURATION = ToastDuration.Short; - public Element_ToastActivationType ActivationType { get; set; } = DEFAULT_ACTIVATION_TYPE; + public Element_ToastActivationType ActivationType { get; set; } = DEFAULT_ACTIVATION_TYPE; - public string ProtocolActivationTargetApplicationPfn { get; set; } + public string ProtocolActivationTargetApplicationPfn { get; set; } - public ToastAfterActivationBehavior AfterActivationBehavior + public ToastAfterActivationBehavior AfterActivationBehavior + { + get { - get - { - return ToastAfterActivationBehavior.Default; - } + return ToastAfterActivationBehavior.Default; + } - set + set + { + if (value != ToastAfterActivationBehavior.Default) { - if (value != ToastAfterActivationBehavior.Default) - { - throw new InvalidOperationException("AfterActivationBehavior on ToastContent only supports the Default value."); - } + throw new InvalidOperationException("AfterActivationBehavior on ToastContent only supports the Default value."); } } + } - public ToastDuration Duration { get; set; } = DEFAULT_DURATION; + public ToastDuration Duration { get; set; } = DEFAULT_DURATION; - public string Launch { get; set; } + public string Launch { get; set; } - public ToastScenario Scenario { get; set; } = DEFAULT_SCENARIO; + public ToastScenario Scenario { get; set; } = DEFAULT_SCENARIO; - public DateTimeOffset? DisplayTimestamp { get; set; } + public DateTimeOffset? DisplayTimestamp { get; set; } - public Element_ToastVisual Visual { get; set; } + public Element_ToastVisual Visual { get; set; } - public Element_ToastAudio Audio { get; set; } + public Element_ToastAudio Audio { get; set; } - public Element_ToastActions Actions { get; set; } + public Element_ToastActions Actions { get; set; } - public Element_ToastHeader Header { get; set; } + public Element_ToastHeader Header { get; set; } - public string HintToastId { get; set; } + public string HintToastId { get; set; } - public string HintPeople { get; set; } + public string HintPeople { get; set; } - public IReadOnlyDictionary AdditionalProperties { get; set; } + public IReadOnlyDictionary AdditionalProperties { get; set; } - public static Element_ToastActivationType ConvertActivationType(ToastActivationType publicType) + public static Element_ToastActivationType ConvertActivationType(ToastActivationType publicType) + { + switch (publicType) { - switch (publicType) - { - case ToastActivationType.Foreground: - return Element_ToastActivationType.Foreground; + case ToastActivationType.Foreground: + return Element_ToastActivationType.Foreground; - case ToastActivationType.Background: - return Element_ToastActivationType.Background; + case ToastActivationType.Background: + return Element_ToastActivationType.Background; - case ToastActivationType.Protocol: - return Element_ToastActivationType.Protocol; + case ToastActivationType.Protocol: + return Element_ToastActivationType.Protocol; - default: - throw new NotImplementedException(); - } + default: + throw new NotImplementedException(); } + } - /// - string IHaveXmlName.Name => "toast"; + /// + string IHaveXmlName.Name => "toast"; - /// - IEnumerable IHaveXmlChildren.Children => new object[] { Visual, Audio, Actions, Header }; + /// + IEnumerable IHaveXmlChildren.Children => new object[] { Visual, Audio, Actions, Header }; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + if (ActivationType != DEFAULT_ACTIVATION_TYPE) { - if (ActivationType != DEFAULT_ACTIVATION_TYPE) - { - yield return new("activationType", ActivationType.ToPascalCaseString()); - } - - yield return new("protocolActivationTargetApplicationPfn", ProtocolActivationTargetApplicationPfn); + yield return new("activationType", ActivationType.ToPascalCaseString()); + } - if (AfterActivationBehavior != ToastAfterActivationBehavior.Default) - { - yield return new("afterActivationBehavior", AfterActivationBehavior.ToPascalCaseString()); - } + yield return new("protocolActivationTargetApplicationPfn", ProtocolActivationTargetApplicationPfn); - if (Duration != DEFAULT_DURATION) - { - yield return new("duration", Duration.ToPascalCaseString()); - } + if (AfterActivationBehavior != ToastAfterActivationBehavior.Default) + { + yield return new("afterActivationBehavior", AfterActivationBehavior.ToPascalCaseString()); + } - yield return new("launch", Launch); + if (Duration != DEFAULT_DURATION) + { + yield return new("duration", Duration.ToPascalCaseString()); + } - if (Scenario != DEFAULT_SCENARIO) - { - yield return new("scenario", Scenario.ToPascalCaseString()); - } + yield return new("launch", Launch); - yield return new("displayTimestamp", DisplayTimestamp); - yield return new("hint-toastId", HintToastId); - yield return new("hint-people", HintPeople); + if (Scenario != DEFAULT_SCENARIO) + { + yield return new("scenario", Scenario.ToPascalCaseString()); } + + yield return new("displayTimestamp", DisplayTimestamp); + yield return new("hint-toastId", HintToastId); + yield return new("hint-people", HintPeople); } +} +/// +/// The amount of time the Toast should display. +/// +public enum ToastDuration +{ /// - /// The amount of time the Toast should display. + /// Default value. Toast appears for a short while and then goes into Action Center. /// - public enum ToastDuration - { - /// - /// Default value. Toast appears for a short while and then goes into Action Center. - /// - Short, - - /// - /// Toast stays on-screen for longer, and then goes into Action Center. - /// - Long - } + Short, /// - /// Specifies the scenario, controlling behaviors about the Toast. + /// Toast stays on-screen for longer, and then goes into Action Center. /// - public enum ToastScenario - { - /// - /// The normal Toast behavior. The Toast appears for a short duration, and then automatically dismisses into Action Center. - /// - Default, - - /// - /// Causes the Toast to stay on-screen and expanded until the user takes action. Also causes a looping alarm sound to be selected by default. - /// - Alarm, - - /// - /// Causes the Toast to stay on-screen and expanded until the user takes action. - /// - Reminder, - - /// - /// Causes the Toast to stay on-screen and expanded until the user takes action (on Mobile this expands to full screen). Also causes a looping incoming call sound to be selected by default. - /// - IncomingCall - } + Long +} + +/// +/// Specifies the scenario, controlling behaviors about the Toast. +/// +public enum ToastScenario +{ + /// + /// The normal Toast behavior. The Toast appears for a short duration, and then automatically dismisses into Action Center. + /// + Default, + + /// + /// Causes the Toast to stay on-screen and expanded until the user takes action. Also causes a looping alarm sound to be selected by default. + /// + Alarm, + + /// + /// Causes the Toast to stay on-screen and expanded until the user takes action. + /// + Reminder, + + /// + /// Causes the Toast to stay on-screen and expanded until the user takes action (on Mobile this expands to full screen). Also causes a looping incoming call sound to be selected by default. + /// + IncomingCall } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Elements/Element_ToastAction.cs b/components/Notifications/src/Toasts/Elements/Element_ToastAction.cs index eaab27b19..d9b387520 100644 --- a/components/Notifications/src/Toasts/Elements/Element_ToastAction.cs +++ b/components/Notifications/src/Toasts/Elements/Element_ToastAction.cs @@ -4,103 +4,102 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_ToastAction : IElement_ToastActionsChild, IElement_ToastActivatable, IHaveXmlName, IHaveXmlNamedProperties { - internal sealed class Element_ToastAction : IElement_ToastActionsChild, IElement_ToastActivatable, IHaveXmlName, IHaveXmlNamedProperties - { - internal const Element_ToastActivationType DEFAULT_ACTIVATION_TYPE = Element_ToastActivationType.Foreground; - internal const ToastAfterActivationBehavior DEFAULT_AFTER_ACTIVATION_BEHAVIOR = ToastAfterActivationBehavior.Default; - internal const Element_ToastActionPlacement DEFAULT_PLACEMENT = Element_ToastActionPlacement.Inline; + internal const Element_ToastActivationType DEFAULT_ACTIVATION_TYPE = Element_ToastActivationType.Foreground; + internal const ToastAfterActivationBehavior DEFAULT_AFTER_ACTIVATION_BEHAVIOR = ToastAfterActivationBehavior.Default; + internal const Element_ToastActionPlacement DEFAULT_PLACEMENT = Element_ToastActionPlacement.Inline; - /// - /// Gets or sets the text to be displayed on the button. - /// - public string Content { get; set; } + /// + /// Gets or sets the text to be displayed on the button. + /// + public string Content { get; set; } - /// - /// Gets or sets the arguments attribute describing the app-defined data that the app can later retrieve once it is activated from user taking this action. - /// - public string Arguments { get; set; } + /// + /// Gets or sets the arguments attribute describing the app-defined data that the app can later retrieve once it is activated from user taking this action. + /// + public string Arguments { get; set; } - public Element_ToastActivationType ActivationType { get; set; } = DEFAULT_ACTIVATION_TYPE; + public Element_ToastActivationType ActivationType { get; set; } = DEFAULT_ACTIVATION_TYPE; - public string ProtocolActivationTargetApplicationPfn { get; set; } + public string ProtocolActivationTargetApplicationPfn { get; set; } - public ToastAfterActivationBehavior AfterActivationBehavior { get; set; } = DEFAULT_AFTER_ACTIVATION_BEHAVIOR; + public ToastAfterActivationBehavior AfterActivationBehavior { get; set; } = DEFAULT_AFTER_ACTIVATION_BEHAVIOR; - /// - /// Gets or sets optional value to provide an image icon for this action to display inside the button alone with the text content. - /// - public string ImageUri { get; set; } + /// + /// Gets or sets optional value to provide an image icon for this action to display inside the button alone with the text content. + /// + public string ImageUri { get; set; } - /// - /// Gets or sets value used for the quick reply scenario. - /// - public string InputId { get; set; } + /// + /// Gets or sets value used for the quick reply scenario. + /// + public string InputId { get; set; } - public Element_ToastActionPlacement Placement { get; set; } = DEFAULT_PLACEMENT; + public Element_ToastActionPlacement Placement { get; set; } = DEFAULT_PLACEMENT; - public string HintActionId { get; set; } + public string HintActionId { get; set; } - /// - string IHaveXmlName.Name => "action"; + /// + string IHaveXmlName.Name => "action"; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("content", Content); - yield return new("arguments", Arguments); - - if (ActivationType != DEFAULT_ACTIVATION_TYPE) - { - yield return new("activationType", ActivationType.ToPascalCaseString()); - } + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("content", Content); + yield return new("arguments", Arguments); - yield return new("protocolActivationTargetApplicationPfn", ProtocolActivationTargetApplicationPfn); + if (ActivationType != DEFAULT_ACTIVATION_TYPE) + { + yield return new("activationType", ActivationType.ToPascalCaseString()); + } - if (AfterActivationBehavior != DEFAULT_AFTER_ACTIVATION_BEHAVIOR) - { - yield return new("afterActivationBehavior", AfterActivationBehavior.ToPascalCaseString()); - } + yield return new("protocolActivationTargetApplicationPfn", ProtocolActivationTargetApplicationPfn); - yield return new("imageUri", ImageUri); - yield return new("hint-inputId", InputId); + if (AfterActivationBehavior != DEFAULT_AFTER_ACTIVATION_BEHAVIOR) + { + yield return new("afterActivationBehavior", AfterActivationBehavior.ToPascalCaseString()); + } - if (Placement != DEFAULT_PLACEMENT) - { - yield return new("placement", Placement.ToPascalCaseString()); - } + yield return new("imageUri", ImageUri); + yield return new("hint-inputId", InputId); - yield return new("hint-actionId", HintActionId); + if (Placement != DEFAULT_PLACEMENT) + { + yield return new("placement", Placement.ToPascalCaseString()); } - } - internal enum Element_ToastActionPlacement - { - Inline, - ContextMenu + yield return new("hint-actionId", HintActionId); } +} - internal enum Element_ToastActivationType - { - /// - /// Default value. Your foreground app is launched. - /// - Foreground, - - /// - /// Your corresponding background task (assuming you set everything up) is triggered, and you can execute code in the background (like sending the user's quick reply message) without interrupting the user. - /// - Background, - - /// - /// Launch a different app using protocol activation. - /// - Protocol, - - /// - /// System handles the activation. - /// - System - } +internal enum Element_ToastActionPlacement +{ + Inline, + ContextMenu +} + +internal enum Element_ToastActivationType +{ + /// + /// Default value. Your foreground app is launched. + /// + Foreground, + + /// + /// Your corresponding background task (assuming you set everything up) is triggered, and you can execute code in the background (like sending the user's quick reply message) without interrupting the user. + /// + Background, + + /// + /// Launch a different app using protocol activation. + /// + Protocol, + + /// + /// System handles the activation. + /// + System } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Elements/Element_ToastActions.cs b/components/Notifications/src/Toasts/Elements/Element_ToastActions.cs index c5ff90347..be2bff657 100644 --- a/components/Notifications/src/Toasts/Elements/Element_ToastActions.cs +++ b/components/Notifications/src/Toasts/Elements/Element_ToastActions.cs @@ -4,39 +4,38 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_ToastActions : IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren { - internal sealed class Element_ToastActions : IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren - { - internal const ToastSystemCommand DEFAULT_SYSTEM_COMMAND = ToastSystemCommand.None; + internal const ToastSystemCommand DEFAULT_SYSTEM_COMMAND = ToastSystemCommand.None; - public ToastSystemCommand SystemCommands { get; set; } = ToastSystemCommand.None; + public ToastSystemCommand SystemCommands { get; set; } = ToastSystemCommand.None; - public IList Children { get; private set; } = new List(); + public IList Children { get; private set; } = new List(); - /// - string IHaveXmlName.Name => "actions"; + /// + string IHaveXmlName.Name => "actions"; - /// - IEnumerable IHaveXmlChildren.Children => Children; + /// + IEnumerable IHaveXmlChildren.Children => Children; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + if (SystemCommands != DEFAULT_SYSTEM_COMMAND) { - if (SystemCommands != DEFAULT_SYSTEM_COMMAND) - { - yield return new("hint-systemCommands", SystemCommands); - } + yield return new("hint-systemCommands", SystemCommands); } } +} - internal interface IElement_ToastActionsChild - { - } +internal interface IElement_ToastActionsChild +{ +} - internal enum ToastSystemCommand - { - None, - SnoozeAndDismiss - } +internal enum ToastSystemCommand +{ + None, + SnoozeAndDismiss } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Elements/Element_ToastAudio.cs b/components/Notifications/src/Toasts/Elements/Element_ToastAudio.cs index 2a674556a..34b8949d9 100644 --- a/components/Notifications/src/Toasts/Elements/Element_ToastAudio.cs +++ b/components/Notifications/src/Toasts/Elements/Element_ToastAudio.cs @@ -5,42 +5,41 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_ToastAudio : IHaveXmlName, IHaveXmlNamedProperties { - internal sealed class Element_ToastAudio : IHaveXmlName, IHaveXmlNamedProperties - { - internal const bool DEFAULT_LOOP = false; - internal const bool DEFAULT_SILENT = false; + internal const bool DEFAULT_LOOP = false; + internal const bool DEFAULT_SILENT = false; - /// - /// Gets or sets the media file to play in place of the default sound. This can either be a ms-winsoundevent value, or a custom ms-appx:/// or ms-appdata:/// file, or null for the default sound. - /// - public Uri Src { get; set; } + /// + /// Gets or sets the media file to play in place of the default sound. This can either be a ms-winsoundevent value, or a custom ms-appx:/// or ms-appdata:/// file, or null for the default sound. + /// + public Uri Src { get; set; } - public bool Loop { get; set; } = DEFAULT_LOOP; + public bool Loop { get; set; } = DEFAULT_LOOP; - /// - /// Gets or sets a value indicating whether the sound is muted; false to allow the Toast notification sound to play. - /// - public bool Silent { get; set; } = DEFAULT_SILENT; + /// + /// Gets or sets a value indicating whether the sound is muted; false to allow the Toast notification sound to play. + /// + public bool Silent { get; set; } = DEFAULT_SILENT; - /// - string IHaveXmlName.Name => "audio"; + /// + string IHaveXmlName.Name => "audio"; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("src", Src); + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("src", Src); - if (Loop != DEFAULT_LOOP) - { - yield return new("loop", Loop); - } + if (Loop != DEFAULT_LOOP) + { + yield return new("loop", Loop); + } - if (Silent != DEFAULT_SILENT) - { - yield return new("silent", Silent); - } + if (Silent != DEFAULT_SILENT) + { + yield return new("silent", Silent); } } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Elements/Element_ToastBinding.cs b/components/Notifications/src/Toasts/Elements/Element_ToastBinding.cs index c5a680a74..f2fda2f58 100644 --- a/components/Notifications/src/Toasts/Elements/Element_ToastBinding.cs +++ b/components/Notifications/src/Toasts/Elements/Element_ToastBinding.cs @@ -5,73 +5,72 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_ToastBinding : IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren { - internal sealed class Element_ToastBinding : IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren + public Element_ToastBinding(ToastTemplateType template) { - public Element_ToastBinding(ToastTemplateType template) - { - Template = template; - } + Template = template; + } - public ToastTemplateType Template { get; private set; } + public ToastTemplateType Template { get; private set; } - /// - /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of - /// - /// "www.website.com/images/hello.png" - /// - /// included in the notification becomes - /// - /// "www.website.com/images/hello.png?ms-scale=100&ms-contrast=standard&ms-lang=en-us" - /// - public bool? AddImageQuery { get; set; } + /// + /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of + /// + /// "www.website.com/images/hello.png" + /// + /// included in the notification becomes + /// + /// "www.website.com/images/hello.png?ms-scale=100&ms-contrast=standard&ms-lang=en-us" + /// + public bool? AddImageQuery { get; set; } - /// - /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. - /// - public Uri BaseUri { get; set; } + /// + /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. + /// + public Uri BaseUri { get; set; } - /// - /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides that in visual, but can be overridden by that in text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. See Remarks for when this value isn't specified. - /// - public string Language { get; set; } + /// + /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides that in visual, but can be overridden by that in text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. See Remarks for when this value isn't specified. + /// + public string Language { get; set; } - public string ExperienceType { get; set; } + public string ExperienceType { get; set; } - public IList Children { get; private set; } = new List(); + public IList Children { get; private set; } = new List(); - /// - string IHaveXmlName.Name => "binding"; + /// + string IHaveXmlName.Name => "binding"; - /// - IEnumerable IHaveXmlChildren.Children => Children; + /// + IEnumerable IHaveXmlChildren.Children => Children; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("template", Template); - yield return new("addImageQuery", AddImageQuery); - yield return new("baseUri", BaseUri); - yield return new("lang", Language); - yield return new("experienceType", ExperienceType); - } - } - - internal interface IElement_ToastBindingChild + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() { + yield return new("template", Template); + yield return new("addImageQuery", AddImageQuery); + yield return new("baseUri", BaseUri); + yield return new("lang", Language); + yield return new("experienceType", ExperienceType); } +} - internal enum ToastTemplateType - { - ToastGeneric, - ToastImageAndText01, - ToastImageAndText02, - ToastImageAndText03, - ToastImageAndText04, - ToastText01, - ToastText02, - ToastText03, - ToastText04 - } +internal interface IElement_ToastBindingChild +{ +} + +internal enum ToastTemplateType +{ + ToastGeneric, + ToastImageAndText01, + ToastImageAndText02, + ToastImageAndText03, + ToastImageAndText04, + ToastText01, + ToastText02, + ToastText03, + ToastText04 } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Elements/Element_ToastHeader.cs b/components/Notifications/src/Toasts/Elements/Element_ToastHeader.cs index 7b1f5aec7..673848f69 100644 --- a/components/Notifications/src/Toasts/Elements/Element_ToastHeader.cs +++ b/components/Notifications/src/Toasts/Elements/Element_ToastHeader.cs @@ -5,57 +5,56 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_ToastHeader : IElement_ToastActivatable, IHaveXmlName, IHaveXmlNamedProperties { - internal sealed class Element_ToastHeader : IElement_ToastActivatable, IHaveXmlName, IHaveXmlNamedProperties - { - public string Id { get; set; } + public string Id { get; set; } - public string Title { get; set; } + public string Title { get; set; } - public string Arguments { get; set; } + public string Arguments { get; set; } - public Element_ToastActivationType ActivationType { get; set; } = Element_ToastActivationType.Foreground; + public Element_ToastActivationType ActivationType { get; set; } = Element_ToastActivationType.Foreground; - public string ProtocolActivationTargetApplicationPfn { get; set; } + public string ProtocolActivationTargetApplicationPfn { get; set; } - public ToastAfterActivationBehavior AfterActivationBehavior + public ToastAfterActivationBehavior AfterActivationBehavior + { + get { - get - { - return ToastAfterActivationBehavior.Default; - } + return ToastAfterActivationBehavior.Default; + } - set + set + { + if (value != ToastAfterActivationBehavior.Default) { - if (value != ToastAfterActivationBehavior.Default) - { - throw new InvalidOperationException("AfterActivationBehavior on ToastHeader only supports the Default value."); - } + throw new InvalidOperationException("AfterActivationBehavior on ToastHeader only supports the Default value."); } } + } - /// - string IHaveXmlName.Name => "header"; + /// + string IHaveXmlName.Name => "header"; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("id", Id); - yield return new("title", Title); - yield return new("arguments", Arguments); + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("id", Id); + yield return new("title", Title); + yield return new("arguments", Arguments); - if (ActivationType != Element_ToastActivationType.Foreground) - { - yield return new("activationType", ActivationType.ToPascalCaseString()); - } + if (ActivationType != Element_ToastActivationType.Foreground) + { + yield return new("activationType", ActivationType.ToPascalCaseString()); + } - yield return new("protocolActivationTargetApplicationPfn", ProtocolActivationTargetApplicationPfn); + yield return new("protocolActivationTargetApplicationPfn", ProtocolActivationTargetApplicationPfn); - if (AfterActivationBehavior != ToastAfterActivationBehavior.Default) - { - yield return new("afterActivationBehavior", AfterActivationBehavior.ToPascalCaseString()); - } + if (AfterActivationBehavior != ToastAfterActivationBehavior.Default) + { + yield return new("afterActivationBehavior", AfterActivationBehavior.ToPascalCaseString()); } } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Elements/Element_ToastImage.cs b/components/Notifications/src/Toasts/Elements/Element_ToastImage.cs index e3473a278..4043a654f 100644 --- a/components/Notifications/src/Toasts/Elements/Element_ToastImage.cs +++ b/components/Notifications/src/Toasts/Elements/Element_ToastImage.cs @@ -4,70 +4,69 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_ToastImage : IElement_ToastBindingChild, IHaveXmlName, IHaveXmlNamedProperties { - internal sealed class Element_ToastImage : IElement_ToastBindingChild, IHaveXmlName, IHaveXmlNamedProperties - { - internal const ToastImagePlacement DEFAULT_PLACEMENT = ToastImagePlacement.Inline; - internal const bool DEFAULT_ADD_IMAGE_QUERY = false; - internal const ToastImageCrop DEFAULT_CROP = ToastImageCrop.None; + internal const ToastImagePlacement DEFAULT_PLACEMENT = ToastImagePlacement.Inline; + internal const bool DEFAULT_ADD_IMAGE_QUERY = false; + internal const ToastImageCrop DEFAULT_CROP = ToastImageCrop.None; + + public string Src { get; set; } + + public string Alt { get; set; } + + public bool AddImageQuery { get; set; } = DEFAULT_ADD_IMAGE_QUERY; - public string Src { get; set; } + public ToastImagePlacement Placement { get; set; } = DEFAULT_PLACEMENT; - public string Alt { get; set; } + public ToastImageCrop Crop { get; set; } = DEFAULT_CROP; - public bool AddImageQuery { get; set; } = DEFAULT_ADD_IMAGE_QUERY; + /// + string IHaveXmlName.Name => "image"; - public ToastImagePlacement Placement { get; set; } = DEFAULT_PLACEMENT; + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("src", Src); + yield return new("alt", Alt); - public ToastImageCrop Crop { get; set; } = DEFAULT_CROP; + if (AddImageQuery != DEFAULT_ADD_IMAGE_QUERY) + { + yield return new("addImageQuery", AddImageQuery); + } - /// - string IHaveXmlName.Name => "image"; + if (Placement != DEFAULT_PLACEMENT) + { + yield return new("placement", Placement.ToPascalCaseString()); + } - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + if (Crop != DEFAULT_CROP) { - yield return new("src", Src); - yield return new("alt", Alt); - - if (AddImageQuery != DEFAULT_ADD_IMAGE_QUERY) - { - yield return new("addImageQuery", AddImageQuery); - } - - if (Placement != DEFAULT_PLACEMENT) - { - yield return new("placement", Placement.ToPascalCaseString()); - } - - if (Crop != DEFAULT_CROP) - { - yield return new("crop", Crop.ToPascalCaseString()); - } + yield return new("crop", Crop.ToPascalCaseString()); } } +} +/// +/// Specify the desired cropping of the image. +/// +public enum ToastImageCrop +{ /// - /// Specify the desired cropping of the image. + /// Default value. Image is not cropped. /// - public enum ToastImageCrop - { - /// - /// Default value. Image is not cropped. - /// - None, - - /// - /// Image is cropped to a circle shape. - /// - Circle - } + None, - internal enum ToastImagePlacement - { - Inline, - AppLogoOverride, - Hero - } + /// + /// Image is cropped to a circle shape. + /// + Circle +} + +internal enum ToastImagePlacement +{ + Inline, + AppLogoOverride, + Hero } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Elements/Element_ToastInput.cs b/components/Notifications/src/Toasts/Elements/Element_ToastInput.cs index 0e8cd882b..927098191 100644 --- a/components/Notifications/src/Toasts/Elements/Element_ToastInput.cs +++ b/components/Notifications/src/Toasts/Elements/Element_ToastInput.cs @@ -4,58 +4,57 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_ToastInput : IElement_ToastActionsChild, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren { - internal sealed class Element_ToastInput : IElement_ToastActionsChild, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren - { - /// - /// Gets or sets the required attributes for developers to retrieve user inputs once the app is activated (in the foreground or background). - /// - public string Id { get; set; } - - public ToastInputType Type { get; set; } - - /// - /// Gets or sets the optional title attribute and is for developers to specify a title for the input for shells to render when there is affordance. - /// - public string Title { get; set; } - - /// - /// Gets or sets the optional placeholderContent attribute and is the grey-out hint text for text input type. This attribute is ignored when the input type is not �text�. - /// - public string PlaceholderContent { get; set; } - - /// - /// Gets or sets the optional defaultInput attribute and it allows developer to provide a default input value. - /// - public string DefaultInput { get; set; } - - public IList Children { get; private set; } = new List(); - - /// - string IHaveXmlName.Name => "input"; - - /// - IEnumerable IHaveXmlChildren.Children => Children; - - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("id", Id); - yield return new("type", Type.ToPascalCaseString()); - yield return new("title", Title); - yield return new("placeHolderContent", PlaceholderContent); - yield return new("defaultInput", DefaultInput); - } - } + /// + /// Gets or sets the required attributes for developers to retrieve user inputs once the app is activated (in the foreground or background). + /// + public string Id { get; set; } - internal interface IElement_ToastInputChild - { - } + public ToastInputType Type { get; set; } + + /// + /// Gets or sets the optional title attribute and is for developers to specify a title for the input for shells to render when there is affordance. + /// + public string Title { get; set; } + + /// + /// Gets or sets the optional placeholderContent attribute and is the grey-out hint text for text input type. This attribute is ignored when the input type is not �text�. + /// + public string PlaceholderContent { get; set; } + + /// + /// Gets or sets the optional defaultInput attribute and it allows developer to provide a default input value. + /// + public string DefaultInput { get; set; } - internal enum ToastInputType + public IList Children { get; private set; } = new List(); + + /// + string IHaveXmlName.Name => "input"; + + /// + IEnumerable IHaveXmlChildren.Children => Children; + + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() { - Text, - Selection + yield return new("id", Id); + yield return new("type", Type.ToPascalCaseString()); + yield return new("title", Title); + yield return new("placeHolderContent", PlaceholderContent); + yield return new("defaultInput", DefaultInput); } +} + +internal interface IElement_ToastInputChild +{ +} + +internal enum ToastInputType +{ + Text, + Selection } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Elements/Element_ToastSelection.cs b/components/Notifications/src/Toasts/Elements/Element_ToastSelection.cs index 4092ad554..b42ff9777 100644 --- a/components/Notifications/src/Toasts/Elements/Element_ToastSelection.cs +++ b/components/Notifications/src/Toasts/Elements/Element_ToastSelection.cs @@ -4,28 +4,27 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_ToastSelection : IElement_ToastInputChild, IHaveXmlName, IHaveXmlNamedProperties { - internal sealed class Element_ToastSelection : IElement_ToastInputChild, IHaveXmlName, IHaveXmlNamedProperties - { - /// - /// Gets or sets the id attribute for apps to retrieve back the user selected input after the app is activated. Required - /// - public string Id { get; set; } + /// + /// Gets or sets the id attribute for apps to retrieve back the user selected input after the app is activated. Required + /// + public string Id { get; set; } - /// - /// Gets or sets the text to display for this selection element. - /// - public string Content { get; set; } + /// + /// Gets or sets the text to display for this selection element. + /// + public string Content { get; set; } - /// - string IHaveXmlName.Name => "selection"; + /// + string IHaveXmlName.Name => "selection"; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("id", Id); - yield return new("content", Content); - } + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("id", Id); + yield return new("content", Content); } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Elements/Element_ToastText.cs b/components/Notifications/src/Toasts/Elements/Element_ToastText.cs index f9b9947aa..a30b48e1e 100644 --- a/components/Notifications/src/Toasts/Elements/Element_ToastText.cs +++ b/components/Notifications/src/Toasts/Elements/Element_ToastText.cs @@ -4,36 +4,35 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_ToastText : IElement_ToastBindingChild, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlText { - internal sealed class Element_ToastText : IElement_ToastBindingChild, IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlText - { - internal const ToastTextPlacement DEFAULT_PLACEMENT = ToastTextPlacement.Inline; + internal const ToastTextPlacement DEFAULT_PLACEMENT = ToastTextPlacement.Inline; - public string Text { get; set; } + public string Text { get; set; } - public string Lang { get; set; } + public string Lang { get; set; } - public ToastTextPlacement Placement { get; set; } = DEFAULT_PLACEMENT; + public ToastTextPlacement Placement { get; set; } = DEFAULT_PLACEMENT; - /// - string IHaveXmlName.Name => "text"; + /// + string IHaveXmlName.Name => "text"; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("lang", Lang); + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("lang", Lang); - if (Placement != DEFAULT_PLACEMENT) - { - yield return new("placement", Placement.ToPascalCaseString()); - } + if (Placement != DEFAULT_PLACEMENT) + { + yield return new("placement", Placement.ToPascalCaseString()); } } +} - internal enum ToastTextPlacement - { - Inline, - Attribution - } +internal enum ToastTextPlacement +{ + Inline, + Attribution } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Elements/Element_ToastVisual.cs b/components/Notifications/src/Toasts/Elements/Element_ToastVisual.cs index 0baf45b1a..a199e9fb4 100644 --- a/components/Notifications/src/Toasts/Elements/Element_ToastVisual.cs +++ b/components/Notifications/src/Toasts/Elements/Element_ToastVisual.cs @@ -5,35 +5,34 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal sealed class Element_ToastVisual : IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren { - internal sealed class Element_ToastVisual : IHaveXmlName, IHaveXmlNamedProperties, IHaveXmlChildren - { - internal const bool DEFAULT_ADD_IMAGE_QUERY = false; + internal const bool DEFAULT_ADD_IMAGE_QUERY = false; - public bool? AddImageQuery { get; set; } + public bool? AddImageQuery { get; set; } - public Uri BaseUri { get; set; } + public Uri BaseUri { get; set; } - public string Language { get; set; } + public string Language { get; set; } - public int? Version { get; set; } + public int? Version { get; set; } - public IList Bindings { get; private set; } = new List(); + public IList Bindings { get; private set; } = new List(); - /// - string IHaveXmlName.Name => "visual"; + /// + string IHaveXmlName.Name => "visual"; - /// - IEnumerable IHaveXmlChildren.Children => Bindings; + /// + IEnumerable IHaveXmlChildren.Children => Bindings; - /// - IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() - { - yield return new("addImageQuery", AddImageQuery); - yield return new("baseUri", BaseUri); - yield return new("lang", Language); - yield return new("version", Version); - } + /// + IEnumerable> IHaveXmlNamedProperties.EnumerateNamedProperties() + { + yield return new("addImageQuery", AddImageQuery); + yield return new("baseUri", BaseUri); + yield return new("lang", Language); + yield return new("version", Version); } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/Elements/IElement_ToastActivatable.cs b/components/Notifications/src/Toasts/Elements/IElement_ToastActivatable.cs index bc4a7d293..3a5ed0de6 100644 --- a/components/Notifications/src/Toasts/Elements/IElement_ToastActivatable.cs +++ b/components/Notifications/src/Toasts/Elements/IElement_ToastActivatable.cs @@ -2,14 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +internal interface IElement_ToastActivatable { - internal interface IElement_ToastActivatable - { - Element_ToastActivationType ActivationType { get; set; } + Element_ToastActivationType ActivationType { get; set; } - string ProtocolActivationTargetApplicationPfn { get; set; } + string ProtocolActivationTargetApplicationPfn { get; set; } - ToastAfterActivationBehavior AfterActivationBehavior { get; set; } - } + ToastAfterActivationBehavior AfterActivationBehavior { get; set; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/IToastActions.cs b/components/Notifications/src/Toasts/IToastActions.cs index 4b7627307..a4520592d 100644 --- a/components/Notifications/src/Toasts/IToastActions.cs +++ b/components/Notifications/src/Toasts/IToastActions.cs @@ -4,16 +4,15 @@ using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Actions to display on a Toast notification. One of or . +/// +public interface IToastActions { /// - /// Actions to display on a Toast notification. One of or . + /// Gets custom context menu items, providing additional actions when the user right clicks the Toast notification. New in Anniversary Update /// - public interface IToastActions - { - /// - /// Gets custom context menu items, providing additional actions when the user right clicks the Toast notification. New in Anniversary Update - /// - IList ContextMenuItems { get; } - } -} \ No newline at end of file + IList ContextMenuItems { get; } +} diff --git a/components/Notifications/src/Toasts/IToastActivateableBuilder.cs b/components/Notifications/src/Toasts/IToastActivateableBuilder.cs index 319575498..68d162498 100644 --- a/components/Notifications/src/Toasts/IToastActivateableBuilder.cs +++ b/components/Notifications/src/Toasts/IToastActivateableBuilder.cs @@ -4,88 +4,87 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Interfaces for classes that can have activation info added to them. +/// +/// The type of the host object. +internal interface IToastActivateableBuilder { /// - /// Interfaces for classes that can have activation info added to them. + /// Adds a key (without value) to the activation arguments that will be returned when the content is clicked. /// - /// The type of the host object. - internal interface IToastActivateableBuilder - { - /// - /// Adds a key (without value) to the activation arguments that will be returned when the content is clicked. - /// - /// The key. - /// The current instance of the object. - T AddArgument(string key); + /// The key. + /// The current instance of the object. + T AddArgument(string key); - /// - /// Adds a key/value to the activation arguments that will be returned when the content is clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of the object. - T AddArgument(string key, string value); + /// + /// Adds a key/value to the activation arguments that will be returned when the content is clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of the object. + T AddArgument(string key, string value); - /// - /// Adds a key/value to the activation arguments that will be returned when the content is clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of the object. - T AddArgument(string key, int value); + /// + /// Adds a key/value to the activation arguments that will be returned when the content is clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of the object. + T AddArgument(string key, int value); - /// - /// Adds a key/value to the activation arguments that will be returned when the content is clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of the object. - T AddArgument(string key, double value); + /// + /// Adds a key/value to the activation arguments that will be returned when the content is clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of the object. + T AddArgument(string key, double value); - /// - /// Adds a key/value to the activation arguments that will be returned when the content is clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of the object. - T AddArgument(string key, float value); + /// + /// Adds a key/value to the activation arguments that will be returned when the content is clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of the object. + T AddArgument(string key, float value); - /// - /// Adds a key/value to the activation arguments that will be returned when the content is clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of the object. - T AddArgument(string key, bool value); + /// + /// Adds a key/value to the activation arguments that will be returned when the content is clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of the object. + T AddArgument(string key, bool value); - /// - /// Adds a key/value to the activation arguments that will be returned when the content is clicked. - /// - /// The key for this 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. - /// The current instance of the object. - T AddArgument(string key, Enum value); + /// + /// Adds a key/value to the activation arguments that will be returned when the content is clicked. + /// + /// The key for this 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. + /// The current instance of the object. + T AddArgument(string key, Enum value); - /// - /// Configures the content to use background activation when it is clicked. - /// - /// The current instance of the object. - T SetBackgroundActivation(); + /// + /// Configures the content to use background activation when it is clicked. + /// + /// The current instance of the object. + T SetBackgroundActivation(); - /// - /// Configures the content to use protocol activation when it is clicked. - /// - /// The protocol to launch. - /// The current instance of the object. - T SetProtocolActivation(Uri protocol); + /// + /// Configures the content to use protocol activation when it is clicked. + /// + /// The protocol to launch. + /// The current instance of the object. + T SetProtocolActivation(Uri protocol); - /// - /// Configures the content to use protocol activation when it is clicked. - /// - /// The protocol to launch. - /// New in Creators Update: The target PFN, so that regardless of whether multiple apps are registered to handle the same protocol uri, your desired app will always be launched. - /// The current instance of the object. - T SetProtocolActivation(Uri protocol, string targetApplicationPfn); - } + /// + /// Configures the content to use protocol activation when it is clicked. + /// + /// The protocol to launch. + /// New in Creators Update: The target PFN, so that regardless of whether multiple apps are registered to handle the same protocol uri, your desired app will always be launched. + /// The current instance of the object. + T SetProtocolActivation(Uri protocol, string targetApplicationPfn); } diff --git a/components/Notifications/src/Toasts/IToastBindingGenericChild.cs b/components/Notifications/src/Toasts/IToastBindingGenericChild.cs index 444cefbe6..43c783158 100644 --- a/components/Notifications/src/Toasts/IToastBindingGenericChild.cs +++ b/components/Notifications/src/Toasts/IToastBindingGenericChild.cs @@ -2,13 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Elements that can be direct children of , including (, , and ). +/// +public interface IToastBindingGenericChild { - /// - /// Elements that can be direct children of , including (, , and ). - /// - public interface IToastBindingGenericChild - { - // Blank interface simply for compile-enforcing the child types in the list. - } + // Blank interface simply for compile-enforcing the child types in the list. } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/IToastButton.cs b/components/Notifications/src/Toasts/IToastButton.cs index 0f52fee31..58159c250 100644 --- a/components/Notifications/src/Toasts/IToastButton.cs +++ b/components/Notifications/src/Toasts/IToastButton.cs @@ -2,23 +2,22 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// One of , , or . +/// +public interface IToastButton { /// - /// One of , , or . + /// Gets or sets an optional image icon for the button to display (required for buttons adjacent to inputs like quick reply). /// - public interface IToastButton - { - /// - /// Gets or sets an optional image icon for the button to display (required for buttons adjacent to inputs like quick reply). - /// - string ImageUri { get; set; } + string ImageUri { get; set; } - /// - /// Gets or sets an identifier used in telemetry to identify your category of action. This should be something - /// like "Delete", "Reply", or "Archive". In the upcoming toast telemetry dashboard in Dev Center, you will - /// be able to view how frequently your actions are being clicked. - /// - string HintActionId { get; set; } - } + /// + /// Gets or sets an identifier used in telemetry to identify your category of action. This should be something + /// like "Delete", "Reply", or "Archive". In the upcoming toast telemetry dashboard in Dev Center, you will + /// be able to view how frequently your actions are being clicked. + /// + string HintActionId { get; set; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/IToastInput.cs b/components/Notifications/src/Toasts/IToastInput.cs index 7b13e568d..954f89d11 100644 --- a/components/Notifications/src/Toasts/IToastInput.cs +++ b/components/Notifications/src/Toasts/IToastInput.cs @@ -2,12 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// An input element on a Toast notification. One of or . +/// +public interface IToastInput { - /// - /// An input element on a Toast notification. One of or . - /// - public interface IToastInput - { - } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastActionsCustom.cs b/components/Notifications/src/Toasts/ToastActionsCustom.cs index a40f8d702..65ebbb1b5 100644 --- a/components/Notifications/src/Toasts/ToastActionsCustom.cs +++ b/components/Notifications/src/Toasts/ToastActionsCustom.cs @@ -5,90 +5,89 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Create your own custom actions, using controls like , , and . +/// +public sealed class ToastActionsCustom : IToastActions { /// - /// Create your own custom actions, using controls like , , and . + /// Gets inputs like and . Only up to 5 inputs can be added; after that, an exception is thrown. + /// + public IList Inputs { get; private set; } = new LimitedList(5); + + /// + /// Gets buttons displayed after all the inputs (or adjacent to inputs if used as quick reply buttons). Only up to 5 buttons can be added (or fewer if you are also including context menu items). After that, an exception is thrown. You can add , , or + /// + public IList Buttons { get; private set; } = new LimitedList(5); + + /// + /// Gets custom context menu items, providing additional actions when the user right clicks the Toast notification. + /// You can only have up to 5 buttons and context menu items *combined*. Thus, if you have one context menu item, + /// you can only have four buttons, etc. New in Anniversary Update: /// - public sealed class ToastActionsCustom : IToastActions + public IList ContextMenuItems { get; private set; } = new List(); + + internal Element_ToastActions ConvertToElement() { - /// - /// Gets inputs like and . Only up to 5 inputs can be added; after that, an exception is thrown. - /// - public IList Inputs { get; private set; } = new LimitedList(5); - - /// - /// Gets buttons displayed after all the inputs (or adjacent to inputs if used as quick reply buttons). Only up to 5 buttons can be added (or fewer if you are also including context menu items). After that, an exception is thrown. You can add , , or - /// - public IList Buttons { get; private set; } = new LimitedList(5); - - /// - /// Gets custom context menu items, providing additional actions when the user right clicks the Toast notification. - /// You can only have up to 5 buttons and context menu items *combined*. Thus, if you have one context menu item, - /// you can only have four buttons, etc. New in Anniversary Update: - /// - public IList ContextMenuItems { get; private set; } = new List(); - - internal Element_ToastActions ConvertToElement() + if (Buttons.Count + ContextMenuItems.Count > 5) { - if (Buttons.Count + ContextMenuItems.Count > 5) - { - throw new InvalidOperationException("You have too many buttons/context menu items. You can only have up to 5 total."); - } + throw new InvalidOperationException("You have too many buttons/context menu items. You can only have up to 5 total."); + } - var el = new Element_ToastActions(); + var el = new Element_ToastActions(); - foreach (var input in Inputs) - { - el.Children.Add(ConvertToInputElement(input)); - } + foreach (var input in Inputs) + { + el.Children.Add(ConvertToInputElement(input)); + } - foreach (var button in this.Buttons) - { - el.Children.Add(ConvertToActionElement(button)); - } + foreach (var button in this.Buttons) + { + el.Children.Add(ConvertToActionElement(button)); + } - foreach (var item in ContextMenuItems) - { - el.Children.Add(item.ConvertToElement()); - } + foreach (var item in ContextMenuItems) + { + el.Children.Add(item.ConvertToElement()); + } + + return el; + } - return el; + private static Element_ToastAction ConvertToActionElement(IToastButton button) + { + if (button is ToastButton) + { + return (button as ToastButton).ConvertToElement(); } - private static Element_ToastAction ConvertToActionElement(IToastButton button) + if (button is ToastButtonDismiss) { - if (button is ToastButton) - { - return (button as ToastButton).ConvertToElement(); - } - - if (button is ToastButtonDismiss) - { - return (button as ToastButtonDismiss).ConvertToElement(); - } - - if (button is ToastButtonSnooze) - { - return (button as ToastButtonSnooze).ConvertToElement(); - } - - throw new NotImplementedException("Unknown button child: " + button.GetType()); + return (button as ToastButtonDismiss).ConvertToElement(); } - private static Element_ToastInput ConvertToInputElement(IToastInput input) + if (button is ToastButtonSnooze) { - if (input is ToastTextBox) - { - return (input as ToastTextBox).ConvertToElement(); - } + return (button as ToastButtonSnooze).ConvertToElement(); + } - if (input is ToastSelectionBox) - { - return (input as ToastSelectionBox).ConvertToElement(); - } + throw new NotImplementedException("Unknown button child: " + button.GetType()); + } - throw new NotImplementedException("Unknown input child: " + input.GetType()); + private static Element_ToastInput ConvertToInputElement(IToastInput input) + { + if (input is ToastTextBox) + { + return (input as ToastTextBox).ConvertToElement(); + } + + if (input is ToastSelectionBox) + { + return (input as ToastSelectionBox).ConvertToElement(); } + + throw new NotImplementedException("Unknown input child: " + input.GetType()); } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastActionsSnoozeAndDismiss.cs b/components/Notifications/src/Toasts/ToastActionsSnoozeAndDismiss.cs index 13d5a76ff..3e61b53a6 100644 --- a/components/Notifications/src/Toasts/ToastActionsSnoozeAndDismiss.cs +++ b/components/Notifications/src/Toasts/ToastActionsSnoozeAndDismiss.cs @@ -5,37 +5,36 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Automatically constructs a selection box for snooze intervals, and snooze/dismiss buttons, all automatically localized, and snoozing logic is automatically handled by the system. +/// +public sealed class ToastActionsSnoozeAndDismiss : IToastActions { /// - /// Automatically constructs a selection box for snooze intervals, and snooze/dismiss buttons, all automatically localized, and snoozing logic is automatically handled by the system. + /// Gets custom context menu items, providing additional actions when the user right clicks the Toast notification. + /// You can only have up to 5 items. New in Anniversary Update /// - public sealed class ToastActionsSnoozeAndDismiss : IToastActions - { - /// - /// Gets custom context menu items, providing additional actions when the user right clicks the Toast notification. - /// You can only have up to 5 items. New in Anniversary Update - /// - public IList ContextMenuItems { get; private set; } = new List(); + public IList ContextMenuItems { get; private set; } = new List(); - internal Element_ToastActions ConvertToElement() + internal Element_ToastActions ConvertToElement() + { + if (ContextMenuItems.Count > 5) { - if (ContextMenuItems.Count > 5) - { - throw new InvalidOperationException("You have too many context menu items. You can only have up to 5."); - } - - var el = new Element_ToastActions() - { - SystemCommands = ToastSystemCommand.SnoozeAndDismiss - }; + throw new InvalidOperationException("You have too many context menu items. You can only have up to 5."); + } - foreach (var item in ContextMenuItems) - { - el.Children.Add(item.ConvertToElement()); - } + var el = new Element_ToastActions() + { + SystemCommands = ToastSystemCommand.SnoozeAndDismiss + }; - return el; + foreach (var item in ContextMenuItems) + { + el.Children.Add(item.ConvertToElement()); } + + return el; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastActivationOptions.cs b/components/Notifications/src/Toasts/ToastActivationOptions.cs index 81609903a..aa0d25d01 100644 --- a/components/Notifications/src/Toasts/ToastActivationOptions.cs +++ b/components/Notifications/src/Toasts/ToastActivationOptions.cs @@ -4,35 +4,34 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// New in Creators Update: Additional options relating to activation. +/// +public sealed class ToastActivationOptions { /// - /// New in Creators Update: Additional options relating to activation. + /// Gets or sets the target PFN if you are using . You can optionally specify, so that regardless of whether multiple apps are registered to handle the same protocol uri, your desired app will always be launched. /// - public sealed class ToastActivationOptions - { - /// - /// Gets or sets the target PFN if you are using . You can optionally specify, so that regardless of whether multiple apps are registered to handle the same protocol uri, your desired app will always be launched. - /// - public string ProtocolActivationTargetApplicationPfn { get; set; } + public string ProtocolActivationTargetApplicationPfn { get; set; } - /// - /// Gets or sets the behavior that the toast should use when the user invokes this action. - /// Note that this option only works on and . - /// Desktop-only, supported in builds 16251 or higher. New in Fall Creators Update - /// - public ToastAfterActivationBehavior AfterActivationBehavior { get; set; } = ToastAfterActivationBehavior.Default; + /// + /// Gets or sets the behavior that the toast should use when the user invokes this action. + /// Note that this option only works on and . + /// Desktop-only, supported in builds 16251 or higher. New in Fall Creators Update + /// + public ToastAfterActivationBehavior AfterActivationBehavior { get; set; } = ToastAfterActivationBehavior.Default; - internal void PopulateElement(IElement_ToastActivatable el) + internal void PopulateElement(IElement_ToastActivatable el) + { + // If protocol PFN is specified but protocol activation isn't used, throw exception + if (ProtocolActivationTargetApplicationPfn != null && el.ActivationType != Element_ToastActivationType.Protocol) { - // If protocol PFN is specified but protocol activation isn't used, throw exception - if (ProtocolActivationTargetApplicationPfn != null && el.ActivationType != Element_ToastActivationType.Protocol) - { - throw new InvalidOperationException($"You cannot specify {nameof(ProtocolActivationTargetApplicationPfn)} without using ActivationType of Protocol."); - } - - el.ProtocolActivationTargetApplicationPfn = ProtocolActivationTargetApplicationPfn; - el.AfterActivationBehavior = AfterActivationBehavior; + throw new InvalidOperationException($"You cannot specify {nameof(ProtocolActivationTargetApplicationPfn)} without using ActivationType of Protocol."); } + + el.ProtocolActivationTargetApplicationPfn = ProtocolActivationTargetApplicationPfn; + el.AfterActivationBehavior = AfterActivationBehavior; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastArguments.cs b/components/Notifications/src/Toasts/ToastArguments.cs index c7d756a5c..7b294ca6d 100644 --- a/components/Notifications/src/Toasts/ToastArguments.cs +++ b/components/Notifications/src/Toasts/ToastArguments.cs @@ -7,423 +7,422 @@ using System.Collections.Generic; using System.Linq; -namespace CommunityToolkit.Notifications -{ - /// - /// A class that supports serializing simple key/value pairs into a format that's friendly for being used within toast notifications. The serialized format is similar to a query string, however optimized for being placed within an XML property (uses semicolons instead of ampersands since those don't need to be XML-escaped, doesn't url-encode all special characters since not being used within a URL, etc). - /// - public sealed partial class ToastArguments : IEnumerable> - { - private Dictionary _dictionary = new Dictionary(); +namespace CommunityToolkit.Notifications; - internal ToastArguments Clone() - { - return new ToastArguments() - { - _dictionary = new Dictionary(_dictionary) - }; - } +/// +/// A class that supports serializing simple key/value pairs into a format that's friendly for being used within toast notifications. The serialized format is similar to a query string, however optimized for being placed within an XML property (uses semicolons instead of ampersands since those don't need to be XML-escaped, doesn't url-encode all special characters since not being used within a URL, etc). +/// +public sealed partial class ToastArguments : IEnumerable> +{ + private Dictionary _dictionary = new Dictionary(); - /// - /// Gets the value of the specified key. Throws if the key could not be found. - /// - /// The key to find. - /// The value of the specified key. - public string this[string key] + internal ToastArguments Clone() + { + return new ToastArguments() { - get - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - if (TryGetValue(key, out string value)) - { - return value; - } - - throw new KeyNotFoundException($"A key with name '{key}' could not be found."); - } - - set - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - _dictionary[key] = value; - } - } + _dictionary = new Dictionary(_dictionary) + }; + } - /// - /// Attempts to get the value of the specified key. If no key exists, returns false. - /// - /// The key to find. - /// The key's value will be written here if found. - /// True if found the key and set the value, otherwise false. - public bool TryGetValue(string key, out string value) + /// + /// Gets the value of the specified key. Throws if the key could not be found. + /// + /// The key to find. + /// The value of the specified key. + public string this[string key] + { + get { if (key == null) { throw new ArgumentNullException(nameof(key)); } - return _dictionary.TryGetValue(key, out value); - } - - /// - /// Attempts to get the value of the specified key. If no key exists, returns false. - /// - /// The enum to parse. - /// The key to find. - /// The key's value will be written here if found. - /// True if found the key and set the value, otherwise false. - public bool TryGetValue(string key, out T value) - where T : struct, Enum - { - if (TryGetValue(key, out string strValue)) + if (TryGetValue(key, out string value)) { - return Enum.TryParse(strValue, out value); + return value; } - value = default(T); - return false; + throw new KeyNotFoundException($"A key with name '{key}' could not be found."); } - /// - /// Gets the value of the specified key, or throws if key didn't exist. - /// - /// The key to get. - /// The value of the key. - public string Get(string key) + set { if (key == null) { throw new ArgumentNullException(nameof(key)); } - if (_dictionary.TryGetValue(key, out string value)) - { - return value; - } - - throw new KeyNotFoundException(); + _dictionary[key] = value; } + } - /// - /// Gets the value of the specified key, or throws if key didn't exist. - /// - /// The key to get. - /// The value of the key. - public int GetInt(string key) + /// + /// Attempts to get the value of the specified key. If no key exists, returns false. + /// + /// The key to find. + /// The key's value will be written here if found. + /// True if found the key and set the value, otherwise false. + public bool TryGetValue(string key, out string value) + { + if (key == null) { - return int.Parse(Get(key)); + throw new ArgumentNullException(nameof(key)); } - /// - /// Gets the value of the specified key, or throws if key didn't exist. - /// - /// The key to get. - /// The value of the key. - public double GetDouble(string key) - { - return double.Parse(Get(key)); - } + return _dictionary.TryGetValue(key, out value); + } - /// - /// Gets the value of the specified key, or throws if key didn't exist. - /// - /// The key to get. - /// The value of the key. - public float GetFloat(string key) + /// + /// Attempts to get the value of the specified key. If no key exists, returns false. + /// + /// The enum to parse. + /// The key to find. + /// The key's value will be written here if found. + /// True if found the key and set the value, otherwise false. + public bool TryGetValue(string key, out T value) + where T : struct, Enum + { + if (TryGetValue(key, out string strValue)) { - return float.Parse(Get(key)); + return Enum.TryParse(strValue, out value); } - /// - /// Gets the value of the specified key, or throws if key didn't exist. - /// - /// The key to get. - /// The value of the key. - public byte GetByte(string key) - { - return byte.Parse(Get(key)); - } + value = default(T); + return false; + } - /// - /// Gets the value of the specified key, or throws if key didn't exist. - /// - /// The key to get. - /// The value of the key. - public bool GetBool(string key) + /// + /// Gets the value of the specified key, or throws if key didn't exist. + /// + /// The key to get. + /// The value of the key. + public string Get(string key) + { + if (key == null) { - return Get(key) == "1" ? true : false; + throw new ArgumentNullException(nameof(key)); } - /// - /// Gets the value of the specified key, or throws if key didn't exist. - /// - /// The enum to parse. - /// The key to get. - /// The value of the key. - public T GetEnum(string key) - where T : struct, Enum + if (_dictionary.TryGetValue(key, out string value)) { - if (TryGetValue(key, out T value)) - { - return value; - } - - throw new KeyNotFoundException(); + return value; } - /// - /// Gets the number of key/value pairs contained in the toast arguments. - /// - public int Count => _dictionary.Count; - - /// - /// Adds a key. If there is an existing key, it is replaced. - /// - /// The key. - /// The current object. - public ToastArguments Add(string key) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } + throw new KeyNotFoundException(); + } - _dictionary[key] = null; + /// + /// Gets the value of the specified key, or throws if key didn't exist. + /// + /// The key to get. + /// The value of the key. + public int GetInt(string key) + { + return int.Parse(Get(key)); + } - return this; - } + /// + /// Gets the value of the specified key, or throws if key didn't exist. + /// + /// The key to get. + /// The value of the key. + public double GetDouble(string key) + { + return double.Parse(Get(key)); + } - /// - /// Adds a key and optional value. If there is an existing key, it is replaced. - /// - /// The key. - /// The optional value of the key. - /// The current object. - public ToastArguments Add(string key, string value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } + /// + /// Gets the value of the specified key, or throws if key didn't exist. + /// + /// The key to get. + /// The value of the key. + public float GetFloat(string key) + { + return float.Parse(Get(key)); + } - _dictionary[key] = value; + /// + /// Gets the value of the specified key, or throws if key didn't exist. + /// + /// The key to get. + /// The value of the key. + public byte GetByte(string key) + { + return byte.Parse(Get(key)); + } - return this; - } + /// + /// Gets the value of the specified key, or throws if key didn't exist. + /// + /// The key to get. + /// The value of the key. + public bool GetBool(string key) + { + return Get(key) == "1" ? true : false; + } - /// - /// Adds a key and value. If there is an existing key, it is replaced. - /// - /// The key. - /// The value of the key. - /// The current object. - public ToastArguments Add(string key, int value) + /// + /// Gets the value of the specified key, or throws if key didn't exist. + /// + /// The enum to parse. + /// The key to get. + /// The value of the key. + public T GetEnum(string key) + where T : struct, Enum + { + if (TryGetValue(key, out T value)) { - return AddHelper(key, value); + return value; } - /// - /// Adds a key and value. If there is an existing key, it is replaced. - /// - /// The key. - /// The value of the key. - /// The current object. - public ToastArguments Add(string key, double value) - { - return AddHelper(key, value); - } + throw new KeyNotFoundException(); + } - /// - /// Adds a key and value. If there is an existing key, it is replaced. - /// - /// The key. - /// The value of the key. - /// The current object. - public ToastArguments Add(string key, float value) - { - return AddHelper(key, value); - } + /// + /// Gets the number of key/value pairs contained in the toast arguments. + /// + public int Count => _dictionary.Count; - /// - /// Adds a key and value. If there is an existing key, it is replaced. - /// - /// The key. - /// The value of the key. - /// The current object. - public ToastArguments Add(string key, bool value) + /// + /// Adds a key. If there is an existing key, it is replaced. + /// + /// The key. + /// The current object. + public ToastArguments Add(string key) + { + if (key == null) { - return Add(key, value ? "1" : "0"); // Encode as 1 or 0 to save string space + throw new ArgumentNullException(nameof(key)); } - /// - /// Adds a key and value. If there is an existing key, it is replaced. - /// - /// The key. - /// The value of the key. 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. - /// The current object. - public ToastArguments Add(string key, Enum value) + _dictionary[key] = null; + + return this; + } + + /// + /// Adds a key and optional value. If there is an existing key, it is replaced. + /// + /// The key. + /// The optional value of the key. + /// The current object. + public ToastArguments Add(string key, string value) + { + if (key == null) { - return Add(key, (int)(object)value); + throw new ArgumentNullException(nameof(key)); } - private ToastArguments AddHelper(string key, object value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } + _dictionary[key] = value; - _dictionary[key] = value.ToString(); + return this; + } - return this; - } + /// + /// Adds a key and value. If there is an existing key, it is replaced. + /// + /// The key. + /// The value of the key. + /// The current object. + public ToastArguments Add(string key, int value) + { + return AddHelper(key, value); + } - /// - /// Determines if the specified key is present. - /// - /// The key to look for. - /// True if the key is present, otherwise false. - public bool Contains(string key) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } + /// + /// Adds a key and value. If there is an existing key, it is replaced. + /// + /// The key. + /// The value of the key. + /// The current object. + public ToastArguments Add(string key, double value) + { + return AddHelper(key, value); + } - return _dictionary.ContainsKey(key); - } + /// + /// Adds a key and value. If there is an existing key, it is replaced. + /// + /// The key. + /// The value of the key. + /// The current object. + public ToastArguments Add(string key, float value) + { + return AddHelper(key, value); + } - /// - /// Determines if specified key and value are present. - /// - /// The key to look for. - /// The value to look for when the key has been matched. - /// True if the key and value were found, else false. - public bool Contains(string key, string value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } + /// + /// Adds a key and value. If there is an existing key, it is replaced. + /// + /// The key. + /// The value of the key. + /// The current object. + public ToastArguments Add(string key, bool value) + { + return Add(key, value ? "1" : "0"); // Encode as 1 or 0 to save string space + } - return _dictionary.TryGetValue(key, out string actualValue) && actualValue == value; - } + /// + /// Adds a key and value. If there is an existing key, it is replaced. + /// + /// The key. + /// The value of the key. 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. + /// The current object. + public ToastArguments Add(string key, Enum value) + { + return Add(key, (int)(object)value); + } - /// - /// Removes the specified key and its associated value. - /// - /// The key to remove. - /// True if the key was removed, else false. - public bool Remove(string key) + private ToastArguments AddHelper(string key, object value) + { + if (key == null) { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } + throw new ArgumentNullException(nameof(key)); + } + + _dictionary[key] = value.ToString(); - return _dictionary.Remove(key); + return this; + } + + /// + /// Determines if the specified key is present. + /// + /// The key to look for. + /// True if the key is present, otherwise false. + public bool Contains(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); } - private static string Encode(string str) + return _dictionary.ContainsKey(key); + } + + /// + /// Determines if specified key and value are present. + /// + /// The key to look for. + /// The value to look for when the key has been matched. + /// True if the key and value were found, else false. + public bool Contains(string key, string value) + { + if (key == null) { - return str - .Replace("%", "%25") - .Replace(";", "%3B") - .Replace("=", "%3D"); + throw new ArgumentNullException(nameof(key)); } - private static string Decode(string str) + return _dictionary.TryGetValue(key, out string actualValue) && actualValue == value; + } + + /// + /// Removes the specified key and its associated value. + /// + /// The key to remove. + /// True if the key was removed, else false. + public bool Remove(string key) + { + if (key == null) { - return str - .Replace("%25", "%") - .Replace("%3B", ";") - .Replace("%3D", "="); + throw new ArgumentNullException(nameof(key)); } - /// - /// Parses a string that was generated using ToastArguments into a object. - /// - /// The toast arguments string to deserialize. - /// The parsed toast arguments. - public static ToastArguments Parse(string toastArgumentsStr) + return _dictionary.Remove(key); + } + + private static string Encode(string str) + { + return str + .Replace("%", "%25") + .Replace(";", "%3B") + .Replace("=", "%3D"); + } + + private static string Decode(string str) + { + return str + .Replace("%25", "%") + .Replace("%3B", ";") + .Replace("%3D", "="); + } + + /// + /// Parses a string that was generated using ToastArguments into a object. + /// + /// The toast arguments string to deserialize. + /// The parsed toast arguments. + public static ToastArguments Parse(string toastArgumentsStr) + { + if (string.IsNullOrWhiteSpace(toastArgumentsStr)) { - if (string.IsNullOrWhiteSpace(toastArgumentsStr)) - { - return new ToastArguments(); - } + return new ToastArguments(); + } + + string[] pairs = toastArgumentsStr.Split(';'); + + ToastArguments answer = new ToastArguments(); - string[] pairs = toastArgumentsStr.Split(';'); + foreach (string pair in pairs) + { + string name; + string value; - ToastArguments answer = new ToastArguments(); + int indexOfEquals = pair.IndexOf('='); - foreach (string pair in pairs) + if (indexOfEquals == -1) + { + name = Decode(pair); + value = null; + } + else { - string name; - string value; - - int indexOfEquals = pair.IndexOf('='); - - if (indexOfEquals == -1) - { - name = Decode(pair); - value = null; - } - else - { - name = Decode(pair.Substring(0, indexOfEquals)); - value = Decode(pair.Substring(indexOfEquals + 1)); - } - - answer.Add(name, value); + name = Decode(pair.Substring(0, indexOfEquals)); + value = Decode(pair.Substring(indexOfEquals + 1)); } - return answer; + answer.Add(name, value); } - /// - /// Serializes the key-value pairs into a string that can be used within a toast notification. - /// - /// A string that can be used within a toast notification. - public sealed override string ToString() - { - return string.Join(Separator, this.Select(pair => EncodePair(pair.Key, pair.Value))); - } + return answer; + } - internal static string EncodePair(string key, string value) - { - // Key - return Encode(key) + + /// + /// Serializes the key-value pairs into a string that can be used within a toast notification. + /// + /// A string that can be used within a toast notification. + public sealed override string ToString() + { + return string.Join(Separator, this.Select(pair => EncodePair(pair.Key, pair.Value))); + } - // Write value if not null - ((value == null) ? string.Empty : ("=" + Encode(value))); - } + internal static string EncodePair(string key, string value) + { + // Key + return Encode(key) + - internal const string Separator = ";"; + // Write value if not null + ((value == null) ? string.Empty : ("=" + Encode(value))); + } - /// - /// Gets an enumerator to enumerate the arguments. Note that order of the arguments is NOT preserved. - /// - /// An enumeartor of the key/value pairs. - public IEnumerator> GetEnumerator() - { - return _dictionary.GetEnumerator(); - } + internal const string Separator = ";"; - /// - /// Gets an enumerator to enumerate the query string parameters. - /// - /// An enumeartor of the key/value pairs. - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + /// + /// Gets an enumerator to enumerate the arguments. Note that order of the arguments is NOT preserved. + /// + /// An enumeartor of the key/value pairs. + public IEnumerator> GetEnumerator() + { + return _dictionary.GetEnumerator(); + } + + /// + /// Gets an enumerator to enumerate the query string parameters. + /// + /// An enumeartor of the key/value pairs. + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); } } diff --git a/components/Notifications/src/Toasts/ToastAudio.cs b/components/Notifications/src/Toasts/ToastAudio.cs index 1f7f3a949..a284bdf7f 100644 --- a/components/Notifications/src/Toasts/ToastAudio.cs +++ b/components/Notifications/src/Toasts/ToastAudio.cs @@ -4,36 +4,35 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Specify audio to be played when the Toast notification is received. +/// +public sealed class ToastAudio { /// - /// Specify audio to be played when the Toast notification is received. + /// Gets or sets the media file to play in place of the default sound. /// - public sealed class ToastAudio - { - /// - /// Gets or sets the media file to play in place of the default sound. - /// - public Uri Src { get; set; } + public Uri Src { get; set; } - /// - /// Gets or sets a value indicating whether sound should repeat as long as the Toast is shown; false to play only once (default). - /// - public bool Loop { get; set; } = Element_ToastAudio.DEFAULT_LOOP; + /// + /// Gets or sets a value indicating whether sound should repeat as long as the Toast is shown; false to play only once (default). + /// + public bool Loop { get; set; } = Element_ToastAudio.DEFAULT_LOOP; - /// - /// Gets or sets a value indicating whether sound is muted; false to allow the Toast notification sound to play (default). - /// - public bool Silent { get; set; } = Element_ToastAudio.DEFAULT_SILENT; + /// + /// Gets or sets a value indicating whether sound is muted; false to allow the Toast notification sound to play (default). + /// + public bool Silent { get; set; } = Element_ToastAudio.DEFAULT_SILENT; - internal Element_ToastAudio ConvertToElement() + internal Element_ToastAudio ConvertToElement() + { + return new Element_ToastAudio() { - return new Element_ToastAudio() - { - Src = Src, - Loop = Loop, - Silent = Silent - }; - } + Src = Src, + Loop = Loop, + Silent = Silent + }; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastBindingGeneric.cs b/components/Notifications/src/Toasts/ToastBindingGeneric.cs index 7ea818807..39b01820b 100644 --- a/components/Notifications/src/Toasts/ToastBindingGeneric.cs +++ b/components/Notifications/src/Toasts/ToastBindingGeneric.cs @@ -6,94 +6,93 @@ using System.Collections.Generic; using CommunityToolkit.Notifications.Adaptive; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Generic Toast binding, where you provide text, images, and other visual elements for your Toast notification. +/// +public sealed class ToastBindingGeneric { /// - /// Generic Toast binding, where you provide text, images, and other visual elements for your Toast notification. + /// Gets the contents of the body of the Toast, which can include , , + /// and (added in Anniversary Update). Also, elements must come + /// before any other elements. If an element is placed after any other element, an exception + /// will be thrown when you try to retrieve the Toast XML content. And finally, certain properties + /// like HintStyle aren't supported on the root children text elements, and only work inside an . + /// If you use on devices without the Anniversary Update, the group content will simply be dropped. /// - public sealed class ToastBindingGeneric - { - /// - /// Gets the contents of the body of the Toast, which can include , , - /// and (added in Anniversary Update). Also, elements must come - /// before any other elements. If an element is placed after any other element, an exception - /// will be thrown when you try to retrieve the Toast XML content. And finally, certain properties - /// like HintStyle aren't supported on the root children text elements, and only work inside an . - /// If you use on devices without the Anniversary Update, the group content will simply be dropped. - /// - public IList Children { get; private set; } = new List(); + public IList Children { get; private set; } = new List(); - /// - /// Gets or sets an optional override of the logo displayed on the Toast notification. - /// - public ToastGenericAppLogo AppLogoOverride { get; set; } + /// + /// Gets or sets an optional override of the logo displayed on the Toast notification. + /// + public ToastGenericAppLogo AppLogoOverride { get; set; } - /// - /// Gets or sets an optional hero image (a visually impactful image displayed on the Toast notification). - /// On devices without the Anniversary Update, the hero image will simply be ignored. - /// - public ToastGenericHeroImage HeroImage { get; set; } + /// + /// Gets or sets an optional hero image (a visually impactful image displayed on the Toast notification). + /// On devices without the Anniversary Update, the hero image will simply be ignored. + /// + public ToastGenericHeroImage HeroImage { get; set; } - /// - /// Gets or sets an optional text element that is displayed as attribution text. On devices without - /// the Anniversary Update, this text will appear as if it's another - /// element at the end of your Children list. - /// - public ToastGenericAttributionText Attribution { get; set; } + /// + /// Gets or sets an optional text element that is displayed as attribution text. On devices without + /// the Anniversary Update, this text will appear as if it's another + /// element at the end of your Children list. + /// + public ToastGenericAttributionText Attribution { get; set; } - /// - /// Gets or sets the target locale of the XML payload, specified as BCP-47 language tags such as "en-US" - /// or "fr-FR". This locale is overridden by any locale specified in binding or text. If this value is - /// a literal string, this attribute defaults to the user's UI language. If this value is a string reference, - /// this attribute defaults to the locale chosen by Windows Runtime in resolving the string. - /// - public string Language { get; set; } + /// + /// Gets or sets the target locale of the XML payload, specified as BCP-47 language tags such as "en-US" + /// or "fr-FR". This locale is overridden by any locale specified in binding or text. If this value is + /// a literal string, this attribute defaults to the user's UI language. If this value is a string reference, + /// this attribute defaults to the locale chosen by Windows Runtime in resolving the string. + /// + public string Language { get; set; } - /// - /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. - /// - public Uri BaseUri { get; set; } + /// + /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. + /// + public Uri BaseUri { get; set; } - /// - /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Toast notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. - /// - public bool? AddImageQuery { get; set; } + /// + /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Toast notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. + /// + public bool? AddImageQuery { get; set; } - internal Element_ToastBinding ConvertToElement() + internal Element_ToastBinding ConvertToElement() + { + Element_ToastBinding binding = new Element_ToastBinding(ToastTemplateType.ToastGeneric) { - Element_ToastBinding binding = new Element_ToastBinding(ToastTemplateType.ToastGeneric) - { - BaseUri = BaseUri, - AddImageQuery = AddImageQuery, - Language = Language - }; + BaseUri = BaseUri, + AddImageQuery = AddImageQuery, + Language = Language + }; - // Add children - foreach (var child in Children) - { - var el = (IElement_ToastBindingChild)AdaptiveHelper.ConvertToElement(child); - binding.Children.Add(el); - } - - // Add attribution - if (Attribution != null) - { - binding.Children.Add(Attribution.ConvertToElement()); - } + // Add children + foreach (var child in Children) + { + var el = (IElement_ToastBindingChild)AdaptiveHelper.ConvertToElement(child); + binding.Children.Add(el); + } - // If there's hero, add it - if (HeroImage != null) - { - binding.Children.Add(HeroImage.ConvertToElement()); - } + // Add attribution + if (Attribution != null) + { + binding.Children.Add(Attribution.ConvertToElement()); + } - // If there's app logo, add it - if (AppLogoOverride != null) - { - binding.Children.Add(AppLogoOverride.ConvertToElement()); - } + // If there's hero, add it + if (HeroImage != null) + { + binding.Children.Add(HeroImage.ConvertToElement()); + } - return binding; + // If there's app logo, add it + if (AppLogoOverride != null) + { + binding.Children.Add(AppLogoOverride.ConvertToElement()); } + + return binding; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastBindingShoulderTap.cs b/components/Notifications/src/Toasts/ToastBindingShoulderTap.cs index 0097eb721..eb596ed3c 100644 --- a/components/Notifications/src/Toasts/ToastBindingShoulderTap.cs +++ b/components/Notifications/src/Toasts/ToastBindingShoulderTap.cs @@ -4,53 +4,52 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Specifies content you want to appear in a My People shoulder tap notification. For more info, see the My People notifications documentation. New in Fall Creators Update. +/// +public sealed class ToastBindingShoulderTap { /// - /// Specifies content you want to appear in a My People shoulder tap notification. For more info, see the My People notifications documentation. New in Fall Creators Update. + /// Gets or sets the image to be displayed in the shoulder tap notification. Required. + /// + public ToastShoulderTapImage Image { get; set; } + + /// + /// Gets or sets the target locale of the XML payload, specified as BCP-47 language tags such as "en-US" + /// or "fr-FR". This locale is overridden by any locale specified in binding or text. If this value is + /// a literal string, this attribute defaults to the user's UI language. If this value is a string reference, + /// this attribute defaults to the locale chosen by Windows Runtime in resolving the string. + /// + public string Language { get; set; } + + /// + /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. /// - public sealed class ToastBindingShoulderTap + public Uri BaseUri { get; set; } + + /// + /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Toast notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. + /// + public bool? AddImageQuery { get; set; } + + internal Element_ToastBinding ConvertToElement() { - /// - /// Gets or sets the image to be displayed in the shoulder tap notification. Required. - /// - public ToastShoulderTapImage Image { get; set; } - - /// - /// Gets or sets the target locale of the XML payload, specified as BCP-47 language tags such as "en-US" - /// or "fr-FR". This locale is overridden by any locale specified in binding or text. If this value is - /// a literal string, this attribute defaults to the user's UI language. If this value is a string reference, - /// this attribute defaults to the locale chosen by Windows Runtime in resolving the string. - /// - public string Language { get; set; } - - /// - /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. - /// - public Uri BaseUri { get; set; } - - /// - /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Toast notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. - /// - public bool? AddImageQuery { get; set; } - - internal Element_ToastBinding ConvertToElement() + Element_ToastBinding binding = new Element_ToastBinding(ToastTemplateType.ToastGeneric) + { + ExperienceType = "shoulderTap", + BaseUri = BaseUri, + AddImageQuery = AddImageQuery, + Language = Language + }; + + // If there's an image, add it + if (Image != null) { - Element_ToastBinding binding = new Element_ToastBinding(ToastTemplateType.ToastGeneric) - { - ExperienceType = "shoulderTap", - BaseUri = BaseUri, - AddImageQuery = AddImageQuery, - Language = Language - }; - - // If there's an image, add it - if (Image != null) - { - binding.Children.Add(Image.ConvertToElement()); - } - - return binding; + binding.Children.Add(Image.ConvertToElement()); } + + return binding; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastButton.cs b/components/Notifications/src/Toasts/ToastButton.cs index e0db4f7cf..92d150e0f 100644 --- a/components/Notifications/src/Toasts/ToastButton.cs +++ b/components/Notifications/src/Toasts/ToastButton.cs @@ -5,442 +5,441 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A button that the user can click on a Toast notification. +/// +public sealed class ToastButton : + IToastActivateableBuilder, + IToastButton { - /// - /// A button that the user can click on a Toast notification. - /// - public sealed class ToastButton : - IToastActivateableBuilder, - IToastButton - { - private Dictionary _arguments = new Dictionary(); + private Dictionary _arguments = new Dictionary(); - private bool _usingCustomArguments; + private bool _usingCustomArguments; - private bool _usingSnoozeActivation; - private string _snoozeSelectionBoxId; + private bool _usingSnoozeActivation; + private string _snoozeSelectionBoxId; - private bool _usingDismissActivation; + private bool _usingDismissActivation; - internal bool NeedsContent() - { - // Snooze/dismiss buttons don't need content (the system will auto-add the localized strings). - return !_usingDismissActivation && !_usingSnoozeActivation; - } + internal bool NeedsContent() + { + // Snooze/dismiss buttons don't need content (the system will auto-add the localized strings). + return !_usingDismissActivation && !_usingSnoozeActivation; + } - /// - /// Initializes a new instance of the class. - /// - /// The text to display on the button. - /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button. - public ToastButton(string content, string arguments) + /// + /// Initializes a new instance of the class. + /// + /// The text to display on the button. + /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button. + public ToastButton(string content, string arguments) + { + if (content == null) { - if (content == null) - { - throw new ArgumentNullException(nameof(content)); - } - - if (arguments == null) - { - throw new ArgumentNullException(nameof(arguments)); - } - - Content = content; - Arguments = arguments; - - _usingCustomArguments = arguments.Length > 0; + throw new ArgumentNullException(nameof(content)); } - /// - /// Initializes a new instance of the class. - /// - public ToastButton() + if (arguments == null) { - // Arguments are required (we'll initialize to empty string which is fine). - Arguments = string.Empty; + throw new ArgumentNullException(nameof(arguments)); } - /// - /// Gets the text to display on the button. Required - /// - public string Content { get; private set; } - - /// - /// Gets app-defined string of arguments that the app can later retrieve once it is - /// activated when the user clicks the button. Required - /// - public string Arguments { get; internal set; } - - /// - /// Gets or sets what type of activation this button will use when clicked. Defaults to Foreground. - /// - public ToastActivationType ActivationType { get; set; } = ToastActivationType.Foreground; - - /// - /// Gets or sets additional options relating to activation of the toast button. New in Creators Update - /// - public ToastActivationOptions ActivationOptions { get; set; } - - /// - /// Gets or sets an optional image icon for the button to display (required for buttons adjacent to inputs like quick reply). - /// - public string ImageUri { get; set; } - - /// - /// Gets or sets the ID of an existing in order to have this button display - /// to the right of the input, achieving a quick reply scenario. - /// - public string TextBoxId { get; set; } - - /// - /// Gets or sets an identifier used in telemetry to identify your category of action. This should be something - /// like "Delete", "Reply", or "Archive". In the upcoming toast telemetry dashboard in Dev Center, you will - /// be able to view how frequently your actions are being clicked. - /// - public string HintActionId { get; set; } - - /// - /// Sets the text to display on the button. - /// - /// The text to display on the button. - /// The current instance of the . - public ToastButton SetContent(string content) - { - Content = content; - return this; - } + Content = content; + Arguments = arguments; - /// - /// Adds a key (without value) to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key. - /// The current instance of - public ToastButton AddArgument(string key) - { - return AddArgumentHelper(key, null); - } + _usingCustomArguments = arguments.Length > 0; + } - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of - public ToastButton AddArgument(string key, string value) - { - return AddArgumentHelper(key, value); - } + /// + /// Initializes a new instance of the class. + /// + public ToastButton() + { + // Arguments are required (we'll initialize to empty string which is fine). + Arguments = string.Empty; + } - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of - public ToastButton AddArgument(string key, int value) - { - return AddArgumentHelper(key, value.ToString()); - } + /// + /// Gets the text to display on the button. Required + /// + public string Content { get; private set; } - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of - public ToastButton AddArgument(string key, double value) - { - return AddArgumentHelper(key, value.ToString()); - } + /// + /// Gets app-defined string of arguments that the app can later retrieve once it is + /// activated when the user clicks the button. Required + /// + public string Arguments { get; internal set; } - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of - public ToastButton AddArgument(string key, float value) - { - return AddArgumentHelper(key, value.ToString()); - } + /// + /// Gets or sets what type of activation this button will use when clicked. Defaults to Foreground. + /// + public ToastActivationType ActivationType { get; set; } = ToastActivationType.Foreground; - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this value. - /// The value itself. - /// The current instance of - public ToastButton AddArgument(string key, bool value) - { - return AddArgumentHelper(key, value ? "1" : "0"); // Encode as 1 or 0 to save string space - } + /// + /// Gets or sets additional options relating to activation of the toast button. New in Creators Update + /// + public ToastActivationOptions ActivationOptions { get; set; } - /// - /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. - /// - /// The key for this 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. - /// The current instance of - public ToastButton AddArgument(string key, Enum value) - { - return AddArgumentHelper(key, ((int)(object)value).ToString()); - } + /// + /// Gets or sets an optional image icon for the button to display (required for buttons adjacent to inputs like quick reply). + /// + public string ImageUri { get; set; } - private ToastButton AddArgumentHelper(string key, string value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } + /// + /// Gets or sets the ID of an existing in order to have this button display + /// to the right of the input, achieving a quick reply scenario. + /// + public string TextBoxId { get; set; } - if (_usingCustomArguments) - { - throw new InvalidOperationException("You cannot use the AddArgument methods if you've set the Arguments property. Use the default ToastButton constructor instead."); - } + /// + /// Gets or sets an identifier used in telemetry to identify your category of action. This should be something + /// like "Delete", "Reply", or "Archive". In the upcoming toast telemetry dashboard in Dev Center, you will + /// be able to view how frequently your actions are being clicked. + /// + public string HintActionId { get; set; } - if (ActivationType == ToastActivationType.Protocol) - { - throw new InvalidOperationException("You cannot use the AddArgument methods when using protocol activation."); - } + /// + /// Sets the text to display on the button. + /// + /// The text to display on the button. + /// The current instance of the . + public ToastButton SetContent(string content) + { + Content = content; + return this; + } - if (_usingDismissActivation || _usingSnoozeActivation) - { - throw new InvalidOperationException("You cannot use the AddArgument methods when using dismiss or snooze activation."); - } + /// + /// Adds a key (without value) to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key. + /// The current instance of + public ToastButton AddArgument(string key) + { + return AddArgumentHelper(key, null); + } - bool alreadyExists = _arguments.ContainsKey(key); + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of + public ToastButton AddArgument(string key, string value) + { + return AddArgumentHelper(key, value); + } - _arguments[key] = value; + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of + public ToastButton AddArgument(string key, int value) + { + return AddArgumentHelper(key, value.ToString()); + } - Arguments = alreadyExists ? SerializeArgumentsHelper(_arguments) : AddArgumentHelper(Arguments, key, value); + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of + public ToastButton AddArgument(string key, double value) + { + return AddArgumentHelper(key, value.ToString()); + } - return this; - } + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of + public ToastButton AddArgument(string key, float value) + { + return AddArgumentHelper(key, value.ToString()); + } - private string SerializeArgumentsHelper(IDictionary arguments) - { - var args = new ToastArguments(); + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this value. + /// The value itself. + /// The current instance of + public ToastButton AddArgument(string key, bool value) + { + return AddArgumentHelper(key, value ? "1" : "0"); // Encode as 1 or 0 to save string space + } - foreach (var a in arguments) - { - args.Add(a.Key, a.Value); - } + /// + /// Adds a key/value to the activation arguments that will be returned when the toast notification or its buttons are clicked. + /// + /// The key for this 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. + /// The current instance of + public ToastButton AddArgument(string key, Enum value) + { + return AddArgumentHelper(key, ((int)(object)value).ToString()); + } - return args.ToString(); + private ToastButton AddArgumentHelper(string key, string value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); } - private string AddArgumentHelper(string existing, string key, string value) + if (_usingCustomArguments) { - string pair = ToastArguments.EncodePair(key, value); - - if (string.IsNullOrEmpty(existing)) - { - return pair; - } - else - { - return existing + ToastArguments.Separator + pair; - } + throw new InvalidOperationException("You cannot use the AddArgument methods if you've set the Arguments property. Use the default ToastButton constructor instead."); } - /// - /// Configures the button to launch the specified url when the button is clicked. - /// - /// The protocol to launch. - /// The current instance of - public ToastButton SetProtocolActivation(Uri protocol) + if (ActivationType == ToastActivationType.Protocol) { - return SetProtocolActivation(protocol, default); + throw new InvalidOperationException("You cannot use the AddArgument methods when using protocol activation."); } - /// - /// Configures the button to launch the specified url when the button is clicked. - /// - /// The protocol to launch. - /// New in Creators Update: The target PFN, so that regardless of whether multiple apps are registered to handle the same protocol uri, your desired app will always be launched. - /// The current instance of - public ToastButton SetProtocolActivation(Uri protocol, string targetApplicationPfn) + if (_usingDismissActivation || _usingSnoozeActivation) { - if (_arguments.Count > 0) - { - throw new InvalidOperationException("SetProtocolActivation cannot be used in conjunction with AddArgument"); - } + throw new InvalidOperationException("You cannot use the AddArgument methods when using dismiss or snooze activation."); + } - Arguments = protocol.ToString(); - ActivationType = ToastActivationType.Protocol; + bool alreadyExists = _arguments.ContainsKey(key); - if (targetApplicationPfn != null) - { - if (ActivationOptions == null) - { - ActivationOptions = new ToastActivationOptions(); - } + _arguments[key] = value; - ActivationOptions.ProtocolActivationTargetApplicationPfn = targetApplicationPfn; - } + Arguments = alreadyExists ? SerializeArgumentsHelper(_arguments) : AddArgumentHelper(Arguments, key, value); - return this; - } + return this; + } - /// - /// Configures the button to use background activation when the button is clicked. - /// - /// The current instance of - public ToastButton SetBackgroundActivation() - { - ActivationType = ToastActivationType.Background; - return this; - } + private string SerializeArgumentsHelper(IDictionary arguments) + { + var args = new ToastArguments(); - /// - /// Sets the behavior that the toast should use when the user invokes this button. Desktop-only, supported in builds 16251 or higher. New in Fall Creators Update. - /// - /// The behavior that the toast should use when the user invokes this button. - /// The current instance of - public ToastButton SetAfterActivationBehavior(ToastAfterActivationBehavior afterActivationBehavior) + foreach (var a in arguments) { - if (ActivationOptions == null) - { - ActivationOptions = new ToastActivationOptions(); - } + args.Add(a.Key, a.Value); + } - ActivationOptions.AfterActivationBehavior = afterActivationBehavior; + return args.ToString(); + } - return this; - } + private string AddArgumentHelper(string existing, string key, string value) + { + string pair = ToastArguments.EncodePair(key, value); - /// - /// Configures the button to use system snooze activation when the button is clicked, using the default system snooze time. - /// - /// The current instance of - public ToastButton SetSnoozeActivation() + if (string.IsNullOrEmpty(existing)) { - return SetSnoozeActivation(null); + return pair; } - - /// - /// Configures the button to use system snooze activation when the button is clicked, with a snooze time defined by the specified selection box. - /// - /// The ID of an existing which allows the user to pick a custom snooze time. The ID's of the s inside the selection box must represent the snooze interval in minutes. For example, if the user selects an item that has an ID of "120", then the notification will be snoozed for 2 hours. When the user clicks this button, if you specified a SelectionBoxId, the system will parse the ID of the selected item and snooze by that amount of minutes. - /// The current instance of - public ToastButton SetSnoozeActivation(string selectionBoxId) + else { - if (_arguments.Count > 0) - { - throw new InvalidOperationException($"{nameof(SetSnoozeActivation)} cannot be used in conjunction with ${nameof(AddArgument)}."); - } + return existing + ToastArguments.Separator + pair; + } + } - _usingSnoozeActivation = true; - _snoozeSelectionBoxId = selectionBoxId; + /// + /// Configures the button to launch the specified url when the button is clicked. + /// + /// The protocol to launch. + /// The current instance of + public ToastButton SetProtocolActivation(Uri protocol) + { + return SetProtocolActivation(protocol, default); + } - return this; + /// + /// Configures the button to launch the specified url when the button is clicked. + /// + /// The protocol to launch. + /// New in Creators Update: The target PFN, so that regardless of whether multiple apps are registered to handle the same protocol uri, your desired app will always be launched. + /// The current instance of + public ToastButton SetProtocolActivation(Uri protocol, string targetApplicationPfn) + { + if (_arguments.Count > 0) + { + throw new InvalidOperationException("SetProtocolActivation cannot be used in conjunction with AddArgument"); } - /// - /// Configures the button to use system dismiss activation when the button is clicked (the toast will simply dismiss rather than activating). - /// - /// The current instance of - public ToastButton SetDismissActivation() + Arguments = protocol.ToString(); + ActivationType = ToastActivationType.Protocol; + + if (targetApplicationPfn != null) { - if (_arguments.Count > 0) + if (ActivationOptions == null) { - throw new InvalidOperationException($"{nameof(SetDismissActivation)} cannot be used in conjunction with ${nameof(AddArgument)}."); + ActivationOptions = new ToastActivationOptions(); } - _usingDismissActivation = true; - return this; + ActivationOptions.ProtocolActivationTargetApplicationPfn = targetApplicationPfn; } - /// - /// Sets an identifier used in telemetry to identify your category of action. This should be something like "Delete", "Reply", or "Archive". In the upcoming toast telemetry dashboard in Dev Center, you will be able to view how frequently your actions are being clicked. - /// - /// An identifier used in telemetry to identify your category of action. - /// The current instance of - public ToastButton SetHintActionId(string actionId) - { - HintActionId = actionId; - return this; - } + return this; + } + + /// + /// Configures the button to use background activation when the button is clicked. + /// + /// The current instance of + public ToastButton SetBackgroundActivation() + { + ActivationType = ToastActivationType.Background; + return this; + } - /// - /// Sets an optional image icon for the button to display (required for buttons adjacent to inputs like quick reply). - /// - /// An optional image icon for the button to display. - /// The current instance of - public ToastButton SetImageUri(Uri imageUri) + /// + /// Sets the behavior that the toast should use when the user invokes this button. Desktop-only, supported in builds 16251 or higher. New in Fall Creators Update. + /// + /// The behavior that the toast should use when the user invokes this button. + /// The current instance of + public ToastButton SetAfterActivationBehavior(ToastAfterActivationBehavior afterActivationBehavior) + { + if (ActivationOptions == null) { - ImageUri = imageUri.ToString(); - return this; + ActivationOptions = new ToastActivationOptions(); } - /// - /// Sets the ID of an existing in order to have this button display to the right of the input, achieving a quick reply scenario. - /// - /// The ID of an existing . - /// The current instance of - public ToastButton SetTextBoxId(string textBoxId) + ActivationOptions.AfterActivationBehavior = afterActivationBehavior; + + return this; + } + + /// + /// Configures the button to use system snooze activation when the button is clicked, using the default system snooze time. + /// + /// The current instance of + public ToastButton SetSnoozeActivation() + { + return SetSnoozeActivation(null); + } + + /// + /// Configures the button to use system snooze activation when the button is clicked, with a snooze time defined by the specified selection box. + /// + /// The ID of an existing which allows the user to pick a custom snooze time. The ID's of the s inside the selection box must represent the snooze interval in minutes. For example, if the user selects an item that has an ID of "120", then the notification will be snoozed for 2 hours. When the user clicks this button, if you specified a SelectionBoxId, the system will parse the ID of the selected item and snooze by that amount of minutes. + /// The current instance of + public ToastButton SetSnoozeActivation(string selectionBoxId) + { + if (_arguments.Count > 0) { - TextBoxId = textBoxId; - return this; + throw new InvalidOperationException($"{nameof(SetSnoozeActivation)} cannot be used in conjunction with ${nameof(AddArgument)}."); } - internal bool CanAddArguments() + _usingSnoozeActivation = true; + _snoozeSelectionBoxId = selectionBoxId; + + return this; + } + + /// + /// Configures the button to use system dismiss activation when the button is clicked (the toast will simply dismiss rather than activating). + /// + /// The current instance of + public ToastButton SetDismissActivation() + { + if (_arguments.Count > 0) { - return ActivationType != ToastActivationType.Protocol && !_usingCustomArguments && !_usingDismissActivation && !_usingSnoozeActivation; + throw new InvalidOperationException($"{nameof(SetDismissActivation)} cannot be used in conjunction with ${nameof(AddArgument)}."); } - internal bool ContainsArgument(string key) + _usingDismissActivation = true; + return this; + } + + /// + /// Sets an identifier used in telemetry to identify your category of action. This should be something like "Delete", "Reply", or "Archive". In the upcoming toast telemetry dashboard in Dev Center, you will be able to view how frequently your actions are being clicked. + /// + /// An identifier used in telemetry to identify your category of action. + /// The current instance of + public ToastButton SetHintActionId(string actionId) + { + HintActionId = actionId; + return this; + } + + /// + /// Sets an optional image icon for the button to display (required for buttons adjacent to inputs like quick reply). + /// + /// An optional image icon for the button to display. + /// The current instance of + public ToastButton SetImageUri(Uri imageUri) + { + ImageUri = imageUri.ToString(); + return this; + } + + /// + /// Sets the ID of an existing in order to have this button display to the right of the input, achieving a quick reply scenario. + /// + /// The ID of an existing . + /// The current instance of + public ToastButton SetTextBoxId(string textBoxId) + { + TextBoxId = textBoxId; + return this; + } + + internal bool CanAddArguments() + { + return ActivationType != ToastActivationType.Protocol && !_usingCustomArguments && !_usingDismissActivation && !_usingSnoozeActivation; + } + + internal bool ContainsArgument(string key) + { + return _arguments.ContainsKey(key); + } + + internal Element_ToastAction ConvertToElement() + { + var el = new Element_ToastAction() { - return _arguments.ContainsKey(key); - } + Content = Content, + ImageUri = ImageUri, + InputId = TextBoxId, + HintActionId = HintActionId + }; - internal Element_ToastAction ConvertToElement() + if (_usingSnoozeActivation) { - var el = new Element_ToastAction() - { - Content = Content, - ImageUri = ImageUri, - InputId = TextBoxId, - HintActionId = HintActionId - }; + el.ActivationType = Element_ToastActivationType.System; + el.Arguments = "snooze"; - if (_usingSnoozeActivation) + if (_snoozeSelectionBoxId != null) { - el.ActivationType = Element_ToastActivationType.System; - el.Arguments = "snooze"; - - if (_snoozeSelectionBoxId != null) - { - el.InputId = _snoozeSelectionBoxId; - } - - // Content needs to be specified as empty for auto-generated Snooze content - if (el.Content == null) - { - el.Content = string.Empty; - } + el.InputId = _snoozeSelectionBoxId; } - else if (_usingDismissActivation) + + // Content needs to be specified as empty for auto-generated Snooze content + if (el.Content == null) { - el.ActivationType = Element_ToastActivationType.System; - el.Arguments = "dismiss"; - - // Content needs to be specified as empty for auto-generated Dismiss content - if (el.Content == null) - { - el.Content = string.Empty; - } + el.Content = string.Empty; } - else + } + else if (_usingDismissActivation) + { + el.ActivationType = Element_ToastActivationType.System; + el.Arguments = "dismiss"; + + // Content needs to be specified as empty for auto-generated Dismiss content + if (el.Content == null) { - el.ActivationType = Element_Toast.ConvertActivationType(ActivationType); - el.Arguments = Arguments; + el.Content = string.Empty; } + } + else + { + el.ActivationType = Element_Toast.ConvertActivationType(ActivationType); + el.Arguments = Arguments; + } - ActivationOptions?.PopulateElement(el); + ActivationOptions?.PopulateElement(el); - return el; - } + return el; } } diff --git a/components/Notifications/src/Toasts/ToastButtonDismiss.cs b/components/Notifications/src/Toasts/ToastButtonDismiss.cs index 9a92683b5..e3df03cb1 100644 --- a/components/Notifications/src/Toasts/ToastButtonDismiss.cs +++ b/components/Notifications/src/Toasts/ToastButtonDismiss.cs @@ -4,64 +4,63 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A button that, when clicked, is interpreted as a "dismiss" by the system, and the Toast is dismissed just like if the user swiped the Toast away. +/// +public sealed class ToastButtonDismiss : IToastButton { /// - /// A button that, when clicked, is interpreted as a "dismiss" by the system, and the Toast is dismissed just like if the user swiped the Toast away. + /// Gets custom text displayed on the button that overrides the default localized "Dismiss" text. /// - public sealed class ToastButtonDismiss : IToastButton - { - /// - /// Gets custom text displayed on the button that overrides the default localized "Dismiss" text. - /// - public string CustomContent { get; private set; } + public string CustomContent { get; private set; } - /// - /// Gets or sets an optional image icon for the button to display. - /// - public string ImageUri { get; set; } + /// + /// Gets or sets an optional image icon for the button to display. + /// + public string ImageUri { get; set; } - /// - /// Gets or sets an identifier used in telemetry to identify your category of action. This should be something - /// like "Delete", "Reply", or "Archive". In the upcoming toast telemetry dashboard in Dev Center, you will - /// be able to view how frequently your actions are being clicked. - /// - public string HintActionId { get; set; } + /// + /// Gets or sets an identifier used in telemetry to identify your category of action. This should be something + /// like "Delete", "Reply", or "Archive". In the upcoming toast telemetry dashboard in Dev Center, you will + /// be able to view how frequently your actions are being clicked. + /// + public string HintActionId { get; set; } - /// - /// Initializes a new instance of the class. - /// - public ToastButtonDismiss() - { - } + /// + /// Initializes a new instance of the class. + /// + public ToastButtonDismiss() + { + } - /// - /// Initializes a new instance of the class. - /// Constructs a system-handled dismiss button that displays your text on the button. - /// - /// The text you want displayed on the button. - public ToastButtonDismiss(string customContent) + /// + /// Initializes a new instance of the class. + /// Constructs a system-handled dismiss button that displays your text on the button. + /// + /// The text you want displayed on the button. + public ToastButtonDismiss(string customContent) + { + if (customContent == null) { - if (customContent == null) - { - throw new ArgumentNullException(nameof(customContent)); - } - - CustomContent = customContent; + throw new ArgumentNullException(nameof(customContent)); } - internal Element_ToastAction ConvertToElement() + CustomContent = customContent; + } + + internal Element_ToastAction ConvertToElement() + { + return new Element_ToastAction() { - return new Element_ToastAction() - { - Content = this.CustomContent == null ? string.Empty : this.CustomContent, // If not using custom content, we need to provide empty string, otherwise Toast doesn't get displayed - Arguments = "dismiss", - ActivationType = Element_ToastActivationType.System, - ImageUri = ImageUri, - HintActionId = HintActionId + Content = this.CustomContent == null ? string.Empty : this.CustomContent, // If not using custom content, we need to provide empty string, otherwise Toast doesn't get displayed + Arguments = "dismiss", + ActivationType = Element_ToastActivationType.System, + ImageUri = ImageUri, + HintActionId = HintActionId - // InputId is useless since dismiss button can't be placed to the right of text box (shell doesn't display it) - }; - } + // InputId is useless since dismiss button can't be placed to the right of text box (shell doesn't display it) + }; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastButtonSnooze.cs b/components/Notifications/src/Toasts/ToastButtonSnooze.cs index f2f29283a..d9f33c574 100644 --- a/components/Notifications/src/Toasts/ToastButtonSnooze.cs +++ b/components/Notifications/src/Toasts/ToastButtonSnooze.cs @@ -4,74 +4,73 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A system-handled snooze button that automatically handles snoozing of a Toast notification. +/// +public sealed class ToastButtonSnooze : IToastButton { /// - /// A system-handled snooze button that automatically handles snoozing of a Toast notification. + /// Gets custom text displayed on the button that overrides the default localized "Snooze" text. /// - public sealed class ToastButtonSnooze : IToastButton - { - /// - /// Gets custom text displayed on the button that overrides the default localized "Snooze" text. - /// - public string CustomContent { get; private set; } + public string CustomContent { get; private set; } - /// - /// Gets or sets an optional image icon for the button to display. - /// - public string ImageUri { get; set; } + /// + /// Gets or sets an optional image icon for the button to display. + /// + public string ImageUri { get; set; } - /// - /// Gets or sets the ID of an existing in order to allow the - /// user to pick a custom snooze time. Optional. The ID's of the s - /// inside the selection box must represent the snooze interval in minutes. For example, - /// if the user selects an item that has an ID of "120", then the notification will be snoozed - /// for 2 hours. When the user clicks this button, if you specified a SelectionBoxId, the system - /// will parse the ID of the selected item and snooze by that amount of minutes. If you didn't specify - /// a SelectionBoxId, the system will snooze by the default system snooze time. - /// - public string SelectionBoxId { get; set; } + /// + /// Gets or sets the ID of an existing in order to allow the + /// user to pick a custom snooze time. Optional. The ID's of the s + /// inside the selection box must represent the snooze interval in minutes. For example, + /// if the user selects an item that has an ID of "120", then the notification will be snoozed + /// for 2 hours. When the user clicks this button, if you specified a SelectionBoxId, the system + /// will parse the ID of the selected item and snooze by that amount of minutes. If you didn't specify + /// a SelectionBoxId, the system will snooze by the default system snooze time. + /// + public string SelectionBoxId { get; set; } - /// - /// Gets or sets an identifier used in telemetry to identify your category of action. This should be something - /// like "Delete", "Reply", or "Archive". In the upcoming toast telemetry dashboard in Dev Center, you will - /// be able to view how frequently your actions are being clicked. - /// - public string HintActionId { get; set; } + /// + /// Gets or sets an identifier used in telemetry to identify your category of action. This should be something + /// like "Delete", "Reply", or "Archive". In the upcoming toast telemetry dashboard in Dev Center, you will + /// be able to view how frequently your actions are being clicked. + /// + public string HintActionId { get; set; } - /// - /// Initializes a new instance of the class. - /// - public ToastButtonSnooze() - { - } + /// + /// Initializes a new instance of the class. + /// + public ToastButtonSnooze() + { + } - /// - /// Initializes a new instance of the class. - /// Initializes a system-handled snooze button that displays your text on the button and automatically handles snoozing. - /// - /// The text you want displayed on the button. - public ToastButtonSnooze(string customContent) + /// + /// Initializes a new instance of the class. + /// Initializes a system-handled snooze button that displays your text on the button and automatically handles snoozing. + /// + /// The text you want displayed on the button. + public ToastButtonSnooze(string customContent) + { + if (customContent == null) { - if (customContent == null) - { - throw new ArgumentNullException(nameof(customContent)); - } - - CustomContent = customContent; + throw new ArgumentNullException(nameof(customContent)); } - internal Element_ToastAction ConvertToElement() + CustomContent = customContent; + } + + internal Element_ToastAction ConvertToElement() + { + return new Element_ToastAction() { - return new Element_ToastAction() - { - Content = CustomContent ?? string.Empty, // If not using custom content, we need to provide empty string, otherwise Toast doesn't get displayed - Arguments = "snooze", - ActivationType = Element_ToastActivationType.System, - InputId = SelectionBoxId, - ImageUri = ImageUri, - HintActionId = HintActionId - }; - } + Content = CustomContent ?? string.Empty, // If not using custom content, we need to provide empty string, otherwise Toast doesn't get displayed + Arguments = "snooze", + ActivationType = Element_ToastActivationType.System, + InputId = SelectionBoxId, + ImageUri = ImageUri, + HintActionId = HintActionId + }; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastCommon.cs b/components/Notifications/src/Toasts/ToastCommon.cs index 088ec6ca0..76f4937fe 100644 --- a/components/Notifications/src/Toasts/ToastCommon.cs +++ b/components/Notifications/src/Toasts/ToastCommon.cs @@ -2,42 +2,41 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Decides the type of activation that will be used when the user interacts with the Toast notification. +/// +public enum ToastActivationType { /// - /// Decides the type of activation that will be used when the user interacts with the Toast notification. + /// Default value. Your foreground app is launched. /// - public enum ToastActivationType - { - /// - /// Default value. Your foreground app is launched. - /// - Foreground, + Foreground, - /// - /// Your corresponding background task (assuming you set everything up) is triggered, and you can execute code in the background (like sending the user's quick reply message) without interrupting the user. - /// - Background, + /// + /// Your corresponding background task (assuming you set everything up) is triggered, and you can execute code in the background (like sending the user's quick reply message) without interrupting the user. + /// + Background, - /// - /// Launch a different app using protocol activation. - /// - Protocol - } + /// + /// Launch a different app using protocol activation. + /// + Protocol +} +/// +/// Specifies the behavior that the toast should use when the user takes action on the toast. +/// +public enum ToastAfterActivationBehavior +{ /// - /// Specifies the behavior that the toast should use when the user takes action on the toast. + /// Default behavior. The toast will be dismissed when the user takes action on the toast. /// - public enum ToastAfterActivationBehavior - { - /// - /// Default behavior. The toast will be dismissed when the user takes action on the toast. - /// - Default, + Default, - /// - /// After the user clicks a button on your toast, the notification will remain present, in a "pending update" visual state. You should immediately update your toast from a background task so that the user does not see this "pending update" visual state for too long. - /// - PendingUpdate - } + /// + /// After the user clicks a button on your toast, the notification will remain present, in a "pending update" visual state. You should immediately update your toast from a background task so that the user does not see this "pending update" visual state for too long. + /// + PendingUpdate } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastContent.cs b/components/Notifications/src/Toasts/ToastContent.cs index d361cca3e..a99d5674a 100644 --- a/components/Notifications/src/Toasts/ToastContent.cs +++ b/components/Notifications/src/Toasts/ToastContent.cs @@ -7,181 +7,180 @@ using Windows.Data.Xml.Dom; using Windows.UI.Notifications; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Base Toast element, which contains at least a visual element. +/// +public sealed class ToastContent : INotificationContent { /// - /// Base Toast element, which contains at least a visual element. + /// Gets or sets the visual element (Required). /// - public sealed class ToastContent : INotificationContent - { - /// - /// Gets or sets the visual element (Required). - /// - public ToastVisual Visual { get; set; } - - /// - /// Gets or sets custom audio options. - /// - public ToastAudio Audio { get; set; } - - /// - /// Gets or sets optional custom actions with buttons and inputs (using ) - /// or optionally use the system-default snooze/dismiss controls (with ). - /// - public IToastActions Actions { get; set; } - - /// - /// Gets or sets an optional header for the toast notification. Requires Creators Update - /// - public ToastHeader Header { get; set; } - - /// - /// Gets or sets the scenario, to make the Toast behave like an alarm, reminder, or more. - /// - public ToastScenario Scenario { get; set; } - - /// - /// Gets or sets the amount of time the Toast should display. You typically should use the - /// Scenario attribute instead, which impacts how long a Toast stays on screen. - /// - public ToastDuration Duration { get; set; } - - /// - /// Gets or sets a string that is passed to the application when it is activated by the Toast. - /// The format and contents of this string are defined by the app for its own use. When the user - /// taps or clicks the Toast to launch its associated app, the launch string provides the context - /// to the app that allows it to show the user a view relevant to the Toast content, rather than - /// launching in its default way. - /// - public string Launch { get; set; } - - /// - /// Gets or sets what activation type will be used when the user clicks the body of this Toast. - /// - public ToastActivationType ActivationType { get; set; } - - /// - /// Gets or sets additional options relating to activation of the toast notification. Requires Creators Updated - /// - public ToastActivationOptions ActivationOptions { get; set; } - - /// - /// Gets or sets an optional custom time to use for the notification's timestamp, visible within Action Center. - /// If provided, this date/time will be used on the notification instead of the date/time that the notification was received. - /// Requires Creators Update - /// - public DateTimeOffset? DisplayTimestamp { get; set; } - - /// - /// Gets or sets an identifier used in telemetry to identify your category of toast notification. This should be something - /// like "NewMessage", "AppointmentReminder", "Promo30Off", or "PleaseRate". In the upcoming toast telemetry dashboard - /// in Dev Center, you will be able to view activation info filtered by toast identifier. - /// - public string HintToastId { get; set; } - - /// - /// Gets or sets the person that this toast is related to. For more info, see the My People documentation. New in Fall Creators Update. - /// - public ToastPeople HintPeople { get; set; } - - /// - /// Gets a dictionary where you can assign additional properties. - /// - public IDictionary AdditionalProperties { get; } = new Dictionary(); - - /// - /// Retrieves the notification XML content as a string, so that it can be sent with a HTTP POST in a push notification. - /// - /// The notification XML content as a string. - public string GetContent() - { - return ConvertToElement().GetContent(); - } + public ToastVisual Visual { get; set; } + /// + /// Gets or sets custom audio options. + /// + public ToastAudio Audio { get; set; } - /// - /// Retrieves the notification XML content as a WinRT XmlDocument, so that it can be used with a local Toast notification's constructor on either or . - /// - /// The notification XML content as a WinRT XmlDocument. - public XmlDocument GetXml() - { - XmlDocument doc = new XmlDocument(); - doc.LoadXml(GetContent()); + /// + /// Gets or sets optional custom actions with buttons and inputs (using ) + /// or optionally use the system-default snooze/dismiss controls (with ). + /// + public IToastActions Actions { get; set; } - return doc; - } + /// + /// Gets or sets an optional header for the toast notification. Requires Creators Update + /// + public ToastHeader Header { get; set; } - internal Element_Toast ConvertToElement() - { - if (ActivationOptions != null) - { - if (ActivationOptions.AfterActivationBehavior != ToastAfterActivationBehavior.Default) - { - throw new InvalidOperationException("ToastContent does not support a custom AfterActivationBehavior. Please ensure ActivationOptions.AfterActivationBehavior is set to Default."); - } - } + /// + /// Gets or sets the scenario, to make the Toast behave like an alarm, reminder, or more. + /// + public ToastScenario Scenario { get; set; } - DateTimeOffset? strippedDisplayTimestamp = null; - if (DisplayTimestamp != null) - { - // We need to make sure we don't include more than 3 decimal points on seconds - // The Millisecond value itself is limited to 3 decimal points, thus by doing the following - // we bypass the more granular value that can come from Ticks and ensure we only have 3 decimals at most. - var val = DisplayTimestamp.Value; - strippedDisplayTimestamp = new DateTimeOffset(val.Year, val.Month, val.Day, val.Hour, val.Minute, val.Second, val.Millisecond, val.Offset); - } + /// + /// Gets or sets the amount of time the Toast should display. You typically should use the + /// Scenario attribute instead, which impacts how long a Toast stays on screen. + /// + public ToastDuration Duration { get; set; } - var toast = new Element_Toast() - { - ActivationType = Element_Toast.ConvertActivationType(ActivationType), - Duration = Duration, - Launch = Launch, - Scenario = Scenario, - DisplayTimestamp = strippedDisplayTimestamp, - HintToastId = HintToastId, - AdditionalProperties = (Dictionary)AdditionalProperties - }; - - ActivationOptions?.PopulateElement(toast); - - if (Visual != null) - { - toast.Visual = Visual.ConvertToElement(); - } + /// + /// Gets or sets a string that is passed to the application when it is activated by the Toast. + /// The format and contents of this string are defined by the app for its own use. When the user + /// taps or clicks the Toast to launch its associated app, the launch string provides the context + /// to the app that allows it to show the user a view relevant to the Toast content, rather than + /// launching in its default way. + /// + public string Launch { get; set; } - if (Audio != null) - { - toast.Audio = Audio.ConvertToElement(); - } + /// + /// Gets or sets what activation type will be used when the user clicks the body of this Toast. + /// + public ToastActivationType ActivationType { get; set; } - if (Actions != null) - { - toast.Actions = ConvertToActionsElement(Actions); - } + /// + /// Gets or sets additional options relating to activation of the toast notification. Requires Creators Updated + /// + public ToastActivationOptions ActivationOptions { get; set; } + + /// + /// Gets or sets an optional custom time to use for the notification's timestamp, visible within Action Center. + /// If provided, this date/time will be used on the notification instead of the date/time that the notification was received. + /// Requires Creators Update + /// + public DateTimeOffset? DisplayTimestamp { get; set; } + + /// + /// Gets or sets an identifier used in telemetry to identify your category of toast notification. This should be something + /// like "NewMessage", "AppointmentReminder", "Promo30Off", or "PleaseRate". In the upcoming toast telemetry dashboard + /// in Dev Center, you will be able to view activation info filtered by toast identifier. + /// + public string HintToastId { get; set; } + + /// + /// Gets or sets the person that this toast is related to. For more info, see the My People documentation. New in Fall Creators Update. + /// + public ToastPeople HintPeople { get; set; } + + /// + /// Gets a dictionary where you can assign additional properties. + /// + public IDictionary AdditionalProperties { get; } = new Dictionary(); - if (Header != null) + /// + /// Retrieves the notification XML content as a string, so that it can be sent with a HTTP POST in a push notification. + /// + /// The notification XML content as a string. + public string GetContent() + { + return ConvertToElement().GetContent(); + } + + + /// + /// Retrieves the notification XML content as a WinRT XmlDocument, so that it can be used with a local Toast notification's constructor on either or . + /// + /// The notification XML content as a WinRT XmlDocument. + public XmlDocument GetXml() + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(GetContent()); + + return doc; + } + + internal Element_Toast ConvertToElement() + { + if (ActivationOptions != null) + { + if (ActivationOptions.AfterActivationBehavior != ToastAfterActivationBehavior.Default) { - toast.Header = Header.ConvertToElement(); + throw new InvalidOperationException("ToastContent does not support a custom AfterActivationBehavior. Please ensure ActivationOptions.AfterActivationBehavior is set to Default."); } + } + + DateTimeOffset? strippedDisplayTimestamp = null; + if (DisplayTimestamp != null) + { + // We need to make sure we don't include more than 3 decimal points on seconds + // The Millisecond value itself is limited to 3 decimal points, thus by doing the following + // we bypass the more granular value that can come from Ticks and ensure we only have 3 decimals at most. + var val = DisplayTimestamp.Value; + strippedDisplayTimestamp = new DateTimeOffset(val.Year, val.Month, val.Day, val.Hour, val.Minute, val.Second, val.Millisecond, val.Offset); + } - HintPeople?.PopulateToastElement(toast); + var toast = new Element_Toast() + { + ActivationType = Element_Toast.ConvertActivationType(ActivationType), + Duration = Duration, + Launch = Launch, + Scenario = Scenario, + DisplayTimestamp = strippedDisplayTimestamp, + HintToastId = HintToastId, + AdditionalProperties = (Dictionary)AdditionalProperties + }; + + ActivationOptions?.PopulateElement(toast); + + if (Visual != null) + { + toast.Visual = Visual.ConvertToElement(); + } - return toast; + if (Audio != null) + { + toast.Audio = Audio.ConvertToElement(); } - private static Element_ToastActions ConvertToActionsElement(IToastActions actions) + if (Actions != null) { - if (actions is ToastActionsCustom) - { - return (actions as ToastActionsCustom).ConvertToElement(); - } + toast.Actions = ConvertToActionsElement(Actions); + } - if (actions is ToastActionsSnoozeAndDismiss) - { - return (actions as ToastActionsSnoozeAndDismiss).ConvertToElement(); - } + if (Header != null) + { + toast.Header = Header.ConvertToElement(); + } + + HintPeople?.PopulateToastElement(toast); + + return toast; + } + + private static Element_ToastActions ConvertToActionsElement(IToastActions actions) + { + if (actions is ToastActionsCustom) + { + return (actions as ToastActionsCustom).ConvertToElement(); + } - throw new NotImplementedException("Unknown actions type: " + actions.GetType()); + if (actions is ToastActionsSnoozeAndDismiss) + { + return (actions as ToastActionsSnoozeAndDismiss).ConvertToElement(); } + + throw new NotImplementedException("Unknown actions type: " + actions.GetType()); } } diff --git a/components/Notifications/src/Toasts/ToastContextMenuItem.cs b/components/Notifications/src/Toasts/ToastContextMenuItem.cs index a98b1a9e4..a095aa89c 100644 --- a/components/Notifications/src/Toasts/ToastContextMenuItem.cs +++ b/components/Notifications/src/Toasts/ToastContextMenuItem.cs @@ -4,76 +4,75 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A Toast context menu item. +/// +public sealed class ToastContextMenuItem { /// - /// A Toast context menu item. + /// Initializes a new instance of the class. + /// A Toast context menu item with the required properties. /// - public sealed class ToastContextMenuItem + /// The text to display on the menu item. + /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the menu item. + public ToastContextMenuItem(string content, string arguments) { - /// - /// Initializes a new instance of the class. - /// A Toast context menu item with the required properties. - /// - /// The text to display on the menu item. - /// App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the menu item. - public ToastContextMenuItem(string content, string arguments) + if (content == null) { - if (content == null) - { - throw new ArgumentNullException(nameof(content)); - } - - if (arguments == null) - { - throw new ArgumentNullException(nameof(arguments)); - } + throw new ArgumentNullException(nameof(content)); + } - Content = content; - Arguments = arguments; + if (arguments == null) + { + throw new ArgumentNullException(nameof(arguments)); } - /// - /// Gets the text to display on the menu item. Required - /// - public string Content { get; private set; } + Content = content; + Arguments = arguments; + } - /// - /// Gets app-defined string of arguments that the app can later retrieve once it is activated when the user clicks the menu item. Required - /// - public string Arguments { get; private set; } + /// + /// Gets the text to display on the menu item. Required + /// + public string Content { get; private set; } + + /// + /// Gets app-defined string of arguments that the app can later retrieve once it is activated when the user clicks the menu item. Required + /// + public string Arguments { get; private set; } - /// - /// Gets or sets what type of activation this menu item will use when clicked. Defaults to Foreground. - /// - public ToastActivationType ActivationType { get; set; } = ToastActivationType.Foreground; + /// + /// Gets or sets what type of activation this menu item will use when clicked. Defaults to Foreground. + /// + public ToastActivationType ActivationType { get; set; } = ToastActivationType.Foreground; - /// - /// Gets or sets additional options relating to activation of the toast context menu item. New in Creators Update - /// - public ToastActivationOptions ActivationOptions { get; set; } + /// + /// Gets or sets additional options relating to activation of the toast context menu item. New in Creators Update + /// + public ToastActivationOptions ActivationOptions { get; set; } - /// - /// Gets or sets an identifier used in telemetry to identify your category of action. This should be something - /// like "TurnOff" or "ManageSettings". In the upcoming toast telemetry dashboard in Dev Center, you will - /// be able to view how frequently your actions are being clicked. - /// - public string HintActionId { get; set; } + /// + /// Gets or sets an identifier used in telemetry to identify your category of action. This should be something + /// like "TurnOff" or "ManageSettings". In the upcoming toast telemetry dashboard in Dev Center, you will + /// be able to view how frequently your actions are being clicked. + /// + public string HintActionId { get; set; } - internal Element_ToastAction ConvertToElement() + internal Element_ToastAction ConvertToElement() + { + var el = new Element_ToastAction { - var el = new Element_ToastAction - { - Content = Content, - Arguments = Arguments, - ActivationType = Element_Toast.ConvertActivationType(ActivationType), - Placement = Element_ToastActionPlacement.ContextMenu, - HintActionId = HintActionId - }; + Content = Content, + Arguments = Arguments, + ActivationType = Element_Toast.ConvertActivationType(ActivationType), + Placement = Element_ToastActionPlacement.ContextMenu, + HintActionId = HintActionId + }; - ActivationOptions?.PopulateElement(el); + ActivationOptions?.PopulateElement(el); - return el; - } + return el; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastGenericAppLogo.cs b/components/Notifications/src/Toasts/ToastGenericAppLogo.cs index c2c8fd0b7..43d856770 100644 --- a/components/Notifications/src/Toasts/ToastGenericAppLogo.cs +++ b/components/Notifications/src/Toasts/ToastGenericAppLogo.cs @@ -4,70 +4,69 @@ using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// The logo that is displayed on your Toast notification. +/// +public sealed class ToastGenericAppLogo : IBaseImage { /// - /// The logo that is displayed on your Toast notification. + /// Initializes a new instance of the class, + /// a logo that is displayed on your Toast notification. /// - public sealed class ToastGenericAppLogo : IBaseImage + public ToastGenericAppLogo() { - /// - /// Initializes a new instance of the class, - /// a logo that is displayed on your Toast notification. - /// - public ToastGenericAppLogo() - { - } + } - private string _source; + private string _source; - /// - /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. - /// - public string Source - { - get { return _source; } - set { BaseImageHelper.SetSource(ref _source, value); } - } + /// + /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. + /// + public string Source + { + get { return _source; } + set { BaseImageHelper.SetSource(ref _source, value); } + } - /// - /// Gets or sets a description of the image, for users of assistive technologies. - /// - public string AlternateText { get; set; } + /// + /// Gets or sets a description of the image, for users of assistive technologies. + /// + public string AlternateText { get; set; } - /// - /// Gets or sets set a value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. - /// - public bool? AddImageQuery { get; set; } + /// + /// Gets or sets set a value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. + /// + public bool? AddImageQuery { get; set; } - /// - /// Gets or sets specify how the image should be cropped. - /// - public ToastGenericAppLogoCrop HintCrop { get; set; } + /// + /// Gets or sets specify how the image should be cropped. + /// + public ToastGenericAppLogoCrop HintCrop { get; set; } - internal Element_AdaptiveImage ConvertToElement() - { - Element_AdaptiveImage el = BaseImageHelper.CreateBaseElement(this); + internal Element_AdaptiveImage ConvertToElement() + { + Element_AdaptiveImage el = BaseImageHelper.CreateBaseElement(this); - el.Placement = AdaptiveImagePlacement.AppLogoOverride; - el.Crop = GetAdaptiveImageCrop(); + el.Placement = AdaptiveImagePlacement.AppLogoOverride; + el.Crop = GetAdaptiveImageCrop(); - return el; - } + return el; + } - private AdaptiveImageCrop GetAdaptiveImageCrop() + private AdaptiveImageCrop GetAdaptiveImageCrop() + { + switch (HintCrop) { - switch (HintCrop) - { - case ToastGenericAppLogoCrop.Circle: - return AdaptiveImageCrop.Circle; + case ToastGenericAppLogoCrop.Circle: + return AdaptiveImageCrop.Circle; - case ToastGenericAppLogoCrop.None: - return AdaptiveImageCrop.None; + case ToastGenericAppLogoCrop.None: + return AdaptiveImageCrop.None; - default: - return AdaptiveImageCrop.Default; - } + default: + return AdaptiveImageCrop.Default; } } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastGenericAppLogoEnums.cs b/components/Notifications/src/Toasts/ToastGenericAppLogoEnums.cs index b8f79aa7f..77a79d30b 100644 --- a/components/Notifications/src/Toasts/ToastGenericAppLogoEnums.cs +++ b/components/Notifications/src/Toasts/ToastGenericAppLogoEnums.cs @@ -2,26 +2,25 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Specify the desired cropping of the image. +/// +public enum ToastGenericAppLogoCrop { /// - /// Specify the desired cropping of the image. + /// Cropping uses the default behavior of the renderer. /// - public enum ToastGenericAppLogoCrop - { - /// - /// Cropping uses the default behavior of the renderer. - /// - Default, + Default, - /// - /// Image is not cropped. - /// - None, + /// + /// Image is not cropped. + /// + None, - /// - /// Image is cropped to a circle shape. - /// - Circle - } + /// + /// Image is cropped to a circle shape. + /// + Circle } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastGenericAttributionText.cs b/components/Notifications/src/Toasts/ToastGenericAttributionText.cs index b3ec7d2dc..eab5f4f93 100644 --- a/components/Notifications/src/Toasts/ToastGenericAttributionText.cs +++ b/components/Notifications/src/Toasts/ToastGenericAttributionText.cs @@ -4,38 +4,37 @@ using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Defines an attribution text element to be displayed on the Toast notification. +/// +public sealed class ToastGenericAttributionText : IBaseText { /// - /// Defines an attribution text element to be displayed on the Toast notification. + /// Initializes a new instance of the class. + /// An attribution text element to be displayed on the Toast notification. + /// + public ToastGenericAttributionText() + { + } + + /// + /// Gets or sets the text to display. /// - public sealed class ToastGenericAttributionText : IBaseText + public string Text { get; set; } + + /// + /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. + /// + public string Language { get; set; } + + internal Element_AdaptiveText ConvertToElement() { - /// - /// Initializes a new instance of the class. - /// An attribution text element to be displayed on the Toast notification. - /// - public ToastGenericAttributionText() - { - } - - /// - /// Gets or sets the text to display. - /// - public string Text { get; set; } - - /// - /// Gets or sets the target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. - /// - public string Language { get; set; } - - internal Element_AdaptiveText ConvertToElement() - { - var el = BaseTextHelper.CreateBaseElement(this); - - el.Placement = AdaptiveTextPlacement.Attribution; - - return el; - } + var el = BaseTextHelper.CreateBaseElement(this); + + el.Placement = AdaptiveTextPlacement.Attribution; + + return el; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastGenericHeroImage.cs b/components/Notifications/src/Toasts/ToastGenericHeroImage.cs index adbb18809..bb4e7131e 100644 --- a/components/Notifications/src/Toasts/ToastGenericHeroImage.cs +++ b/components/Notifications/src/Toasts/ToastGenericHeroImage.cs @@ -4,49 +4,48 @@ using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A hero image for the Toast notification. +/// +public sealed class ToastGenericHeroImage : IBaseImage { /// + /// Initializes a new instance of the class. /// A hero image for the Toast notification. /// - public sealed class ToastGenericHeroImage : IBaseImage + public ToastGenericHeroImage() + { + } + + private string _source; + + /// + /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. + /// + public string Source + { + get { return _source; } + set { BaseImageHelper.SetSource(ref _source, value); } + } + + /// + /// Gets or sets a description of the image, for users of assistive technologies. + /// + public string AlternateText { get; set; } + + /// + /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. + /// + public bool? AddImageQuery { get; set; } + + internal Element_AdaptiveImage ConvertToElement() { - /// - /// Initializes a new instance of the class. - /// A hero image for the Toast notification. - /// - public ToastGenericHeroImage() - { - } - - private string _source; - - /// - /// Gets or sets the URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size. - /// - public string Source - { - get { return _source; } - set { BaseImageHelper.SetSource(ref _source, value); } - } - - /// - /// Gets or sets a description of the image, for users of assistive technologies. - /// - public string AlternateText { get; set; } - - /// - /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. - /// - public bool? AddImageQuery { get; set; } - - internal Element_AdaptiveImage ConvertToElement() - { - Element_AdaptiveImage el = BaseImageHelper.CreateBaseElement(this); - - el.Placement = AdaptiveImagePlacement.Hero; - - return el; - } + Element_AdaptiveImage el = BaseImageHelper.CreateBaseElement(this); + + el.Placement = AdaptiveImagePlacement.Hero; + + return el; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastHeader.cs b/components/Notifications/src/Toasts/ToastHeader.cs index 2f9b9dabd..d87cdeb58 100644 --- a/components/Notifications/src/Toasts/ToastHeader.cs +++ b/components/Notifications/src/Toasts/ToastHeader.cs @@ -4,113 +4,112 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Defines a visual header for the toast notification. +/// +public sealed class ToastHeader { /// - /// Defines a visual header for the toast notification. + /// Initializes a new instance of the class. + /// Constructs a toast header with all the required properties. /// - public sealed class ToastHeader + /// 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. + /// A title for the header. + /// A developer-defined string of arguments that is returned to the app when the user clicks this header. + public ToastHeader(string id, string title, string arguments) { - /// - /// Initializes a new instance of the class. - /// Constructs a toast header with all the required properties. - /// - /// 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. - /// A title for the header. - /// A developer-defined string of arguments that is returned to the app when the user clicks this header. - public ToastHeader(string id, string title, string arguments) - { - Id = id; - Title = title; - Arguments = arguments; - } + Id = id; + Title = title; + Arguments = arguments; + } - private string _id; + private string _id; - /// - /// Gets or sets 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. Cannot be null. - /// - public string Id - { - get { return _id; } - set { ArgumentValidator.SetProperty(ref _id, value, nameof(Id), ArgumentValidatorOptions.NotNull); } - } + /// + /// Gets or sets 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. Cannot be null. + /// + public string Id + { + get { return _id; } + set { ArgumentValidator.SetProperty(ref _id, value, nameof(Id), ArgumentValidatorOptions.NotNull); } + } - private string _title; + private string _title; - /// - /// Gets or sets a title for the header. Cannot be null. - /// - public string Title - { - get { return _title; } - set { ArgumentValidator.SetProperty(ref _title, value, nameof(Title), ArgumentValidatorOptions.NotNull); } - } + /// + /// Gets or sets a title for the header. Cannot be null. + /// + public string Title + { + get { return _title; } + set { ArgumentValidator.SetProperty(ref _title, value, nameof(Title), ArgumentValidatorOptions.NotNull); } + } + + private string _arguments; + + /// + /// Gets or sets a developer-defined string of arguments that is returned to the app when the user clicks this header. Cannot be null. + /// + public string Arguments + { + get { return _arguments; } + set { ArgumentValidator.SetProperty(ref _arguments, value, nameof(Arguments), ArgumentValidatorOptions.NotNull); } + } - private string _arguments; + private ToastActivationType _activationType = ToastActivationType.Foreground; - /// - /// Gets or sets a developer-defined string of arguments that is returned to the app when the user clicks this header. Cannot be null. - /// - public string Arguments + /// + /// Gets or sets the type of activation this header will use when clicked. Defaults to Foreground. Note that only Foreground and Protocol are supported. + /// + public ToastActivationType ActivationType + { + get { - get { return _arguments; } - set { ArgumentValidator.SetProperty(ref _arguments, value, nameof(Arguments), ArgumentValidatorOptions.NotNull); } + return _activationType; } - private ToastActivationType _activationType = ToastActivationType.Foreground; - - /// - /// Gets or sets the type of activation this header will use when clicked. Defaults to Foreground. Note that only Foreground and Protocol are supported. - /// - public ToastActivationType ActivationType + set { - get + switch (value) { - return _activationType; - } + case ToastActivationType.Foreground: + case ToastActivationType.Protocol: + _activationType = value; + break; - set - { - switch (value) - { - case ToastActivationType.Foreground: - case ToastActivationType.Protocol: - _activationType = value; - break; - - default: - throw new ArgumentException($"ActivationType of {value} is not supported on ToastHeader."); - } + default: + throw new ArgumentException($"ActivationType of {value} is not supported on ToastHeader."); } } + } - /// - /// Gets or sets additional options relating to activation of the toast header. New in Creators Update - /// - public ToastActivationOptions ActivationOptions { get; set; } + /// + /// Gets or sets additional options relating to activation of the toast header. New in Creators Update + /// + public ToastActivationOptions ActivationOptions { get; set; } - internal Element_ToastHeader ConvertToElement() + internal Element_ToastHeader ConvertToElement() + { + if (ActivationOptions != null) { - if (ActivationOptions != null) + if (ActivationOptions.AfterActivationBehavior != ToastAfterActivationBehavior.Default) { - if (ActivationOptions.AfterActivationBehavior != ToastAfterActivationBehavior.Default) - { - throw new InvalidOperationException("ToastHeader does not support a custom AfterActivationBehavior. Please ensure ActivationOptions.AfterActivationBehavior is set to Default."); - } + throw new InvalidOperationException("ToastHeader does not support a custom AfterActivationBehavior. Please ensure ActivationOptions.AfterActivationBehavior is set to Default."); } + } - var el = new Element_ToastHeader() - { - Id = Id, - Title = Title, - Arguments = Arguments, - ActivationType = Element_Toast.ConvertActivationType(ActivationType) - }; + var el = new Element_ToastHeader() + { + Id = Id, + Title = Title, + Arguments = Arguments, + ActivationType = Element_Toast.ConvertActivationType(ActivationType) + }; - ActivationOptions?.PopulateElement(el); + ActivationOptions?.PopulateElement(el); - return el; - } + return el; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastPeople.cs b/components/Notifications/src/Toasts/ToastPeople.cs index 3c24740b4..425a306f9 100644 --- a/components/Notifications/src/Toasts/ToastPeople.cs +++ b/components/Notifications/src/Toasts/ToastPeople.cs @@ -2,55 +2,54 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Specify what person this toast is related to. For more info, see the My People documentation. New in Fall Creators Update. +/// +public sealed class ToastPeople { /// - /// Specify what person this toast is related to. For more info, see the My People documentation. New in Fall Creators Update. + /// Gets or sets a remote identifier that corresponds with the RemoteId you set on a Contact you created + /// with the ContactStore APIs. For more info, see the My People documentation. /// - public sealed class ToastPeople - { - /// - /// Gets or sets a remote identifier that corresponds with the RemoteId you set on a Contact you created - /// with the ContactStore APIs. For more info, see the My People documentation. - /// - public string RemoteId { get; set; } - - /// - /// Gets or sets an email address that corresponds with a contact in the local Windows ContactStore. Note - /// that if is specified, this property will be ignored. For more info, - /// see the My People documentation. - /// - public string EmailAddress { get; set; } + public string RemoteId { get; set; } - /// - /// Gets or sets a phone number that corresponds with a contact in the local Windows ContactStore. Note - /// that if is specified, this property will be ignored. - /// For more info, see the My People documentation. - /// - public string PhoneNumber { get; set; } + /// + /// Gets or sets an email address that corresponds with a contact in the local Windows ContactStore. Note + /// that if is specified, this property will be ignored. For more info, + /// see the My People documentation. + /// + public string EmailAddress { get; set; } - internal void PopulateToastElement(Element_Toast toast) - { - string hintPeople; + /// + /// Gets or sets a phone number that corresponds with a contact in the local Windows ContactStore. Note + /// that if is specified, this property will be ignored. + /// For more info, see the My People documentation. + /// + public string PhoneNumber { get; set; } - if (RemoteId != null) - { - hintPeople = "remoteid:" + RemoteId; - } - else if (EmailAddress != null) - { - hintPeople = "mailto:" + EmailAddress; - } - else if (PhoneNumber != null) - { - hintPeople = "tel:" + PhoneNumber; - } - else - { - return; - } + internal void PopulateToastElement(Element_Toast toast) + { + string hintPeople; - toast.HintPeople = hintPeople; + if (RemoteId != null) + { + hintPeople = "remoteid:" + RemoteId; + } + else if (EmailAddress != null) + { + hintPeople = "mailto:" + EmailAddress; + } + else if (PhoneNumber != null) + { + hintPeople = "tel:" + PhoneNumber; + } + else + { + return; } + + toast.HintPeople = hintPeople; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastSelectionBox.cs b/components/Notifications/src/Toasts/ToastSelectionBox.cs index 40d110057..6ddb32b4e 100644 --- a/components/Notifications/src/Toasts/ToastSelectionBox.cs +++ b/components/Notifications/src/Toasts/ToastSelectionBox.cs @@ -5,59 +5,58 @@ using System; using System.Collections.Generic; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A selection box control, which lets users pick from a dropdown list of options. +/// +public sealed class ToastSelectionBox : IToastInput { /// - /// A selection box control, which lets users pick from a dropdown list of options. + /// Initializes a new instance of the class. + /// A Toast SelectionBox input control with the required elements. /// - public sealed class ToastSelectionBox : IToastInput + /// Developer-provided ID that the developer uses later to retrieve input when the Toast is interacted with. + public ToastSelectionBox(string id) { - /// - /// Initializes a new instance of the class. - /// A Toast SelectionBox input control with the required elements. - /// - /// Developer-provided ID that the developer uses later to retrieve input when the Toast is interacted with. - public ToastSelectionBox(string id) - { - Id = id ?? throw new ArgumentNullException(nameof(id)); - } + Id = id ?? throw new ArgumentNullException(nameof(id)); + } - /// - /// Gets the required ID property used so that developers can retrieve user input once the app is activated. - /// - public string Id { get; private set; } + /// + /// Gets the required ID property used so that developers can retrieve user input once the app is activated. + /// + public string Id { get; private set; } + + /// + /// Gets or sets title text to display above the SelectionBox. + /// + public string Title { get; set; } - /// - /// Gets or sets title text to display above the SelectionBox. - /// - public string Title { get; set; } + /// + /// Gets or sets which item is selected by default, and refers to the Id property of . If you do not provide this, the default selection will be empty (user sees nothing). + /// + public string DefaultSelectionBoxItemId { get; set; } - /// - /// Gets or sets which item is selected by default, and refers to the Id property of . If you do not provide this, the default selection will be empty (user sees nothing). - /// - public string DefaultSelectionBoxItemId { get; set; } + /// + /// Gets the selection items that the user can pick from in this SelectionBox. Only 5 items can be added. + /// + public IList Items { get; private set; } = new LimitedList(5); - /// - /// Gets the selection items that the user can pick from in this SelectionBox. Only 5 items can be added. - /// - public IList Items { get; private set; } = new LimitedList(5); + internal Element_ToastInput ConvertToElement() + { + var input = new Element_ToastInput() + { + Type = ToastInputType.Selection, + Id = Id, + DefaultInput = DefaultSelectionBoxItemId, + Title = Title + }; - internal Element_ToastInput ConvertToElement() + foreach (var item in Items) { - var input = new Element_ToastInput() - { - Type = ToastInputType.Selection, - Id = Id, - DefaultInput = DefaultSelectionBoxItemId, - Title = Title - }; - - foreach (var item in Items) - { - input.Children.Add(item.ConvertToElement()); - } - - return input; + input.Children.Add(item.ConvertToElement()); } + + return input; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastSelectionBoxItem.cs b/components/Notifications/src/Toasts/ToastSelectionBoxItem.cs index 225a4f7ab..d013743b2 100644 --- a/components/Notifications/src/Toasts/ToastSelectionBoxItem.cs +++ b/components/Notifications/src/Toasts/ToastSelectionBoxItem.cs @@ -4,42 +4,41 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A selection box item (an item that the user can select from the drop down list). +/// +public sealed class ToastSelectionBoxItem { /// - /// A selection box item (an item that the user can select from the drop down list). + /// Initializes a new instance of the class. + /// Constructs a new Toast SelectionBoxItem with the required elements. /// - public sealed class ToastSelectionBoxItem + /// Developer-provided ID that the developer uses later to retrieve input when the Toast is interacted with. + /// String that is displayed on the selection item. This is what the user sees. + public ToastSelectionBoxItem(string id, string content) { - /// - /// Initializes a new instance of the class. - /// Constructs a new Toast SelectionBoxItem with the required elements. - /// - /// Developer-provided ID that the developer uses later to retrieve input when the Toast is interacted with. - /// String that is displayed on the selection item. This is what the user sees. - public ToastSelectionBoxItem(string id, string content) - { - Id = id ?? throw new ArgumentNullException(nameof(id)); - Content = content ?? throw new ArgumentNullException(nameof(content)); - } + Id = id ?? throw new ArgumentNullException(nameof(id)); + Content = content ?? throw new ArgumentNullException(nameof(content)); + } - /// - /// Gets the required ID property used so that developers can retrieve user input once the app is activated. - /// - public string Id { get; private set; } + /// + /// Gets the required ID property used so that developers can retrieve user input once the app is activated. + /// + public string Id { get; private set; } - /// - /// Gets the required string that is displayed on the selection item. - /// - public string Content { get; private set; } + /// + /// Gets the required string that is displayed on the selection item. + /// + public string Content { get; private set; } - internal Element_ToastSelection ConvertToElement() + internal Element_ToastSelection ConvertToElement() + { + return new Element_ToastSelection() { - return new Element_ToastSelection() - { - Id = Id, - Content = Content - }; - } + Id = Id, + Content = Content + }; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastShoulderTapImage.cs b/components/Notifications/src/Toasts/ToastShoulderTapImage.cs index 58a4e2a52..b6e442841 100644 --- a/components/Notifications/src/Toasts/ToastShoulderTapImage.cs +++ b/components/Notifications/src/Toasts/ToastShoulderTapImage.cs @@ -4,54 +4,53 @@ using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Specifies the image to be displayed on a My People shoulder tap notification. New in Fall Creators Update. +/// +public sealed class ToastShoulderTapImage : IBaseImage { + private string _source; + /// - /// Specifies the image to be displayed on a My People shoulder tap notification. New in Fall Creators Update. + /// Gets or sets the URI of the image (Required). This will be used if the sprite sheet isn't provided, or + /// if the sprite sheet cannot be loaded. Can be from your application package, application data, or the internet. + /// Internet images must obey the toast image size restrictions. /// - public sealed class ToastShoulderTapImage : IBaseImage + public string Source { - private string _source; - - /// - /// Gets or sets the URI of the image (Required). This will be used if the sprite sheet isn't provided, or - /// if the sprite sheet cannot be loaded. Can be from your application package, application data, or the internet. - /// Internet images must obey the toast image size restrictions. - /// - public string Source - { - get { return _source; } - set { BaseImageHelper.SetSource(ref _source, value); } - } + get { return _source; } + set { BaseImageHelper.SetSource(ref _source, value); } + } - /// - /// Gets or sets an optional sprite sheet that can be used instead of the image to display an animated sprite sheet. - /// - public ToastSpriteSheet SpriteSheet { get; set; } - - /// - /// Gets or sets a description of the image, for users of assistive technologies. - /// - public string AlternateText { get; set; } - - /// - /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the property. - /// Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the - /// query strings or by ignoring the query string and returning the image as specified without the query string. - /// This query string specifies scale, contrast setting, and language. - /// - public bool? AddImageQuery { get; set; } - - internal Element_AdaptiveImage ConvertToElement() - { - Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this); + /// + /// Gets or sets an optional sprite sheet that can be used instead of the image to display an animated sprite sheet. + /// + public ToastSpriteSheet SpriteSheet { get; set; } - if (SpriteSheet != null) - { - SpriteSheet.PopulateImageElement(image); - } + /// + /// Gets or sets a description of the image, for users of assistive technologies. + /// + public string AlternateText { get; set; } + + /// + /// Gets or sets a value whether Windows should append a query string to the image URI supplied in the property. + /// Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the + /// query strings or by ignoring the query string and returning the image as specified without the query string. + /// This query string specifies scale, contrast setting, and language. + /// + public bool? AddImageQuery { get; set; } - return image; + internal Element_AdaptiveImage ConvertToElement() + { + Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this); + + if (SpriteSheet != null) + { + SpriteSheet.PopulateImageElement(image); } + + return image; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastSpriteSheet.cs b/components/Notifications/src/Toasts/ToastSpriteSheet.cs index b8e0941f9..2a98d64ab 100644 --- a/components/Notifications/src/Toasts/ToastSpriteSheet.cs +++ b/components/Notifications/src/Toasts/ToastSpriteSheet.cs @@ -5,52 +5,51 @@ using System; using CommunityToolkit.Notifications.Adaptive.Elements; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Specifies a sprite sheet. New in Fall Creators Update. +/// +public sealed class ToastSpriteSheet { + private string _source; + /// - /// Specifies a sprite sheet. New in Fall Creators Update. + /// Gets or sets the URI of the sprite sheet (Required). + /// Can be from your application package, application data, or the internet. + /// Internet sources must obey the toast image size restrictions. /// - public sealed class ToastSpriteSheet + public string Source { - private string _source; - - /// - /// Gets or sets the URI of the sprite sheet (Required). - /// Can be from your application package, application data, or the internet. - /// Internet sources must obey the toast image size restrictions. - /// - public string Source - { - get { return _source; } - set { BaseImageHelper.SetSource(ref _source, value); } - } + get { return _source; } + set { BaseImageHelper.SetSource(ref _source, value); } + } - /// - /// Gets or sets the frame-height of the sprite sheet. Required value that must be greater than 0. - /// - public uint? FrameHeight { get; set; } + /// + /// Gets or sets the frame-height of the sprite sheet. Required value that must be greater than 0. + /// + public uint? FrameHeight { get; set; } - /// - /// Gets or sets the frames per second at which to animate the sprite sheet. Required value that must be greater than 0 but no larger than 120. - /// - public uint? Fps { get; set; } + /// + /// Gets or sets the frames per second at which to animate the sprite sheet. Required value that must be greater than 0 but no larger than 120. + /// + public uint? Fps { get; set; } - /// - /// Gets or sets the starting frame of the sprite sheet. If not specified, it will start at frame zero. - /// - public uint? StartingFrame { get; set; } + /// + /// Gets or sets the starting frame of the sprite sheet. If not specified, it will start at frame zero. + /// + public uint? StartingFrame { get; set; } - internal void PopulateImageElement(Element_AdaptiveImage image) + internal void PopulateImageElement(Element_AdaptiveImage image) + { + if (Source == null) { - if (Source == null) - { - throw new NullReferenceException("Source cannot be null on ToastSpriteSheet"); - } - - image.SpriteSheetSrc = Source; - image.SpriteSheetHeight = FrameHeight; - image.SpriteSheetFps = Fps; - image.SpriteSheetStartingFrame = StartingFrame; + throw new NullReferenceException("Source cannot be null on ToastSpriteSheet"); } + + image.SpriteSheetSrc = Source; + image.SpriteSheetHeight = FrameHeight; + image.SpriteSheetFps = Fps; + image.SpriteSheetStartingFrame = StartingFrame; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastTextBox.cs b/components/Notifications/src/Toasts/ToastTextBox.cs index 432b75e70..3fce8f0a6 100644 --- a/components/Notifications/src/Toasts/ToastTextBox.cs +++ b/components/Notifications/src/Toasts/ToastTextBox.cs @@ -4,53 +4,52 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// A text box control on the Toast that a user can type text into. +/// +public sealed class ToastTextBox : IToastInput { /// - /// A text box control on the Toast that a user can type text into. + /// Initializes a new instance of the class. + /// A new Toast TextBox input control with the required elements. /// - public sealed class ToastTextBox : IToastInput + /// Developer-provided ID that the developer uses later to retrieve input when the Toast is interacted with. + public ToastTextBox(string id) { - /// - /// Initializes a new instance of the class. - /// A new Toast TextBox input control with the required elements. - /// - /// Developer-provided ID that the developer uses later to retrieve input when the Toast is interacted with. - public ToastTextBox(string id) - { - Id = id ?? throw new ArgumentNullException(nameof(id)); - } - - /// - /// Gets the required ID property so that developers can retrieve user input once the app is activated. - /// - public string Id { get; private set; } - - /// - /// Gets or sets title text to display above the text box. - /// - public string Title { get; set; } - - /// - /// Gets or sets placeholder text to be displayed on the text box when the user hasn't typed any text yet. - /// - public string PlaceholderContent { get; set; } - - /// - /// Gets or sets the initial text to place in the text box. Leave this null for a blank text box. - /// - public string DefaultInput { get; set; } - - internal Element_ToastInput ConvertToElement() + Id = id ?? throw new ArgumentNullException(nameof(id)); + } + + /// + /// Gets the required ID property so that developers can retrieve user input once the app is activated. + /// + public string Id { get; private set; } + + /// + /// Gets or sets title text to display above the text box. + /// + public string Title { get; set; } + + /// + /// Gets or sets placeholder text to be displayed on the text box when the user hasn't typed any text yet. + /// + public string PlaceholderContent { get; set; } + + /// + /// Gets or sets the initial text to place in the text box. Leave this null for a blank text box. + /// + public string DefaultInput { get; set; } + + internal Element_ToastInput ConvertToElement() + { + return new Element_ToastInput() { - return new Element_ToastInput() - { - Id = Id, - Type = ToastInputType.Text, - DefaultInput = DefaultInput, - PlaceholderContent = PlaceholderContent, - Title = Title - }; - } + Id = Id, + Type = ToastInputType.Text, + DefaultInput = DefaultInput, + PlaceholderContent = PlaceholderContent, + Title = Title + }; } } \ No newline at end of file diff --git a/components/Notifications/src/Toasts/ToastVisual.cs b/components/Notifications/src/Toasts/ToastVisual.cs index f6f349783..fe6c24725 100644 --- a/components/Notifications/src/Toasts/ToastVisual.cs +++ b/components/Notifications/src/Toasts/ToastVisual.cs @@ -4,63 +4,62 @@ using System; -namespace CommunityToolkit.Notifications +namespace CommunityToolkit.Notifications; + +/// +/// Defines the visual aspects of a Toast notification. +/// +public sealed class ToastVisual { /// - /// Defines the visual aspects of a Toast notification. + /// Gets or sets the target locale of the XML payload, specified as BCP-47 language tags such as "en-US" or "fr-FR". This locale is overridden by any locale specified in binding or text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. /// - public sealed class ToastVisual - { - /// - /// Gets or sets the target locale of the XML payload, specified as BCP-47 language tags such as "en-US" or "fr-FR". This locale is overridden by any locale specified in binding or text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. - /// - public string Language { get; set; } + public string Language { get; set; } - /// - /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. - /// - public Uri BaseUri { get; set; } + /// + /// Gets or sets a default base URI that is combined with relative URIs in image source attributes. + /// + public Uri BaseUri { get; set; } - /// - /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Toast notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. - /// - public bool? AddImageQuery { get; set; } + /// + /// Gets or sets a value whether Windows is allowed to append a query string to the image URI supplied in the Toast notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language. + /// + public bool? AddImageQuery { get; set; } - /// - /// Gets or sets the generic Toast binding, which can be rendered on all devices. This binding is required and cannot be null. - /// - public ToastBindingGeneric BindingGeneric { get; set; } + /// + /// Gets or sets the generic Toast binding, which can be rendered on all devices. This binding is required and cannot be null. + /// + public ToastBindingGeneric BindingGeneric { get; set; } - /// - /// Gets or sets a binding for shoulder tap notifications, which integrate with My People. See the My People documentation for more info. New in Fall Creators Update. - /// - public ToastBindingShoulderTap BindingShoulderTap { get; set; } + /// + /// Gets or sets a binding for shoulder tap notifications, which integrate with My People. See the My People documentation for more info. New in Fall Creators Update. + /// + public ToastBindingShoulderTap BindingShoulderTap { get; set; } - internal Element_ToastVisual ConvertToElement() + internal Element_ToastVisual ConvertToElement() + { + var visual = new Element_ToastVisual() { - var visual = new Element_ToastVisual() - { - Language = Language, - BaseUri = BaseUri, - AddImageQuery = AddImageQuery - }; - - if (BindingGeneric == null) - { - throw new NullReferenceException("BindingGeneric must be initialized"); - } + Language = Language, + BaseUri = BaseUri, + AddImageQuery = AddImageQuery + }; - Element_ToastBinding binding = BindingGeneric.ConvertToElement(); + if (BindingGeneric == null) + { + throw new NullReferenceException("BindingGeneric must be initialized"); + } - // TODO: If a BaseUri wasn't provided, we can potentially optimize the payload size by calculating the best BaseUri - visual.Bindings.Add(binding); + Element_ToastBinding binding = BindingGeneric.ConvertToElement(); - if (BindingShoulderTap != null) - { - visual.Bindings.Add(BindingShoulderTap.ConvertToElement()); - } + // TODO: If a BaseUri wasn't provided, we can potentially optimize the payload size by calculating the best BaseUri + visual.Bindings.Add(binding); - return visual; + if (BindingShoulderTap != null) + { + visual.Bindings.Add(BindingShoulderTap.ConvertToElement()); } + + return visual; } } \ No newline at end of file diff --git a/components/Notifications/tests/TestAssertHelper.cs b/components/Notifications/tests/TestAssertHelper.cs index aaef76806..3110b2f65 100644 --- a/components/Notifications/tests/TestAssertHelper.cs +++ b/components/Notifications/tests/TestAssertHelper.cs @@ -13,440 +13,439 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; #nullable disable -namespace NotificationsExperiment.Tests +namespace NotificationsExperiment.Tests; + +[TestClass] +public class TestAssertHelper { - [TestClass] - public class TestAssertHelper + [TestMethod] + public void TestAssertXmlElement() + { + AssertHelper.AssertXml(" Hello world", " Hello world "); + } + + [TestMethod] + public void TestAssertXmlElement_002() { - [TestMethod] - public void TestAssertXmlElement() + try { - AssertHelper.AssertXml(" Hello world", " Hello world "); + AssertHelper.AssertXml(" Hello world", " Hello world "); } - - [TestMethod] - public void TestAssertXmlElement_002() + catch { - try - { - AssertHelper.AssertXml(" Hello world", " Hello world "); - } - catch - { - return; - } - - Assert.Fail("tile element name was different, should have thrown exception"); + return; } - [TestMethod] - public void TestAssertXmlElement_003() - { - try - { - AssertHelper.AssertXml(" Hello world", " Hello world "); - } - catch - { - return; - } + Assert.Fail("tile element name was different, should have thrown exception"); + } - Assert.Fail("visual element name was incorrect, should have thrown exception"); + [TestMethod] + public void TestAssertXmlElement_003() + { + try + { + AssertHelper.AssertXml(" Hello world", " Hello world "); } - - [TestMethod] - public void TestAssertXmlElement_004() + catch { - try - { - AssertHelper.AssertXml(" Hello world", " Hello world "); - } - catch - { - return; - } - - Assert.Fail("visual version number was incorrect, should have thrown exception"); + return; } - [TestMethod] - public void TestAssertXmlElement_005() - { - try - { - AssertHelper.AssertXml(" Hello world", " Hello world! "); - } - catch - { - return; - } + Assert.Fail("visual element name was incorrect, should have thrown exception"); + } - Assert.Fail("text content was different, should have thrown exception"); + [TestMethod] + public void TestAssertXmlElement_004() + { + try + { + AssertHelper.AssertXml(" Hello world", " Hello world "); } - - [TestMethod] - public void TestAssertXmlElement_006() + catch { - AssertHelper.AssertXml("", ""); + return; } - [TestMethod] - public void TestAssertXmlElement_006_1() - { - try - { - AssertHelper.AssertXml("", ""); - } - catch - { - return; - } + Assert.Fail("visual version number was incorrect, should have thrown exception"); + } - Assert.Fail("Version number was incorrect, should have thrown exception."); + [TestMethod] + public void TestAssertXmlElement_005() + { + try + { + AssertHelper.AssertXml(" Hello world", " Hello world! "); } - - [TestMethod] - public void TestAssertXmlElement_006_2() + catch { - try - { - AssertHelper.AssertXml("", ""); - } - catch - { - return; - } - - Assert.Fail("ID number was incorrect, should have thrown exception."); + return; } - [TestMethod] - public void TestAssertXmlElement_007() + Assert.Fail("text content was different, should have thrown exception"); + } + + [TestMethod] + public void TestAssertXmlElement_006() + { + AssertHelper.AssertXml("", ""); + } + + [TestMethod] + public void TestAssertXmlElement_006_1() + { + try { - AssertHelper.AssertXml("", ""); + AssertHelper.AssertXml("", ""); } - - [TestMethod] - public void TestAssertXmlElement_008() + catch { - AssertHelper.AssertXml("", ""); + return; + } - try - { - AssertHelper.AssertXml("", ""); - } - catch - { - return; - } + Assert.Fail("Version number was incorrect, should have thrown exception."); + } - Assert.Fail("Visual element was missing, should have thrown exception"); + [TestMethod] + public void TestAssertXmlElement_006_2() + { + try + { + AssertHelper.AssertXml("", ""); } - - [TestMethod] - public void TestAssertXmlElement_009() + catch { - AssertHelper.AssertXml("", ""); + return; + } - try - { - AssertHelper.AssertXml("", ""); - } - catch - { - return; - } + Assert.Fail("ID number was incorrect, should have thrown exception."); + } - Assert.Fail("Child elements were different order, should have thrown exception"); - } + [TestMethod] + public void TestAssertXmlElement_007() + { + AssertHelper.AssertXml("", ""); + } - [TestMethod] - public void TestAssertXmlElement_010() + [TestMethod] + public void TestAssertXmlElement_008() + { + AssertHelper.AssertXml("", ""); + + try { - try - { - AssertHelper.AssertXml("", ""); - } - catch - { - return; - } + AssertHelper.AssertXml("", ""); + } + catch + { + return; + } + + Assert.Fail("Visual element was missing, should have thrown exception"); + } + + [TestMethod] + public void TestAssertXmlElement_009() + { + AssertHelper.AssertXml("", ""); - Assert.Fail("id attribute value wasn't the same, should have thrown exception"); + try + { + AssertHelper.AssertXml("", ""); + } + catch + { + return; } - [TestMethod] - public void TestAssertXmlElement_011() + Assert.Fail("Child elements were different order, should have thrown exception"); + } + + [TestMethod] + public void TestAssertXmlElement_010() + { + try { - try - { - AssertHelper.AssertXml("", ""); - } - catch - { - return; - } + AssertHelper.AssertXml("", ""); + } + catch + { + return; + } + + Assert.Fail("id attribute value wasn't the same, should have thrown exception"); + } - Assert.Fail("id attribute was missing, should have thrown exception"); + [TestMethod] + public void TestAssertXmlElement_011() + { + try + { + AssertHelper.AssertXml("", ""); + } + catch + { + return; } + + Assert.Fail("id attribute was missing, should have thrown exception"); } +} #pragma warning disable SA1204 // Static elements should appear before instance elements #pragma warning disable SA1402 // File may only contain a single type - public static class AssertHelper +public static class AssertHelper #pragma warning restore SA1402 // File may only contain a single type #pragma warning restore SA1204 // Static elements should appear before instance elements +{ + private class XmlElementHelper { - private class XmlElementHelper - { - } + } - /* - public static void AssertXml(string expected, string actual) - { - XmlDocument expectedDoc = new XmlDocument(); - expectedDoc.LoadXml(expected); + /* + public static void AssertXml(string expected, string actual) + { + XmlDocument expectedDoc = new XmlDocument(); + expectedDoc.LoadXml(expected); - XmlDocument actualDoc = new XmlDocument(); - actualDoc.LoadXml(actual); + XmlDocument actualDoc = new XmlDocument(); + actualDoc.LoadXml(actual); - AssertXmlElement(expectedDoc.DocumentElement, actualDoc.DocumentElement); - } + AssertXmlElement(expectedDoc.DocumentElement, actualDoc.DocumentElement); + } - private static void AssertXmlElement(XmlElement expected, XmlElement actual) - { - // If both null, good, done - if (expected == null && actual == null) - return; + private static void AssertXmlElement(XmlElement expected, XmlElement actual) + { + // If both null, good, done + if (expected == null && actual == null) + return; - // If one is null and other isn't, bad - if (expected == null) - Assert.Fail("Expected XML element was null, while actual was initialized"); + // If one is null and other isn't, bad + if (expected == null) + Assert.Fail("Expected XML element was null, while actual was initialized"); - if (actual == null) - Assert.Fail("Actual XML element was null, while expected was initialized"); + if (actual == null) + Assert.Fail("Actual XML element was null, while expected was initialized"); - // If name doesn't match - Assert.AreEqual(expected.Name, actual.Name, "Element names did not match."); + // If name doesn't match + Assert.AreEqual(expected.Name, actual.Name, "Element names did not match."); - // If attribute count doesn't match - Assert.AreEqual(expected.Attributes.Count, actual.Attributes.Count, "Element attributes counts didn't match"); + // If attribute count doesn't match + Assert.AreEqual(expected.Attributes.Count, actual.Attributes.Count, "Element attributes counts didn't match"); - // Make sure attributes match (order does NOT matter) - foreach (XmlAttribute expectedAttr in expected.Attributes) - { - var actualAttr = actual.Attributes.GetNamedItem(expectedAttr.Name); + // Make sure attributes match (order does NOT matter) + foreach (XmlAttribute expectedAttr in expected.Attributes) + { + var actualAttr = actual.Attributes.GetNamedItem(expectedAttr.Name); - // If didn't find the attribute - if (actualAttr == null) - Assert.Fail("Expected element to have attribute " + expectedAttr.Name + " but it didn't."); + // If didn't find the attribute + if (actualAttr == null) + Assert.Fail("Expected element to have attribute " + expectedAttr.Name + " but it didn't."); - // Make sure value matches - Assert.AreEqual(expectedAttr.Value, actualAttr.Value, $@"Attribute values for ""{expectedAttr.Name}"" didn't match."); - } + // Make sure value matches + Assert.AreEqual(expectedAttr.Value, actualAttr.Value, $@"Attribute values for ""{expectedAttr.Name}"" didn't match."); + } - // Make sure children elements match (order DOES matter) + // Make sure children elements match (order DOES matter) - // Obtain the child elements (ignore any comments, w - XmlElement[] expectedChildren = expected.ChildNodes.OfType().ToArray(); - XmlElement[] actualChildren = actual.ChildNodes.OfType().ToArray(); + // Obtain the child elements (ignore any comments, w + XmlElement[] expectedChildren = expected.ChildNodes.OfType().ToArray(); + XmlElement[] actualChildren = actual.ChildNodes.OfType().ToArray(); - Assert.AreEqual(expectedChildren.Length, actualChildren.Length, "Number of child elements did not match."); + Assert.AreEqual(expectedChildren.Length, actualChildren.Length, "Number of child elements did not match."); - // If no elements, compare inner text - if (expectedChildren.Length == 0) - { - Assert.AreEqual(expected.InnerText, actual.InnerText, "Inner text did not match."); - } + // If no elements, compare inner text + if (expectedChildren.Length == 0) + { + Assert.AreEqual(expected.InnerText, actual.InnerText, "Inner text did not match."); + } - // Otherwise compare elements - else + // Otherwise compare elements + else + { + for (int i = 0; i < expectedChildren.Length; i++) { - for (int i = 0; i < expectedChildren.Length; i++) - { - AssertXmlElement(expectedChildren[i], actualChildren[i]); - } + AssertXmlElement(expectedChildren[i], actualChildren[i]); } } - */ + } + */ - public static void AssertToast(string expected, ToastContent toast) - { - AssertHelper.AssertXml(expected.ToLower(), toast.GetContent().ToLower()); + public static void AssertToast(string expected, ToastContent toast) + { + AssertHelper.AssertXml(expected.ToLower(), toast.GetContent().ToLower()); - AssertHelper.AssertXml(expected, toast.GetXml().GetXml()); - } + AssertHelper.AssertXml(expected, toast.GetXml().GetXml()); + } - public static void AssertTile(string expected, TileContent tile) - { - AssertHelper.AssertXml(expected.ToLower(), tile.GetContent().ToLower()); + public static void AssertTile(string expected, TileContent tile) + { + AssertHelper.AssertXml(expected.ToLower(), tile.GetContent().ToLower()); - AssertHelper.AssertXml(expected, tile.GetXml().GetXml()); - } + AssertHelper.AssertXml(expected, tile.GetXml().GetXml()); + } - public static void AssertXml(string expected, string actual) - { - MyXmlElement expectedEl = ParseXml(expected); - MyXmlElement actualEl = ParseXml(actual); + public static void AssertXml(string expected, string actual) + { + MyXmlElement expectedEl = ParseXml(expected); + MyXmlElement actualEl = ParseXml(actual); - AssertXmlElement(expectedEl, actualEl); - } + AssertXmlElement(expectedEl, actualEl); + } - private static string AttributesToString(IEnumerable attributes) + private static string AttributesToString(IEnumerable attributes) + { + return string.Join(", ", attributes.Select(i => i.Name)); + } + + private static void AssertXmlElement(MyXmlElement expected, MyXmlElement actual) + { + // If both null, good, done + if (expected == null && actual == null) { - return string.Join(", ", attributes.Select(i => i.Name)); + return; } - private static void AssertXmlElement(MyXmlElement expected, MyXmlElement actual) + // If one is null and other isn't, bad + if (expected == null) { - // If both null, good, done - if (expected == null && actual == null) - { - return; - } + Assert.Fail("Expected XML element was null, while actual was initialized"); + } - // If one is null and other isn't, bad - if (expected == null) - { - Assert.Fail("Expected XML element was null, while actual was initialized"); - } + if (actual == null) + { + Assert.Fail("Actual XML element was null, while expected was initialized"); + } - if (actual == null) - { - Assert.Fail("Actual XML element was null, while expected was initialized"); - } + // If name doesn't match + Assert.AreEqual(expected.Name.ToLower(), actual.Name.ToLower(), "Element names did not match."); - // If name doesn't match - Assert.AreEqual(expected.Name.ToLower(), actual.Name.ToLower(), "Element names did not match."); + // If attribute count doesn't match + Assert.AreEqual(expected.Attributes.Count, actual.Attributes.Count, $"Different number of attributes on <{expected.Name}>\n\nExpected: " + AttributesToString(expected.Attributes) + "\nActual: " + AttributesToString(actual.Attributes)); - // If attribute count doesn't match - Assert.AreEqual(expected.Attributes.Count, actual.Attributes.Count, $"Different number of attributes on <{expected.Name}>\n\nExpected: " + AttributesToString(expected.Attributes) + "\nActual: " + AttributesToString(actual.Attributes)); + // Make sure attributes match (order does NOT matter) + foreach (MyXmlAttribute expectedAttr in expected.Attributes) + { + var actualAttr = actual.Attributes.FirstOrDefault(i => i.Name.Equals(expectedAttr.Name)); - // Make sure attributes match (order does NOT matter) - foreach (MyXmlAttribute expectedAttr in expected.Attributes) + // If didn't find the attribute + if (actualAttr == null) { - var actualAttr = actual.Attributes.FirstOrDefault(i => i.Name.Equals(expectedAttr.Name)); - - // If didn't find the attribute - if (actualAttr == null) - { - Assert.Fail("Expected element to have attribute " + expectedAttr.Name + " but it didn't."); - } - - // Make sure value matches - Assert.AreEqual(expectedAttr.Value.ToLower(), actualAttr.Value.ToLower(), $@"Attribute values for ""{expectedAttr.Name}"" didn't match."); + Assert.Fail("Expected element to have attribute " + expectedAttr.Name + " but it didn't."); } - // Make sure children elements match (order DOES matter) + // Make sure value matches + Assert.AreEqual(expectedAttr.Value.ToLower(), actualAttr.Value.ToLower(), $@"Attribute values for ""{expectedAttr.Name}"" didn't match."); + } - // Obtain the child elements (ignore any comments, w - MyXmlElement[] expectedChildren = expected.ChildNodes.ToArray(); - MyXmlElement[] actualChildren = actual.ChildNodes.ToArray(); + // Make sure children elements match (order DOES matter) - Assert.AreEqual(expectedChildren.Length, actualChildren.Length, "Number of child elements did not match."); + // Obtain the child elements (ignore any comments, w + MyXmlElement[] expectedChildren = expected.ChildNodes.ToArray(); + MyXmlElement[] actualChildren = actual.ChildNodes.ToArray(); - // Compare elements - for (int i = 0; i < expectedChildren.Length; i++) - { - AssertXmlElement(expectedChildren[i], actualChildren[i]); - } - } + Assert.AreEqual(expectedChildren.Length, actualChildren.Length, "Number of child elements did not match."); - private class MyXmlElement + // Compare elements + for (int i = 0; i < expectedChildren.Length; i++) { - public string Name { get; set; } + AssertXmlElement(expectedChildren[i], actualChildren[i]); + } + } - public List ChildNodes { get; private set; } = new List(); + private class MyXmlElement + { + public string Name { get; set; } - public List Attributes { get; private set; } = new List(); - } + public List ChildNodes { get; private set; } = new List(); - private class MyXmlAttribute - { - public string Name { get; set; } + public List Attributes { get; private set; } = new List(); + } - public string Value { get; set; } - } + private class MyXmlAttribute + { + public string Name { get; set; } - private static MyXmlElement ParseXml(string xml) - { - XmlReader reader = XmlReader.Create(new StringReader(xml)); + public string Value { get; set; } + } - MyXmlElement documentElement = new MyXmlElement(); + private static MyXmlElement ParseXml(string xml) + { + XmlReader reader = XmlReader.Create(new StringReader(xml)); - reader.Read(); + MyXmlElement documentElement = new MyXmlElement(); - while (true) - { - if (reader.ReadState == ReadState.EndOfFile) - { - break; - } + reader.Read(); - if (reader.ReadState == ReadState.Error) - { - throw new Exception("ReadState was Error"); - } + while (true) + { + if (reader.ReadState == ReadState.EndOfFile) + { + break; + } - if (reader.NodeType == XmlNodeType.Element) - { - PopulateElement(reader, documentElement); - ParseXml(reader, documentElement); - break; - } + if (reader.ReadState == ReadState.Error) + { + throw new Exception("ReadState was Error"); + } - reader.Read(); + if (reader.NodeType == XmlNodeType.Element) + { + PopulateElement(reader, documentElement); + ParseXml(reader, documentElement); + break; } - return documentElement; + reader.Read(); } - private static void PopulateElement(XmlReader reader, MyXmlElement into) + return documentElement; + } + + private static void PopulateElement(XmlReader reader, MyXmlElement into) + { + into.Name = reader.Name; + + int attrCount = reader.AttributeCount; + for (int i = 0; i < attrCount; i++) { - into.Name = reader.Name; + reader.MoveToNextAttribute(); - int attrCount = reader.AttributeCount; - for (int i = 0; i < attrCount; i++) + into.Attributes.Add(new MyXmlAttribute() { - reader.MoveToNextAttribute(); + Name = reader.Name, + Value = reader.Value + }); + } + } - into.Attributes.Add(new MyXmlAttribute() - { - Name = reader.Name, - Value = reader.Value - }); - } + private static void ParseXml(XmlReader reader, MyXmlElement intoElement) + { + if (!reader.Read()) + { + return; } - private static void ParseXml(XmlReader reader, MyXmlElement intoElement) + while (true) { - if (!reader.Read()) - { - return; + switch (reader.NodeType) + { + // Found child + case XmlNodeType.Element: + case XmlNodeType.Text: + MyXmlElement child = new MyXmlElement(); + PopulateElement(reader, child); + ParseXml(reader, child); + intoElement.ChildNodes.Add(child); + break; + + // All done + case XmlNodeType.EndElement: + return; } - while (true) + if (!reader.Read()) { - switch (reader.NodeType) - { - // Found child - case XmlNodeType.Element: - case XmlNodeType.Text: - MyXmlElement child = new MyXmlElement(); - PopulateElement(reader, child); - ParseXml(reader, child); - intoElement.ChildNodes.Add(child); - break; - - // All done - case XmlNodeType.EndElement: - return; - } - - if (!reader.Read()) - { - return; - } + return; } } } diff --git a/components/Notifications/tests/TestMail.cs b/components/Notifications/tests/TestMail.cs index 3d76ce9b1..e1eaf0898 100644 --- a/components/Notifications/tests/TestMail.cs +++ b/components/Notifications/tests/TestMail.cs @@ -8,164 +8,163 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; #nullable disable -namespace NotificationsExperiment.Tests +namespace NotificationsExperiment.Tests; + +[TestClass] +public class TestMail { - [TestClass] - public class TestMail - { - private const string FirstFrom = "Jennifer Parker"; - private const string FirstSubject = "Photos from our trip"; - private const string FirstBody = "Check out these awesome photos I took while in New Zealand!"; + private const string FirstFrom = "Jennifer Parker"; + private const string FirstSubject = "Photos from our trip"; + private const string FirstBody = "Check out these awesome photos I took while in New Zealand!"; - private const string SecondFrom = "Steve Bosniak"; - private const string SecondSubject = "Build 2015 Dinner"; - private const string SecondBody = "Want to go out for dinner after Build tonight?"; + private const string SecondFrom = "Steve Bosniak"; + private const string SecondSubject = "Build 2015 Dinner"; + private const string SecondBody = "Want to go out for dinner after Build tonight?"; - [TestCategory("EndToEnd/Mail")] - [TestMethod] - public void TestMailTile() + [TestCategory("EndToEnd/Mail")] + [TestMethod] + public void TestMailTile() + { + TileBinding small = new TileBinding() { - TileBinding small = new TileBinding() + Content = new TileBindingContentIconic() { - Content = new TileBindingContentIconic() - { - Icon = new TileBasicImage() { Source = "Assets\\Mail.png" } - } - }; + Icon = new TileBasicImage() { Source = "Assets\\Mail.png" } + } + }; - TileBinding medium = new TileBinding() - { - Branding = TileBranding.Logo, + TileBinding medium = new TileBinding() + { + Branding = TileBranding.Logo, - Content = new TileBindingContentAdaptive() + Content = new TileBindingContentAdaptive() + { + Children = { - Children = - { - GenerateFirstMessage(false), - GenerateSpacer(), - GenerateSecondMessage(false) - } + GenerateFirstMessage(false), + GenerateSpacer(), + GenerateSecondMessage(false) } - }; + } + }; - TileBinding wideAndLarge = new TileBinding() - { - Branding = TileBranding.NameAndLogo, + TileBinding wideAndLarge = new TileBinding() + { + Branding = TileBranding.NameAndLogo, - Content = new TileBindingContentAdaptive() + Content = new TileBindingContentAdaptive() + { + Children = { - Children = - { - GenerateFirstMessage(true), - GenerateSpacer(), - GenerateSecondMessage(true) - } + GenerateFirstMessage(true), + GenerateSpacer(), + GenerateSecondMessage(true) } - }; + } + }; - TileContent content = new TileContent() + TileContent content = new TileContent() + { + Visual = new TileVisual() { - Visual = new TileVisual() - { - TileSmall = small, - TileMedium = medium, - TileWide = wideAndLarge, - TileLarge = wideAndLarge - } - }; + TileSmall = small, + TileMedium = medium, + TileWide = wideAndLarge, + TileLarge = wideAndLarge + } + }; - string expectedXml = $@""; + string expectedXml = $@""; - // Medium - expectedXml += @""; - expectedXml += GenerateXmlGroups(false); - expectedXml += ""; + // Medium + expectedXml += @""; + expectedXml += GenerateXmlGroups(false); + expectedXml += ""; - // Wide - expectedXml += @""; - expectedXml += GenerateXmlGroups(true); - expectedXml += ""; + // Wide + expectedXml += @""; + expectedXml += GenerateXmlGroups(true); + expectedXml += ""; - // Large - expectedXml += @""; - expectedXml += GenerateXmlGroups(true); - expectedXml += ""; + // Large + expectedXml += @""; + expectedXml += GenerateXmlGroups(true); + expectedXml += ""; - expectedXml += ""; + expectedXml += ""; - AssertHelper.AssertTile(expectedXml, content); - } + AssertHelper.AssertTile(expectedXml, content); + } - private static string GenerateXmlGroups(bool makeLarge) + private static string GenerateXmlGroups(bool makeLarge) + { + return GenerateXmlGroup(FirstFrom, FirstSubject, FirstBody, makeLarge) + "" + GenerateXmlGroup(SecondFrom, SecondSubject, SecondBody, makeLarge); + } + + private static string GenerateXmlGroup(string from, string subject, string body, bool makeLarge) + { + string xml = "" + GenerateXmlGroup(SecondFrom, SecondSubject, SecondBody, makeLarge); + xml += @" hint-style=""subtitle"""; } - - private static string GenerateXmlGroup(string from, string subject, string body, bool makeLarge) + else { - string xml = "{from}{subject}{body}"; + xml += $@">{from}{subject}{body}"; - return xml; - } + return xml; + } - private static AdaptiveText GenerateSpacer() - { - return new AdaptiveText(); - } + private static AdaptiveText GenerateSpacer() + { + return new AdaptiveText(); + } - private static AdaptiveGroup GenerateFirstMessage(bool makeLarge) - { - return GenerateMessage(FirstFrom, FirstSubject, FirstBody, makeLarge); - } + private static AdaptiveGroup GenerateFirstMessage(bool makeLarge) + { + return GenerateMessage(FirstFrom, FirstSubject, FirstBody, makeLarge); + } - private static AdaptiveGroup GenerateSecondMessage(bool makeLarge) - { - return GenerateMessage(SecondFrom, SecondSubject, SecondBody, makeLarge); - } + private static AdaptiveGroup GenerateSecondMessage(bool makeLarge) + { + return GenerateMessage(SecondFrom, SecondSubject, SecondBody, makeLarge); + } - private static AdaptiveGroup GenerateMessage(string from, string subject, string body, bool makeLarge) + private static AdaptiveGroup GenerateMessage(string from, string subject, string body, bool makeLarge) + { + return new AdaptiveGroup() { - return new AdaptiveGroup() + Children = { - Children = + new AdaptiveSubgroup() { - new AdaptiveSubgroup() + Children = { - Children = + new AdaptiveText() + { + Text = from, + HintStyle = makeLarge ? AdaptiveTextStyle.Subtitle : AdaptiveTextStyle.Caption + }, + + new AdaptiveText() { - new AdaptiveText() - { - Text = from, - HintStyle = makeLarge ? AdaptiveTextStyle.Subtitle : AdaptiveTextStyle.Caption - }, - - new AdaptiveText() - { - Text = subject, - HintStyle = AdaptiveTextStyle.CaptionSubtle - }, - - new AdaptiveText() - { - Text = body, - HintStyle = AdaptiveTextStyle.CaptionSubtle - } + Text = subject, + HintStyle = AdaptiveTextStyle.CaptionSubtle + }, + + new AdaptiveText() + { + Text = body, + HintStyle = AdaptiveTextStyle.CaptionSubtle } } } - }; - } + } + }; } } #endif diff --git a/components/Notifications/tests/TestTileContentBuilder.cs b/components/Notifications/tests/TestTileContentBuilder.cs index 576049b4a..288e902e8 100644 --- a/components/Notifications/tests/TestTileContentBuilder.cs +++ b/components/Notifications/tests/TestTileContentBuilder.cs @@ -9,107 +9,106 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; #nullable disable -namespace NotificationsExperiment.Tests +namespace NotificationsExperiment.Tests; + +[TestClass] +public class TestTileContentBuilder { - [TestClass] - public class TestTileContentBuilder + [TestMethod] + public void AddTextTest_OnSmallTileOnly() { - [TestMethod] - public void AddTextTest_OnSmallTileOnly() - { - // Arrange - string text = "text on small tile"; - TileContentBuilder builder = new TileContentBuilder(); - builder.AddTile(TileSize.Small); - - // Act - builder.AddText(text); - - // Assert - var tileText = GetTileAdaptiveText(builder, TileSize.Small); - Assert.IsNotNull(tileText); - Assert.AreSame("text on small tile", (string)tileText.Text); - } + // Arrange + string text = "text on small tile"; + TileContentBuilder builder = new TileContentBuilder(); + builder.AddTile(TileSize.Small); + + // Act + builder.AddText(text); + + // Assert + var tileText = GetTileAdaptiveText(builder, TileSize.Small); + Assert.IsNotNull(tileText); + Assert.AreSame("text on small tile", (string)tileText.Text); + } - [TestMethod] - public void AddTextTest_OnMediumTileOnly() - { - // Arrange - string text = "text on medium tile"; - TileContentBuilder builder = new TileContentBuilder(); - builder.AddTile(TileSize.Medium); - - // Act - builder.AddText(text); - - // Assert - var tileText = GetTileAdaptiveText(builder, TileSize.Medium); - Assert.IsNotNull(tileText); - Assert.AreSame("text on medium tile", (string)tileText.Text); - } + [TestMethod] + public void AddTextTest_OnMediumTileOnly() + { + // Arrange + string text = "text on medium tile"; + TileContentBuilder builder = new TileContentBuilder(); + builder.AddTile(TileSize.Medium); + + // Act + builder.AddText(text); + + // Assert + var tileText = GetTileAdaptiveText(builder, TileSize.Medium); + Assert.IsNotNull(tileText); + Assert.AreSame("text on medium tile", (string)tileText.Text); + } - [TestMethod] - public void AddTextTest_OnWideTileOnly() - { - // Arrange - string text = "text on wide tile"; - TileContentBuilder builder = new TileContentBuilder(); - builder.AddTile(TileSize.Wide); - - // Act - builder.AddText(text); - - // Assert - var tileText = GetTileAdaptiveText(builder, TileSize.Wide); - Assert.IsNotNull(tileText); - Assert.AreSame("text on wide tile", (string)tileText.Text); - } + [TestMethod] + public void AddTextTest_OnWideTileOnly() + { + // Arrange + string text = "text on wide tile"; + TileContentBuilder builder = new TileContentBuilder(); + builder.AddTile(TileSize.Wide); + + // Act + builder.AddText(text); + + // Assert + var tileText = GetTileAdaptiveText(builder, TileSize.Wide); + Assert.IsNotNull(tileText); + Assert.AreSame("text on wide tile", (string)tileText.Text); + } - [TestMethod] - public void AddTextTest_OnLargeTileOnly() - { - // Arrange - string text = "text on large tile"; - TileContentBuilder builder = new TileContentBuilder(); - builder.AddTile(TileSize.Large); - - // Act - builder.AddText(text); - - // Assert - var tileText = GetTileAdaptiveText(builder, TileSize.Large); - Assert.IsNotNull(tileText); - Assert.AreSame("text on large tile", (string)tileText.Text); - } + [TestMethod] + public void AddTextTest_OnLargeTileOnly() + { + // Arrange + string text = "text on large tile"; + TileContentBuilder builder = new TileContentBuilder(); + builder.AddTile(TileSize.Large); + + // Act + builder.AddText(text); + + // Assert + var tileText = GetTileAdaptiveText(builder, TileSize.Large); + Assert.IsNotNull(tileText); + Assert.AreSame("text on large tile", (string)tileText.Text); + } - private static AdaptiveText GetTileAdaptiveText(TileContentBuilder builder, TileSize size) + private static AdaptiveText GetTileAdaptiveText(TileContentBuilder builder, TileSize size) + { + TileBinding tileBinding; + switch (size) { - TileBinding tileBinding; - switch (size) - { - case TileSize.Small: - tileBinding = builder.Content.Visual.TileSmall; - break; - - case TileSize.Medium: - tileBinding = builder.Content.Visual.TileMedium; - break; - - case TileSize.Wide: - tileBinding = builder.Content.Visual.TileWide; - break; - - case TileSize.Large: - tileBinding = builder.Content.Visual.TileLarge; - break; - - default: - return null; - } - - var content = (TileBindingContentAdaptive)tileBinding.Content; - return content.Children.FirstOrDefault() as AdaptiveText; + case TileSize.Small: + tileBinding = builder.Content.Visual.TileSmall; + break; + + case TileSize.Medium: + tileBinding = builder.Content.Visual.TileMedium; + break; + + case TileSize.Wide: + tileBinding = builder.Content.Visual.TileWide; + break; + + case TileSize.Large: + tileBinding = builder.Content.Visual.TileLarge; + break; + + default: + return null; } + + var content = (TileBindingContentAdaptive)tileBinding.Content; + return content.Children.FirstOrDefault() as AdaptiveText; } } #endif diff --git a/components/Notifications/tests/TestToastArguments.cs b/components/Notifications/tests/TestToastArguments.cs index 88f5cbd00..fe585e4a0 100644 --- a/components/Notifications/tests/TestToastArguments.cs +++ b/components/Notifications/tests/TestToastArguments.cs @@ -11,492 +11,491 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; #nullable disable -namespace NotificationsExperiment.Tests +namespace NotificationsExperiment.Tests; + +[TestClass] +public class TestToastArguments { - [TestClass] - public class TestToastArguments + [TestMethod] + public void TestAddExceptions_NullName() { - [TestMethod] - public void TestAddExceptions_NullName() - { - ToastArguments query = new ToastArguments(); - - try - { - query.Add(null, "value"); - } - catch (ArgumentNullException) - { - return; - } + ToastArguments query = new ToastArguments(); - Assert.Fail("Adding null name shouldn't be allowed."); + try + { + query.Add(null, "value"); } - - [TestMethod] - public void TestParsing() + catch (ArgumentNullException) { - AssertParse(new ToastArguments(), string.Empty); - AssertParse(new ToastArguments(), " "); - AssertParse(new ToastArguments(), "\n"); - AssertParse(new ToastArguments(), "\t \n"); - AssertParse(new ToastArguments(), null); - - AssertParse( - new ToastArguments() - { - { "isBook" } - }, "isBook"); - - AssertParse( - new ToastArguments() - { - { "isBook" }, - { "isRead" } - }, "isBook;isRead"); - - AssertParse( - new ToastArguments() - { - { "isBook" }, - { "isRead" }, - { "isLiked" } - }, "isBook;isRead;isLiked"); - - AssertParse( - new ToastArguments() - { - { "name", "Andrew" } - }, "name=Andrew"); - - AssertParse( - new ToastArguments() - { - { "name", "Andrew" }, - { "isAdult" } - }, "name=Andrew;isAdult"); - - AssertParse( - new ToastArguments() - { - { "name", "Andrew" }, - { "isAdult" } - }, "isAdult;name=Andrew"); - - AssertParse( - new ToastArguments() - { - { "name", "Andrew" }, - { "age", "22" } - }, "age=22;name=Andrew"); + return; } - [TestMethod] - public void TestToString_ExactString() - { - Assert.AreEqual(string.Empty, new ToastArguments().ToString()); + Assert.Fail("Adding null name shouldn't be allowed."); + } - Assert.AreEqual("isBook", new ToastArguments() + [TestMethod] + public void TestParsing() + { + AssertParse(new ToastArguments(), string.Empty); + AssertParse(new ToastArguments(), " "); + AssertParse(new ToastArguments(), "\n"); + AssertParse(new ToastArguments(), "\t \n"); + AssertParse(new ToastArguments(), null); + + AssertParse( + new ToastArguments() { { "isBook" } - }.ToString()); + }, "isBook"); - Assert.AreEqual("name=Andrew", new ToastArguments() + AssertParse( + new ToastArguments() { - { "name", "Andrew" } - }.ToString()); - } + { "isBook" }, + { "isRead" } + }, "isBook;isRead"); - [TestMethod] - public void TestSpecialCharacters() - { - Assert.AreEqual("full name=Andrew Leader", new ToastArguments() + AssertParse( + new ToastArguments() { - { "full name", "Andrew Leader" } - }.ToString()); + { "isBook" }, + { "isRead" }, + { "isLiked" } + }, "isBook;isRead;isLiked"); - Assert.AreEqual("name%3Bcompany=Andrew%3BMicrosoft", new ToastArguments() + AssertParse( + new ToastArguments() { - { "name;company", "Andrew;Microsoft" } - }.ToString()); + { "name", "Andrew" } + }, "name=Andrew"); - Assert.AreEqual("name/company=Andrew/Microsoft", new ToastArguments() + AssertParse( + new ToastArguments() { - { "name/company", "Andrew/Microsoft" } - }.ToString()); + { "name", "Andrew" }, + { "isAdult" } + }, "name=Andrew;isAdult"); - Assert.AreEqual("message=Dinner?", new ToastArguments() + AssertParse( + new ToastArguments() { - { "message", "Dinner?" } - }.ToString()); + { "name", "Andrew" }, + { "isAdult" } + }, "isAdult;name=Andrew"); - Assert.AreEqual("message=to: Andrew", new ToastArguments() + AssertParse( + new ToastArguments() { - { "message", "to: Andrew" } - }.ToString()); + { "name", "Andrew" }, + { "age", "22" } + }, "age=22;name=Andrew"); + } - Assert.AreEqual("email=andrew@live.com", new ToastArguments() - { - { "email", "andrew@live.com" } - }.ToString()); + [TestMethod] + public void TestToString_ExactString() + { + Assert.AreEqual(string.Empty, new ToastArguments().ToString()); - Assert.AreEqual("messsage=food%3Dyummy", new ToastArguments() - { - { "messsage", "food=yummy" } - }.ToString()); + Assert.AreEqual("isBook", new ToastArguments() + { + { "isBook" } + }.ToString()); - Assert.AreEqual("messsage=$$$", new ToastArguments() - { - { "messsage", "$$$" } - }.ToString()); + Assert.AreEqual("name=Andrew", new ToastArguments() + { + { "name", "Andrew" } + }.ToString()); + } - Assert.AreEqual("messsage=-_.!~*'()", new ToastArguments() - { - { "messsage", "-_.!~*'()" } - }.ToString()); + [TestMethod] + public void TestSpecialCharacters() + { + Assert.AreEqual("full name=Andrew Leader", new ToastArguments() + { + { "full name", "Andrew Leader" } + }.ToString()); - Assert.AreEqual("messsage=this & that", new ToastArguments() - { - { "messsage", "this & that" } - }.ToString()); + Assert.AreEqual("name%3Bcompany=Andrew%3BMicrosoft", new ToastArguments() + { + { "name;company", "Andrew;Microsoft" } + }.ToString()); - Assert.AreEqual("messsage=20%25 off!", new ToastArguments() - { - { "messsage", "20% off!" } - }.ToString()); + Assert.AreEqual("name/company=Andrew/Microsoft", new ToastArguments() + { + { "name/company", "Andrew/Microsoft" } + }.ToString()); - Assert.AreEqual("messsage=Nonsense %2526 %2525 %253D", new ToastArguments() - { - { "messsage", "Nonsense %26 %25 %3D" } - }.ToString()); - } + Assert.AreEqual("message=Dinner?", new ToastArguments() + { + { "message", "Dinner?" } + }.ToString()); - [TestMethod] - public void TestDecoding() + Assert.AreEqual("message=to: Andrew", new ToastArguments() { - AssertDecode("Hello world", "Hello world"); + { "message", "to: Andrew" } + }.ToString()); - AssertDecode(";/?:@&=+$%", "%3B/?:@&%3D+$%25"); - AssertDecode("-_.!~*'()", "-_.!~*'()"); - } + Assert.AreEqual("email=andrew@live.com", new ToastArguments() + { + { "email", "andrew@live.com" } + }.ToString()); - [TestMethod] - public void TestIndexer_NullException() + Assert.AreEqual("messsage=food%3Dyummy", new ToastArguments() { - try - { - string val = new ToastArguments()[null]; - } - catch (ArgumentNullException) - { - return; - } + { "messsage", "food=yummy" } + }.ToString()); - Assert.Fail("Exception should have been thrown."); - } + Assert.AreEqual("messsage=$$$", new ToastArguments() + { + { "messsage", "$$$" } + }.ToString()); - [TestMethod] - public void TestIndexer_NotFoundException() + Assert.AreEqual("messsage=-_.!~*'()", new ToastArguments() { - try - { - var args = new ToastArguments() - { - { "name", "Andrew" } - }; + { "messsage", "-_.!~*'()" } + }.ToString()); - _ = args["Name"]; - } - catch (KeyNotFoundException) - { - return; - } + Assert.AreEqual("messsage=this & that", new ToastArguments() + { + { "messsage", "this & that" } + }.ToString()); - Assert.Fail("Exception should have been thrown."); - } + Assert.AreEqual("messsage=20%25 off!", new ToastArguments() + { + { "messsage", "20% off!" } + }.ToString()); - [TestMethod] - public void TestIndexer() + Assert.AreEqual("messsage=Nonsense %2526 %2525 %253D", new ToastArguments() { - AssertIndexer(null, "isBook;name=Andrew", "isBook"); + { "messsage", "Nonsense %26 %25 %3D" } + }.ToString()); + } - AssertIndexer("Andrew", "isBook;name=Andrew", "name"); + [TestMethod] + public void TestDecoding() + { + AssertDecode("Hello world", "Hello world"); - AssertIndexer("Andrew", "count=2;name=Andrew", "name"); + AssertDecode(";/?:@&=+$%", "%3B/?:@&%3D+$%25"); + AssertDecode("-_.!~*'()", "-_.!~*'()"); + } + + [TestMethod] + public void TestIndexer_NullException() + { + try + { + string val = new ToastArguments()[null]; + } + catch (ArgumentNullException) + { + return; } - [TestMethod] - public void TestRemove_OnlyKey() + Assert.Fail("Exception should have been thrown."); + } + + [TestMethod] + public void TestIndexer_NotFoundException() + { + try { - ToastArguments qs = new ToastArguments() + var args = new ToastArguments() { - { "name", "Andrew" }, - { "age", "22" } + { "name", "Andrew" } }; - Assert.IsTrue(qs.Remove("age")); + _ = args["Name"]; + } + catch (KeyNotFoundException) + { + return; + } - AssertEqual( - new ToastArguments() - { - { "name", "Andrew" } - }, qs); + Assert.Fail("Exception should have been thrown."); + } - Assert.IsFalse(qs.Remove("age")); - } + [TestMethod] + public void TestIndexer() + { + AssertIndexer(null, "isBook;name=Andrew", "isBook"); + + AssertIndexer("Andrew", "isBook;name=Andrew", "name"); - [TestMethod] - public void TestContains() + AssertIndexer("Andrew", "count=2;name=Andrew", "name"); + } + + [TestMethod] + public void TestRemove_OnlyKey() + { + ToastArguments qs = new ToastArguments() { - ToastArguments qs = new ToastArguments(); + { "name", "Andrew" }, + { "age", "22" } + }; - Assert.IsFalse(qs.Contains("name")); - Assert.IsFalse(qs.Contains("name", "Andrew")); + Assert.IsTrue(qs.Remove("age")); - qs.Add("isBook"); + AssertEqual( + new ToastArguments() + { + { "name", "Andrew" } + }, qs); - Assert.IsFalse(qs.Contains("name")); - Assert.IsFalse(qs.Contains("name", "Andrew")); + Assert.IsFalse(qs.Remove("age")); + } - Assert.IsTrue(qs.Contains("isBook")); - Assert.IsTrue(qs.Contains("isBook", null)); - Assert.IsFalse(qs.Contains("isBook", "True")); + [TestMethod] + public void TestContains() + { + ToastArguments qs = new ToastArguments(); - qs.Add("isBook", "True"); + Assert.IsFalse(qs.Contains("name")); + Assert.IsFalse(qs.Contains("name", "Andrew")); - Assert.IsTrue(qs.Contains("isBook")); - Assert.IsFalse(qs.Contains("isBook", null)); - Assert.IsTrue(qs.Contains("isBook", "True")); + qs.Add("isBook"); - qs.Add("name", "Andrew"); + Assert.IsFalse(qs.Contains("name")); + Assert.IsFalse(qs.Contains("name", "Andrew")); - Assert.IsTrue(qs.Contains("name")); - Assert.IsFalse(qs.Contains("name", null)); // Value doesn't exist - Assert.IsTrue(qs.Contains("name", "Andrew")); - Assert.IsFalse(qs.Contains("Name", "Andrew")); // Wrong case on name - Assert.IsFalse(qs.Contains("name", "andrew")); // Wrong case on value - Assert.IsFalse(qs.Contains("Name")); // Wrong case on name - } + Assert.IsTrue(qs.Contains("isBook")); + Assert.IsTrue(qs.Contains("isBook", null)); + Assert.IsFalse(qs.Contains("isBook", "True")); - [TestMethod] - public void TestAdd() - { - ToastArguments qs = new ToastArguments(); - - qs.Add("name", "Andrew"); - - AssertEqual( - new ToastArguments() - { - { "name", "Andrew" } - }, qs); - - qs.Add("age", "22"); - - AssertEqual( - new ToastArguments() - { - { "name", "Andrew" }, - { "age", "22" } - }, qs); - - qs.Add("name", "Lei"); - - AssertEqual( - new ToastArguments() - { - { "name", "Lei" }, - { "age", "22" } - }, qs); - - string nullStr = null; - qs.Add("name", nullStr); - - AssertEqual( - new ToastArguments() - { - { "name" }, - { "age", "22" } - }, qs); - } + qs.Add("isBook", "True"); - [TestMethod] - public void TestEnumerator() - { - KeyValuePair[] parameters = ToastArguments.Parse("name=Andrew;age=22;isOld").ToArray(); - - Assert.AreEqual(3, parameters.Length); - Assert.AreEqual(1, parameters.Count(i => i.Key.Equals("name"))); - Assert.AreEqual(1, parameters.Count(i => i.Key.Equals("age"))); - Assert.AreEqual(1, parameters.Count(i => i.Key.Equals("isOld"))); - Assert.IsTrue(parameters.Any(i => i.Key.Equals("name") && i.Value.Equals("Andrew"))); - Assert.IsTrue(parameters.Any(i => i.Key.Equals("age") && i.Value.Equals("22"))); - Assert.IsTrue(parameters.Any(i => i.Key.Equals("isOld") && i.Value == null)); - } + Assert.IsTrue(qs.Contains("isBook")); + Assert.IsFalse(qs.Contains("isBook", null)); + Assert.IsTrue(qs.Contains("isBook", "True")); - [TestMethod] - public void TestCount() - { - ToastArguments qs = new ToastArguments(); + qs.Add("name", "Andrew"); - Assert.AreEqual(0, qs.Count); + Assert.IsTrue(qs.Contains("name")); + Assert.IsFalse(qs.Contains("name", null)); // Value doesn't exist + Assert.IsTrue(qs.Contains("name", "Andrew")); + Assert.IsFalse(qs.Contains("Name", "Andrew")); // Wrong case on name + Assert.IsFalse(qs.Contains("name", "andrew")); // Wrong case on value + Assert.IsFalse(qs.Contains("Name")); // Wrong case on name + } - qs.Add("name", "Andrew"); + [TestMethod] + public void TestAdd() + { + ToastArguments qs = new ToastArguments(); - Assert.AreEqual(1, qs.Count); + qs.Add("name", "Andrew"); - qs.Add("age", "22"); + AssertEqual( + new ToastArguments() + { + { "name", "Andrew" } + }, qs); - Assert.AreEqual(2, qs.Count); + qs.Add("age", "22"); - qs.Remove("age"); + AssertEqual( + new ToastArguments() + { + { "name", "Andrew" }, + { "age", "22" } + }, qs); - Assert.AreEqual(1, qs.Count); + qs.Add("name", "Lei"); - qs.Remove("name"); + AssertEqual( + new ToastArguments() + { + { "name", "Lei" }, + { "age", "22" } + }, qs); - Assert.AreEqual(0, qs.Count); - } + string nullStr = null; + qs.Add("name", nullStr); - [TestMethod] - public void TestStronglyTyped() - { - ToastArguments args = new ToastArguments() - .Add("isAdult", true) - .Add("isPremium", false) - .Add("age", 22) - .Add("level", 0) - .Add("gpa", 3.97) - .Add("percent", 97.3f); + AssertEqual( + new ToastArguments() + { + { "name" }, + { "age", "22" } + }, qs); + } + + [TestMethod] + public void TestEnumerator() + { + KeyValuePair[] parameters = ToastArguments.Parse("name=Andrew;age=22;isOld").ToArray(); + + Assert.AreEqual(3, parameters.Length); + Assert.AreEqual(1, parameters.Count(i => i.Key.Equals("name"))); + Assert.AreEqual(1, parameters.Count(i => i.Key.Equals("age"))); + Assert.AreEqual(1, parameters.Count(i => i.Key.Equals("isOld"))); + Assert.IsTrue(parameters.Any(i => i.Key.Equals("name") && i.Value.Equals("Andrew"))); + Assert.IsTrue(parameters.Any(i => i.Key.Equals("age") && i.Value.Equals("22"))); + Assert.IsTrue(parameters.Any(i => i.Key.Equals("isOld") && i.Value == null)); + } - args.Add("activationKind", ToastActivationType.Background); + [TestMethod] + public void TestCount() + { + ToastArguments qs = new ToastArguments(); - AssertEqual( - new ToastArguments() - { - { "isAdult", "1" }, - { "isPremium", "0" }, - { "age", "22" }, - { "level", "0" }, - { "gpa", "3.97" }, - { "percent", "97.3" }, - { "activationKind", "1" } - }, args); + Assert.AreEqual(0, qs.Count); - Assert.AreEqual(true, args.GetBool("isAdult")); - Assert.AreEqual("1", args.Get("isAdult")); + qs.Add("name", "Andrew"); - Assert.AreEqual(false, args.GetBool("isPremium")); - Assert.AreEqual("0", args.Get("isPremium")); + Assert.AreEqual(1, qs.Count); - Assert.AreEqual(22, args.GetInt("age")); - Assert.AreEqual(22d, args.GetDouble("age")); - Assert.AreEqual(22f, args.GetFloat("age")); - Assert.AreEqual("22", args.Get("age")); + qs.Add("age", "22"); - Assert.AreEqual(0, args.GetInt("level")); + Assert.AreEqual(2, qs.Count); - Assert.AreEqual(3.97d, args.GetDouble("gpa")); + qs.Remove("age"); - Assert.AreEqual(97.3f, args.GetFloat("percent")); + Assert.AreEqual(1, qs.Count); - Assert.AreEqual(ToastActivationType.Background, args.GetEnum("activationKind")); + qs.Remove("name"); - if (args.TryGetValue("activationKind", out ToastActivationType activationType)) - { - Assert.AreEqual(ToastActivationType.Background, activationType); - } - else + Assert.AreEqual(0, qs.Count); + } + + [TestMethod] + public void TestStronglyTyped() + { + ToastArguments args = new ToastArguments() + .Add("isAdult", true) + .Add("isPremium", false) + .Add("age", 22) + .Add("level", 0) + .Add("gpa", 3.97) + .Add("percent", 97.3f); + + args.Add("activationKind", ToastActivationType.Background); + + AssertEqual( + new ToastArguments() { - Assert.Fail("TryGetValue as enum failed"); - } + { "isAdult", "1" }, + { "isPremium", "0" }, + { "age", "22" }, + { "level", "0" }, + { "gpa", "3.97" }, + { "percent", "97.3" }, + { "activationKind", "1" } + }, args); - // Trying to get enum that isn't an enum should return false - Assert.IsFalse(args.TryGetValue("percent", out activationType)); + Assert.AreEqual(true, args.GetBool("isAdult")); + Assert.AreEqual("1", args.Get("isAdult")); - // After serializing and deserializing, the same should work - args = ToastArguments.Parse(args.ToString()); + Assert.AreEqual(false, args.GetBool("isPremium")); + Assert.AreEqual("0", args.Get("isPremium")); - Assert.AreEqual(true, args.GetBool("isAdult")); - Assert.AreEqual("1", args.Get("isAdult")); + Assert.AreEqual(22, args.GetInt("age")); + Assert.AreEqual(22d, args.GetDouble("age")); + Assert.AreEqual(22f, args.GetFloat("age")); + Assert.AreEqual("22", args.Get("age")); - Assert.AreEqual(false, args.GetBool("isPremium")); - Assert.AreEqual("0", args.Get("isPremium")); + Assert.AreEqual(0, args.GetInt("level")); - Assert.AreEqual(22, args.GetInt("age")); - Assert.AreEqual(22d, args.GetDouble("age")); - Assert.AreEqual(22f, args.GetFloat("age")); - Assert.AreEqual("22", args.Get("age")); + Assert.AreEqual(3.97d, args.GetDouble("gpa")); - Assert.AreEqual(0, args.GetInt("level")); + Assert.AreEqual(97.3f, args.GetFloat("percent")); - Assert.AreEqual(3.97d, args.GetDouble("gpa")); + Assert.AreEqual(ToastActivationType.Background, args.GetEnum("activationKind")); - Assert.AreEqual(97.3f, args.GetFloat("percent")); + if (args.TryGetValue("activationKind", out ToastActivationType activationType)) + { + Assert.AreEqual(ToastActivationType.Background, activationType); + } + else + { + Assert.Fail("TryGetValue as enum failed"); + } - Assert.AreEqual(ToastActivationType.Background, args.GetEnum("activationKind")); + // Trying to get enum that isn't an enum should return false + Assert.IsFalse(args.TryGetValue("percent", out activationType)); - if (args.TryGetValue("activationKind", out activationType)) - { - Assert.AreEqual(ToastActivationType.Background, activationType); - } - else - { - Assert.Fail("TryGetValue as enum failed"); - } + // After serializing and deserializing, the same should work + args = ToastArguments.Parse(args.ToString()); - // Trying to get enum that isn't an enum should return false - Assert.IsFalse(args.TryGetValue("percent", out activationType)); - } + Assert.AreEqual(true, args.GetBool("isAdult")); + Assert.AreEqual("1", args.Get("isAdult")); - private static void AssertIndexer(string expected, string queryString, string paramName) - { - ToastArguments q = ToastArguments.Parse(queryString); + Assert.AreEqual(false, args.GetBool("isPremium")); + Assert.AreEqual("0", args.Get("isPremium")); - Assert.AreEqual(expected, q[paramName]); - } + Assert.AreEqual(22, args.GetInt("age")); + Assert.AreEqual(22d, args.GetDouble("age")); + Assert.AreEqual(22f, args.GetFloat("age")); + Assert.AreEqual("22", args.Get("age")); + + Assert.AreEqual(0, args.GetInt("level")); + + Assert.AreEqual(3.97d, args.GetDouble("gpa")); + + Assert.AreEqual(97.3f, args.GetFloat("percent")); + + Assert.AreEqual(ToastActivationType.Background, args.GetEnum("activationKind")); - private static void AssertDecode(string expected, string encoded) + if (args.TryGetValue("activationKind", out activationType)) { - Assert.AreEqual(expected, ToastArguments.Parse("message=" + encoded).Get("message")); + Assert.AreEqual(ToastActivationType.Background, activationType); } - - private static void AssertParse(ToastArguments expected, string inputQueryString) + else { - Assert.IsTrue(IsSame(expected, ToastArguments.Parse(inputQueryString)), "Expected: " + expected + "\nActual: " + inputQueryString); + Assert.Fail("TryGetValue as enum failed"); } - private static void AssertEqual(ToastArguments expected, ToastArguments actual) - { - Assert.IsTrue(IsSame(expected, actual), "Expected: " + expected + "\nActual: " + actual); + // Trying to get enum that isn't an enum should return false + Assert.IsFalse(args.TryGetValue("percent", out activationType)); + } - Assert.IsTrue(IsSame(expected, ToastArguments.Parse(actual.ToString())), "After serializing and parsing actual, result changed.\n\nExpected: " + expected + "\nActual: " + ToastArguments.Parse(actual.ToString())); - Assert.IsTrue(IsSame(ToastArguments.Parse(expected.ToString()), actual), "After serializing and parsing expected, result changed.\n\nExpected: " + ToastArguments.Parse(expected.ToString()) + "\nActual: " + actual); - Assert.IsTrue(IsSame(ToastArguments.Parse(expected.ToString()), ToastArguments.Parse(actual.ToString())), "After serializing and parsing both, result changed.\n\nExpected: " + ToastArguments.Parse(expected.ToString()) + "\nActual: " + ToastArguments.Parse(actual.ToString())); + private static void AssertIndexer(string expected, string queryString, string paramName) + { + ToastArguments q = ToastArguments.Parse(queryString); + + Assert.AreEqual(expected, q[paramName]); + } + + private static void AssertDecode(string expected, string encoded) + { + Assert.AreEqual(expected, ToastArguments.Parse("message=" + encoded).Get("message")); + } + + private static void AssertParse(ToastArguments expected, string inputQueryString) + { + Assert.IsTrue(IsSame(expected, ToastArguments.Parse(inputQueryString)), "Expected: " + expected + "\nActual: " + inputQueryString); + } + + private static void AssertEqual(ToastArguments expected, ToastArguments actual) + { + Assert.IsTrue(IsSame(expected, actual), "Expected: " + expected + "\nActual: " + actual); + + Assert.IsTrue(IsSame(expected, ToastArguments.Parse(actual.ToString())), "After serializing and parsing actual, result changed.\n\nExpected: " + expected + "\nActual: " + ToastArguments.Parse(actual.ToString())); + Assert.IsTrue(IsSame(ToastArguments.Parse(expected.ToString()), actual), "After serializing and parsing expected, result changed.\n\nExpected: " + ToastArguments.Parse(expected.ToString()) + "\nActual: " + actual); + Assert.IsTrue(IsSame(ToastArguments.Parse(expected.ToString()), ToastArguments.Parse(actual.ToString())), "After serializing and parsing both, result changed.\n\nExpected: " + ToastArguments.Parse(expected.ToString()) + "\nActual: " + ToastArguments.Parse(actual.ToString())); + } + + private static bool IsSame(ToastArguments expected, ToastArguments actual) + { + if (expected.Count != actual.Count) + { + return false; } - private static bool IsSame(ToastArguments expected, ToastArguments actual) + foreach (var pair in expected) { - if (expected.Count != actual.Count) + if (!actual.Contains(pair.Key)) { return false; } - foreach (var pair in expected) + if (actual.Get(pair.Key) != pair.Value) { - if (!actual.Contains(pair.Key)) - { - return false; - } - - if (actual.Get(pair.Key) != pair.Value) - { - return false; - } + return false; } - - return true; } + + return true; } } #endif diff --git a/components/Notifications/tests/TestToastContentBuilder.cs b/components/Notifications/tests/TestToastContentBuilder.cs index 1ea03b124..f74a3033e 100644 --- a/components/Notifications/tests/TestToastContentBuilder.cs +++ b/components/Notifications/tests/TestToastContentBuilder.cs @@ -10,1192 +10,1191 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; #nullable disable -namespace NotificationsExperiment.Tests +namespace NotificationsExperiment.Tests; + +[TestClass] +public class TestToastContentBuilder { - [TestClass] - public class TestToastContentBuilder + [TestMethod] + public void AddCustomTimeStampTest_WithCustomTimeStamp_ReturnSelfWithCustomTimeStampAdded() { - [TestMethod] - public void AddCustomTimeStampTest_WithCustomTimeStamp_ReturnSelfWithCustomTimeStampAdded() - { - // Arrange - DateTime testCustomTimeStamp = DateTime.UtcNow; + // Arrange + DateTime testCustomTimeStamp = DateTime.UtcNow; - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddCustomTimeStamp(testCustomTimeStamp); + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddCustomTimeStamp(testCustomTimeStamp); - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testCustomTimeStamp, builder.Content.DisplayTimestamp); - } + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testCustomTimeStamp, builder.Content.DisplayTimestamp); + } - [TestMethod] - public void AddHeaderTest_WithExpectedArgs_ReturnSelfWithHeaderAdded() - { - // Arrange - string testToastHeaderId = "Test Header ID"; - string testToastTitle = "Test Toast Title"; - string testToastArguments = "Test Toast Arguments"; - - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddHeader(testToastHeaderId, testToastTitle, testToastArguments); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testToastHeaderId, builder.Content.Header.Id); - Assert.AreEqual(testToastTitle, builder.Content.Header.Title); - Assert.AreEqual(testToastArguments, builder.Content.Header.Arguments); - } - - [TestMethod] - public void AddHeaderTest_WithExpectedArgsAndToastArguments_ReturnSelfWithHeaderAdded() - { - // Arrange - string testToastHeaderId = "Test Header ID"; - string testToastTitle = "Test Toast Title"; - ToastArguments testToastArguments = new ToastArguments() - .Add("arg1", 5) - .Add("arg2", "tacos"); - - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddHeader(testToastHeaderId, testToastTitle, testToastArguments); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testToastHeaderId, builder.Content.Header.Id); - Assert.AreEqual(testToastTitle, builder.Content.Header.Title); - Assert.AreEqual(testToastArguments.ToString(), builder.Content.Header.Arguments); - } - - [TestMethod] - public void AddToastActivationInfoTest_WithExpectedArgs_ReturnSelfWithActivationInfoAdded() - { - // Arrange - string testToastLaunchArugments = "Test Toast Launch Args"; - ToastActivationType testToastActivationType = ToastActivationType.Background; - - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddToastActivationInfo(testToastLaunchArugments, testToastActivationType); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testToastLaunchArugments, builder.Content.Launch); - Assert.AreEqual(testToastActivationType, builder.Content.ActivationType); - } - - [TestMethod] - public void AddArgumentTest_Basic_ReturnSelfWithArgumentsAdded() - { - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder - .AddArgument("userId", 542) - .AddArgument("name", "Andrew"); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual("userId=542;name=Andrew", builder.Content.Launch); - } - - [TestMethod] - public void AddArgumentTest_NoValue_ReturnSelfWithArgumentsAdded() - { - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder - .AddArgument("isPurelyInformational"); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual("isPurelyInformational", builder.Content.Launch); - } - - [TestMethod] - public void AddArgumentTest_Escaping_ReturnSelfWithArgumentsAdded() - { - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder - .AddArgument("user;Id", "andrew=leader%26bares"); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual("user%3BId=andrew%3Dleader%2526bares", builder.Content.Launch); - } - - [TestMethod] - public void AddArgumentTest_Replacing_ReturnSelfWithArgumentsAdded() - { - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder - .AddArgument("userId", 542) - .AddArgument("name", "Andrew") - .AddArgument("userId", 601); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual("userId=601;name=Andrew", builder.Content.Launch); - } - - [TestMethod] - public void AddArgumentTest_Generic_ReturnSelfWithArgumentsAdded() - { - // Arrange - const string userIdKey = "userId"; - const int userIdValue = 542; - - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder - .AddButton(new ToastButton() - .SetContent("Accept") - .AddArgument("action", "accept") - .SetBackgroundActivation()) - .AddButton(new ToastButtonSnooze()) - .AddButton("View", ToastActivationType.Protocol, "https://msn.com") - - // Add generic arguments halfway through (should be applied to existing buttons and to any subsequent buttons added later) - .AddArgument(userIdKey, userIdValue) - - .AddButton(new ToastButton() - .SetContent("Decline") - .AddArgument("action", "decline") - .SetBackgroundActivation()) - .AddButton(new ToastButton() - .SetContent("Report") - .SetProtocolActivation(new Uri("https://microsoft.com"))); - - // Assert - Assert.AreSame(builder, anotherReference); - - // Top level arguments should be present - Assert.AreEqual("userId=542", builder.Content.Launch); - - // All foreground/background activation buttons should have received generic arguments. Protocol and system activation buttons shouldn't have had any arguments changed. - var actions = builder.Content.Actions as ToastActionsCustom; - - var button1 = actions.Buttons[0] as ToastButton; - Assert.AreEqual("Accept", button1.Content); - Assert.AreEqual("action=accept;userId=542", button1.Arguments); - - var button2 = actions.Buttons[1]; - Assert.IsInstanceOfType(button2, typeof(ToastButtonSnooze)); - - var button3 = actions.Buttons[2] as ToastButton; - Assert.AreEqual("View", button3.Content); - Assert.AreEqual("https://msn.com", button3.Arguments); - - var button4 = actions.Buttons[3] as ToastButton; - Assert.AreEqual("Decline", button4.Content); - Assert.AreEqual("action=decline;userId=542", button4.Arguments); - - var button5 = actions.Buttons[4] as ToastButton; - Assert.AreEqual("Report", button5.Content); - Assert.AreEqual("https://microsoft.com/", button5.Arguments); - } - - [TestMethod] - public void AddArgumentTest_ReplacingWithinButton_ReturnSelfWithArgumentsAdded() - { - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder - .AddButton(new ToastButton() - .SetContent("Accept") - .AddArgument("action", "accept") - .AddArgument("userId", 601) - .SetBackgroundActivation()) - - // Add generic arguments halfway through (in this case shouldn't overwrite anything) - .AddArgument("userId", 542) - - .AddButton(new ToastButton() - .SetContent("Decline") - .AddArgument("action", "decline") - .AddArgument("userId", 601) - .SetBackgroundActivation()); - - // Assert - Assert.AreSame(builder, anotherReference); - - // Top level arguments should be present - Assert.AreEqual("userId=542", builder.Content.Launch); - - // Buttons should have overridden the generic userId - var actions = builder.Content.Actions as ToastActionsCustom; - - var button1 = actions.Buttons[0] as ToastButton; - Assert.AreEqual("Accept", button1.Content); - Assert.AreEqual("action=accept;userId=601", button1.Arguments); - - var button2 = actions.Buttons[1] as ToastButton; - Assert.AreEqual("Decline", button2.Content); - Assert.AreEqual("action=decline;userId=601", button2.Arguments); - } - - [TestMethod] - public void AddArgumentTest_AvoidModifyingCustomButtons_ReturnSelfWithArgumentsAdded() - { - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder - .AddToastActivationInfo("myCustomLaunchStr", ToastActivationType.Foreground) + [TestMethod] + public void AddHeaderTest_WithExpectedArgs_ReturnSelfWithHeaderAdded() + { + // Arrange + string testToastHeaderId = "Test Header ID"; + string testToastTitle = "Test Toast Title"; + string testToastArguments = "Test Toast Arguments"; + + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddHeader(testToastHeaderId, testToastTitle, testToastArguments); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testToastHeaderId, builder.Content.Header.Id); + Assert.AreEqual(testToastTitle, builder.Content.Header.Title); + Assert.AreEqual(testToastArguments, builder.Content.Header.Arguments); + } - .AddButton("Accept", ToastActivationType.Background, "myAcceptStr") + [TestMethod] + public void AddHeaderTest_WithExpectedArgsAndToastArguments_ReturnSelfWithHeaderAdded() + { + // Arrange + string testToastHeaderId = "Test Header ID"; + string testToastTitle = "Test Toast Title"; + ToastArguments testToastArguments = new ToastArguments() + .Add("arg1", 5) + .Add("arg2", "tacos"); + + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddHeader(testToastHeaderId, testToastTitle, testToastArguments); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testToastHeaderId, builder.Content.Header.Id); + Assert.AreEqual(testToastTitle, builder.Content.Header.Title); + Assert.AreEqual(testToastArguments.ToString(), builder.Content.Header.Arguments); + } - // userId shouldn't be added to any of these except view - .AddArgument("userId", 542) + [TestMethod] + public void AddToastActivationInfoTest_WithExpectedArgs_ReturnSelfWithActivationInfoAdded() + { + // Arrange + string testToastLaunchArugments = "Test Toast Launch Args"; + ToastActivationType testToastActivationType = ToastActivationType.Background; + + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddToastActivationInfo(testToastLaunchArugments, testToastActivationType); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testToastLaunchArugments, builder.Content.Launch); + Assert.AreEqual(testToastActivationType, builder.Content.ActivationType); + } - .AddButton("Decline", ToastActivationType.Background, "myDeclineStr") + [TestMethod] + public void AddArgumentTest_Basic_ReturnSelfWithArgumentsAdded() + { + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder + .AddArgument("userId", 542) + .AddArgument("name", "Andrew"); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual("userId=542;name=Andrew", builder.Content.Launch); + } - .AddButton(new ToastButton() - .SetContent("View") - .AddArgument("action", "view")); + [TestMethod] + public void AddArgumentTest_NoValue_ReturnSelfWithArgumentsAdded() + { + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder + .AddArgument("isPurelyInformational"); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual("isPurelyInformational", builder.Content.Launch); + } - // Assert - Assert.AreSame(builder, anotherReference); + [TestMethod] + public void AddArgumentTest_Escaping_ReturnSelfWithArgumentsAdded() + { + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder + .AddArgument("user;Id", "andrew=leader%26bares"); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual("user%3BId=andrew%3Dleader%2526bares", builder.Content.Launch); + } - // Top level arguments should be the custom string since user set that - Assert.AreEqual("myCustomLaunchStr", builder.Content.Launch); + [TestMethod] + public void AddArgumentTest_Replacing_ReturnSelfWithArgumentsAdded() + { + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder + .AddArgument("userId", 542) + .AddArgument("name", "Andrew") + .AddArgument("userId", 601); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual("userId=601;name=Andrew", builder.Content.Launch); + } - // Buttons should have their custom strings except the last - var actions = builder.Content.Actions as ToastActionsCustom; + [TestMethod] + public void AddArgumentTest_Generic_ReturnSelfWithArgumentsAdded() + { + // Arrange + const string userIdKey = "userId"; + const int userIdValue = 542; + + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder + .AddButton(new ToastButton() + .SetContent("Accept") + .AddArgument("action", "accept") + .SetBackgroundActivation()) + .AddButton(new ToastButtonSnooze()) + .AddButton("View", ToastActivationType.Protocol, "https://msn.com") + + // Add generic arguments halfway through (should be applied to existing buttons and to any subsequent buttons added later) + .AddArgument(userIdKey, userIdValue) + + .AddButton(new ToastButton() + .SetContent("Decline") + .AddArgument("action", "decline") + .SetBackgroundActivation()) + .AddButton(new ToastButton() + .SetContent("Report") + .SetProtocolActivation(new Uri("https://microsoft.com"))); + + // Assert + Assert.AreSame(builder, anotherReference); + + // Top level arguments should be present + Assert.AreEqual("userId=542", builder.Content.Launch); + + // All foreground/background activation buttons should have received generic arguments. Protocol and system activation buttons shouldn't have had any arguments changed. + var actions = builder.Content.Actions as ToastActionsCustom; + + var button1 = actions.Buttons[0] as ToastButton; + Assert.AreEqual("Accept", button1.Content); + Assert.AreEqual("action=accept;userId=542", button1.Arguments); + + var button2 = actions.Buttons[1]; + Assert.IsInstanceOfType(button2, typeof(ToastButtonSnooze)); + + var button3 = actions.Buttons[2] as ToastButton; + Assert.AreEqual("View", button3.Content); + Assert.AreEqual("https://msn.com", button3.Arguments); + + var button4 = actions.Buttons[3] as ToastButton; + Assert.AreEqual("Decline", button4.Content); + Assert.AreEqual("action=decline;userId=542", button4.Arguments); + + var button5 = actions.Buttons[4] as ToastButton; + Assert.AreEqual("Report", button5.Content); + Assert.AreEqual("https://microsoft.com/", button5.Arguments); + } - var button1 = actions.Buttons[0] as ToastButton; - Assert.AreEqual("Accept", button1.Content); - Assert.AreEqual("myAcceptStr", button1.Arguments); + [TestMethod] + public void AddArgumentTest_ReplacingWithinButton_ReturnSelfWithArgumentsAdded() + { + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder + .AddButton(new ToastButton() + .SetContent("Accept") + .AddArgument("action", "accept") + .AddArgument("userId", 601) + .SetBackgroundActivation()) + + // Add generic arguments halfway through (in this case shouldn't overwrite anything) + .AddArgument("userId", 542) + + .AddButton(new ToastButton() + .SetContent("Decline") + .AddArgument("action", "decline") + .AddArgument("userId", 601) + .SetBackgroundActivation()); + + // Assert + Assert.AreSame(builder, anotherReference); + + // Top level arguments should be present + Assert.AreEqual("userId=542", builder.Content.Launch); + + // Buttons should have overridden the generic userId + var actions = builder.Content.Actions as ToastActionsCustom; + + var button1 = actions.Buttons[0] as ToastButton; + Assert.AreEqual("Accept", button1.Content); + Assert.AreEqual("action=accept;userId=601", button1.Arguments); + + var button2 = actions.Buttons[1] as ToastButton; + Assert.AreEqual("Decline", button2.Content); + Assert.AreEqual("action=decline;userId=601", button2.Arguments); + } - var button2 = actions.Buttons[1] as ToastButton; - Assert.AreEqual("Decline", button2.Content); - Assert.AreEqual("myDeclineStr", button2.Arguments); + [TestMethod] + public void AddArgumentTest_AvoidModifyingCustomButtons_ReturnSelfWithArgumentsAdded() + { + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder + .AddToastActivationInfo("myCustomLaunchStr", ToastActivationType.Foreground) - var button3 = actions.Buttons[2] as ToastButton; - Assert.AreEqual("View", button3.Content); - Assert.AreEqual("action=view;userId=542", button3.Arguments); - } + .AddButton("Accept", ToastActivationType.Background, "myAcceptStr") - [TestMethod] - public void AddArgumentTest_BackgroundActivation_ReturnSelfWithArgumentsAdded() - { - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder - .AddArgument("userId", 542) - .SetBackgroundActivation(); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual("userId=542", builder.Content.Launch); - Assert.AreEqual(ToastActivationType.Background, builder.Content.ActivationType); - } - - [TestMethod] - public void SetProtocolActivationTest_ReturnSelfWithArgumentsAdded() - { - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder - .AddButton(new ToastButton() - .SetContent("Accept") - .AddArgument("action", "accept") - .SetBackgroundActivation()) + // userId shouldn't be added to any of these except view + .AddArgument("userId", 542) - .AddArgument("userId", 542) + .AddButton("Decline", ToastActivationType.Background, "myDeclineStr") - .SetProtocolActivation(new Uri("https://msn.com/")) + .AddButton(new ToastButton() + .SetContent("View") + .AddArgument("action", "view")); - .AddArgument("name", "Andrew") + // Assert + Assert.AreSame(builder, anotherReference); - .AddButton(new ToastButton() - .SetContent("Decline") - .AddArgument("action", "decline") - .SetBackgroundActivation()); + // Top level arguments should be the custom string since user set that + Assert.AreEqual("myCustomLaunchStr", builder.Content.Launch); - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual("https://msn.com/", builder.Content.Launch); - Assert.AreEqual(ToastActivationType.Protocol, builder.Content.ActivationType); + // Buttons should have their custom strings except the last + var actions = builder.Content.Actions as ToastActionsCustom; - var actions = builder.Content.Actions as ToastActionsCustom; + var button1 = actions.Buttons[0] as ToastButton; + Assert.AreEqual("Accept", button1.Content); + Assert.AreEqual("myAcceptStr", button1.Arguments); - var button1 = actions.Buttons[0] as ToastButton; - Assert.AreEqual("Accept", button1.Content); - Assert.AreEqual("action=accept;userId=542;name=Andrew", button1.Arguments); + var button2 = actions.Buttons[1] as ToastButton; + Assert.AreEqual("Decline", button2.Content); + Assert.AreEqual("myDeclineStr", button2.Arguments); - var button2 = actions.Buttons[1] as ToastButton; - Assert.AreEqual("Decline", button2.Content); - Assert.AreEqual("action=decline;userId=542;name=Andrew", button2.Arguments); - } + var button3 = actions.Buttons[2] as ToastButton; + Assert.AreEqual("View", button3.Content); + Assert.AreEqual("action=view;userId=542", button3.Arguments); + } - [TestMethod] - public void ToastButtonBuilders_General_ReturnSelf() - { - ToastButton button = new ToastButton(); - ToastButton anotherReference = button - .SetContent("View") - .AddArgument("action", "view") - .AddArgument("imageId", 601); + [TestMethod] + public void AddArgumentTest_BackgroundActivation_ReturnSelfWithArgumentsAdded() + { + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder + .AddArgument("userId", 542) + .SetBackgroundActivation(); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual("userId=542", builder.Content.Launch); + Assert.AreEqual(ToastActivationType.Background, builder.Content.ActivationType); + } - Assert.AreSame(button, anotherReference); - Assert.AreEqual("View", button.Content); - Assert.AreEqual("action=view;imageId=601", button.Arguments); - Assert.AreEqual(ToastActivationType.Foreground, button.ActivationType); - } + [TestMethod] + public void SetProtocolActivationTest_ReturnSelfWithArgumentsAdded() + { + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder + .AddButton(new ToastButton() + .SetContent("Accept") + .AddArgument("action", "accept") + .SetBackgroundActivation()) - [TestMethod] - public void ToastButtonBuilders_AllProperties_ReturnSelf() - { - ToastButton button = new ToastButton(); - ToastButton anotherReference = button - .SetContent("View") - .SetImageUri(new Uri("ms-appx:///Assets/view.png")) - .AddArgument("action", "view") - .SetBackgroundActivation() - .SetAfterActivationBehavior(ToastAfterActivationBehavior.PendingUpdate) - .SetHintActionId("viewImage"); - - Assert.AreSame(button, anotherReference); - Assert.AreEqual("View", button.Content); - Assert.AreEqual("action=view", button.Arguments); - Assert.AreEqual("ms-appx:///Assets/view.png", button.ImageUri); - Assert.AreEqual(ToastActivationType.Background, button.ActivationType); - Assert.AreEqual(ToastAfterActivationBehavior.PendingUpdate, button.ActivationOptions.AfterActivationBehavior); - Assert.AreEqual("viewImage", button.HintActionId); - } - - [TestMethod] - public void ToastButtonBuilders_ProtocolActivation_ReturnSelf() - { - ToastButton button = new ToastButton(); - ToastButton anotherReference = button - .SetContent("View") - .SetProtocolActivation(new Uri("https://msn.com")); + .AddArgument("userId", 542) - Assert.AreSame(button, anotherReference); - Assert.AreEqual("View", button.Content); - Assert.AreEqual("https://msn.com/", button.Arguments); - Assert.AreEqual(ToastActivationType.Protocol, button.ActivationType); - } + .SetProtocolActivation(new Uri("https://msn.com/")) - [TestMethod] - public void ToastButtonBuilders_ProtocolActivationWithPfn_ReturnSelf() - { - ToastButton button = new ToastButton(); - ToastButton anotherReference = button - .SetContent("View") - .SetProtocolActivation(new Uri("https://msn.com"), "MyPfn"); - - Assert.AreSame(button, anotherReference); - Assert.AreEqual("View", button.Content); - Assert.AreEqual("https://msn.com/", button.Arguments); - Assert.AreEqual(ToastActivationType.Protocol, button.ActivationType); - Assert.AreEqual("MyPfn", button.ActivationOptions.ProtocolActivationTargetApplicationPfn); - } - - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void ToastButtonBuilders_InvalidProtocolAfterArguments_ReturnSelf() - { - new ToastButton() - .SetContent("View") - .AddArgument("action", "view") - .SetProtocolActivation(new Uri("https://msn.com")); - } + .AddArgument("name", "Andrew") - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void ToastButtonBuilders_InvalidDismissAfterArguments_ReturnSelf() - { - new ToastButton() - .SetContent("View") - .AddArgument("action", "view") - .SetDismissActivation(); - } + .AddButton(new ToastButton() + .SetContent("Decline") + .AddArgument("action", "decline") + .SetBackgroundActivation()); - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void ToastButtonBuilders_InvalidSnoozeAfterArguments_ReturnSelf() - { - new ToastButton() - .SetContent("View") - .AddArgument("action", "view") - .SetSnoozeActivation(); - } + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual("https://msn.com/", builder.Content.Launch); + Assert.AreEqual(ToastActivationType.Protocol, builder.Content.ActivationType); - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void ToastButtonBuilders_InvalidSnoozeWithIdAfterArguments_ReturnSelf() - { - new ToastButton() - .SetContent("View") - .AddArgument("action", "view") - .SetSnoozeActivation("snoozeId"); - } + var actions = builder.Content.Actions as ToastActionsCustom; - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void ToastButtonBuilders_InvalidArgumentsAfterProtocol_ReturnSelf() - { - new ToastButton() - .SetContent("View") - .SetProtocolActivation(new Uri("https://msn.com")) - .AddArgument("action", "view"); - } + var button1 = actions.Buttons[0] as ToastButton; + Assert.AreEqual("Accept", button1.Content); + Assert.AreEqual("action=accept;userId=542;name=Andrew", button1.Arguments); - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void ToastButtonBuilders_InvalidArgumentsAfterCustomArguments_ReturnSelf() - { - var button = new ToastButton("View", "viewArgs"); + var button2 = actions.Buttons[1] as ToastButton; + Assert.AreEqual("Decline", button2.Content); + Assert.AreEqual("action=decline;userId=542;name=Andrew", button2.Arguments); + } - button.AddArgument("action", "view"); - } + [TestMethod] + public void ToastButtonBuilders_General_ReturnSelf() + { + ToastButton button = new ToastButton(); + ToastButton anotherReference = button + .SetContent("View") + .AddArgument("action", "view") + .AddArgument("imageId", 601); + + Assert.AreSame(button, anotherReference); + Assert.AreEqual("View", button.Content); + Assert.AreEqual("action=view;imageId=601", button.Arguments); + Assert.AreEqual(ToastActivationType.Foreground, button.ActivationType); + } - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void ToastButtonBuilders_InvalidArgumentsAfterSnooze_ReturnSelf() - { - new ToastButton() - .SetContent("Later") - .SetSnoozeActivation() - .AddArgument("action", "later"); - } - - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void ToastButtonBuilders_InvalidArgumentsAfterSnoozeWithId_ReturnSelf() - { - new ToastButton() - .SetContent("Later") - .SetSnoozeActivation("myId") - .AddArgument("action", "later"); - } - - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void ToastButtonBuilders_InvalidArgumentsAfterDismissActivation_ReturnSelf() - { - new ToastButton() - .SetContent("Later") - .SetDismissActivation() - .AddArgument("action", "later"); - } - - [TestMethod] - public void SetToastDurationTest_WithCustomToastDuration_ReturnSelfWithCustomToastDurationSet() - { - // Arrange - ToastDuration testToastDuration = ToastDuration.Long; + [TestMethod] + public void ToastButtonBuilders_AllProperties_ReturnSelf() + { + ToastButton button = new ToastButton(); + ToastButton anotherReference = button + .SetContent("View") + .SetImageUri(new Uri("ms-appx:///Assets/view.png")) + .AddArgument("action", "view") + .SetBackgroundActivation() + .SetAfterActivationBehavior(ToastAfterActivationBehavior.PendingUpdate) + .SetHintActionId("viewImage"); + + Assert.AreSame(button, anotherReference); + Assert.AreEqual("View", button.Content); + Assert.AreEqual("action=view", button.Arguments); + Assert.AreEqual("ms-appx:///Assets/view.png", button.ImageUri); + Assert.AreEqual(ToastActivationType.Background, button.ActivationType); + Assert.AreEqual(ToastAfterActivationBehavior.PendingUpdate, button.ActivationOptions.AfterActivationBehavior); + Assert.AreEqual("viewImage", button.HintActionId); + } - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.SetToastDuration(testToastDuration); + [TestMethod] + public void ToastButtonBuilders_ProtocolActivation_ReturnSelf() + { + ToastButton button = new ToastButton(); + ToastButton anotherReference = button + .SetContent("View") + .SetProtocolActivation(new Uri("https://msn.com")); + + Assert.AreSame(button, anotherReference); + Assert.AreEqual("View", button.Content); + Assert.AreEqual("https://msn.com/", button.Arguments); + Assert.AreEqual(ToastActivationType.Protocol, button.ActivationType); + } - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testToastDuration, builder.Content.Duration); - } + [TestMethod] + public void ToastButtonBuilders_ProtocolActivationWithPfn_ReturnSelf() + { + ToastButton button = new ToastButton(); + ToastButton anotherReference = button + .SetContent("View") + .SetProtocolActivation(new Uri("https://msn.com"), "MyPfn"); + + Assert.AreSame(button, anotherReference); + Assert.AreEqual("View", button.Content); + Assert.AreEqual("https://msn.com/", button.Arguments); + Assert.AreEqual(ToastActivationType.Protocol, button.ActivationType); + Assert.AreEqual("MyPfn", button.ActivationOptions.ProtocolActivationTargetApplicationPfn); + } - [TestMethod] - public void SetToastScenarioTest_WithCustomToastScenario_ReturnSelfWithCustomToastScenarioSet() - { - // Arrange - ToastScenario testToastScenario = ToastScenario.Default; + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void ToastButtonBuilders_InvalidProtocolAfterArguments_ReturnSelf() + { + new ToastButton() + .SetContent("View") + .AddArgument("action", "view") + .SetProtocolActivation(new Uri("https://msn.com")); + } - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.SetToastScenario(testToastScenario); + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void ToastButtonBuilders_InvalidDismissAfterArguments_ReturnSelf() + { + new ToastButton() + .SetContent("View") + .AddArgument("action", "view") + .SetDismissActivation(); + } - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testToastScenario, builder.Content.Scenario); - } + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void ToastButtonBuilders_InvalidSnoozeAfterArguments_ReturnSelf() + { + new ToastButton() + .SetContent("View") + .AddArgument("action", "view") + .SetSnoozeActivation(); + } - [TestMethod] - public void AddAudioTest_WithAudioUriOnly_ReturnSelfWithCustomAudioAdded() - { - // Arrange - Uri testAudioUriSrc = new Uri("C:/justatesturi.mp3"); + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void ToastButtonBuilders_InvalidSnoozeWithIdAfterArguments_ReturnSelf() + { + new ToastButton() + .SetContent("View") + .AddArgument("action", "view") + .SetSnoozeActivation("snoozeId"); + } - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddAudio(testAudioUriSrc); + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void ToastButtonBuilders_InvalidArgumentsAfterProtocol_ReturnSelf() + { + new ToastButton() + .SetContent("View") + .SetProtocolActivation(new Uri("https://msn.com")) + .AddArgument("action", "view"); + } - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testAudioUriSrc.OriginalString, builder.Content.Audio.Src.OriginalString); - } + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void ToastButtonBuilders_InvalidArgumentsAfterCustomArguments_ReturnSelf() + { + var button = new ToastButton("View", "viewArgs"); - [TestMethod] - public void AddAudioTest_WithFullArgs_ReturnSelfWithCustomAudioAddedWithAllOptionsSet() - { - // Arrange - Uri testAudioUriSrc = new Uri("C:/justatesturi.mp3"); - bool testToastAudioLoop = true; - bool testToastAudioSilent = true; - - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddAudio(testAudioUriSrc, testToastAudioLoop, testToastAudioSilent); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testAudioUriSrc.OriginalString, builder.Content.Audio.Src.OriginalString); - Assert.AreEqual(testToastAudioLoop, builder.Content.Audio.Loop); - Assert.AreEqual(testToastAudioSilent, builder.Content.Audio.Silent); - } - - [TestMethod] - public void AddAudioTest_WithMsWinSoundEvent_ReturnSelfWithCustomAudioAdded() - { - // Arrange - Uri testAudioUriSrc = new Uri("ms-winsoundevent:Notification.Reminder"); + button.AddArgument("action", "view"); + } - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddAudio(testAudioUriSrc); + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void ToastButtonBuilders_InvalidArgumentsAfterSnooze_ReturnSelf() + { + new ToastButton() + .SetContent("Later") + .SetSnoozeActivation() + .AddArgument("action", "later"); + } - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testAudioUriSrc.OriginalString, builder.Content.Audio.Src.OriginalString); - } + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void ToastButtonBuilders_InvalidArgumentsAfterSnoozeWithId_ReturnSelf() + { + new ToastButton() + .SetContent("Later") + .SetSnoozeActivation("myId") + .AddArgument("action", "later"); + } - [TestMethod] - public void AddAudioTest_WithMsAppx_ReturnSelfWithCustomAudioAdded() - { - // Arrange - Uri testAudioUriSrc = new Uri("ms-appx:///Assets/Audio.mp3"); + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void ToastButtonBuilders_InvalidArgumentsAfterDismissActivation_ReturnSelf() + { + new ToastButton() + .SetContent("Later") + .SetDismissActivation() + .AddArgument("action", "later"); + } - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddAudio(testAudioUriSrc); + [TestMethod] + public void SetToastDurationTest_WithCustomToastDuration_ReturnSelfWithCustomToastDurationSet() + { + // Arrange + ToastDuration testToastDuration = ToastDuration.Long; - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testAudioUriSrc.OriginalString, builder.Content.Audio.Src.OriginalString); - } + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.SetToastDuration(testToastDuration); - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void AddAudioTest_WithInvalidMsUri_ThrowException() - { - // Arrange - Uri testAudioUriSrc = new Uri("ms-doesntexist:Notification.Reminder"); + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testToastDuration, builder.Content.Duration); + } - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - builder.AddAudio(testAudioUriSrc); - } + [TestMethod] + public void SetToastScenarioTest_WithCustomToastScenario_ReturnSelfWithCustomToastScenarioSet() + { + // Arrange + ToastScenario testToastScenario = ToastScenario.Default; - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void AddAudioTest_WithInvalidAppDataUri_ThrowException() - { - // Arrange (ms-appdata isn't currently supported) - Uri testAudioUriSrc = new Uri("ms-appdata:///local/Sound.mp3"); + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.SetToastScenario(testToastScenario); - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - builder.AddAudio(testAudioUriSrc); - } + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testToastScenario, builder.Content.Scenario); + } - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void AddAudioTest_WithInvalidHttpUri_ThrowException() - { - // Arrange - Uri testAudioUriSrc = new Uri("https://myaudio.com/song.mp3"); + [TestMethod] + public void AddAudioTest_WithAudioUriOnly_ReturnSelfWithCustomAudioAdded() + { + // Arrange + Uri testAudioUriSrc = new Uri("C:/justatesturi.mp3"); - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - builder.AddAudio(testAudioUriSrc); - } + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddAudio(testAudioUriSrc); - [TestMethod] - public void AddAudioTest_WithAudioObject_ReturnSelfWithCustomAudioAdded() - { - // Arrange - var audio = new ToastAudio() - { - Silent = true - }; + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testAudioUriSrc.OriginalString, builder.Content.Audio.Src.OriginalString); + } - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddAudio(audio); + [TestMethod] + public void AddAudioTest_WithFullArgs_ReturnSelfWithCustomAudioAddedWithAllOptionsSet() + { + // Arrange + Uri testAudioUriSrc = new Uri("C:/justatesturi.mp3"); + bool testToastAudioLoop = true; + bool testToastAudioSilent = true; + + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddAudio(testAudioUriSrc, testToastAudioLoop, testToastAudioSilent); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testAudioUriSrc.OriginalString, builder.Content.Audio.Src.OriginalString); + Assert.AreEqual(testToastAudioLoop, builder.Content.Audio.Loop); + Assert.AreEqual(testToastAudioSilent, builder.Content.Audio.Silent); + } - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreSame(audio, builder.Content.Audio); - } + [TestMethod] + public void AddAudioTest_WithMsWinSoundEvent_ReturnSelfWithCustomAudioAdded() + { + // Arrange + Uri testAudioUriSrc = new Uri("ms-winsoundevent:Notification.Reminder"); - [TestMethod] - public void AddAttributionTextTest_WithSimpleText_ReturnSelfWithCustomAttributionTextAdded() - { - // Arrange - string testAttributionText = "Test Attribution Text"; + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddAudio(testAudioUriSrc); - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddAttributionText(testAttributionText); + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testAudioUriSrc.OriginalString, builder.Content.Audio.Src.OriginalString); + } - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testAttributionText, builder.Content.Visual.BindingGeneric.Attribution.Text); - } + [TestMethod] + public void AddAudioTest_WithMsAppx_ReturnSelfWithCustomAudioAdded() + { + // Arrange + Uri testAudioUriSrc = new Uri("ms-appx:///Assets/Audio.mp3"); - [TestMethod] - public void AddAttributionTextTest_WithTextAndLanguage_ReturnSelfWithCustomAttributionTextAndLanguageAdded() - { - // Arrange - string testAttributionText = "Test Attribution Text"; - string testAttributionTextLanguage = "en-US"; - - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddAttributionText(testAttributionText, testAttributionTextLanguage); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testAttributionText, builder.Content.Visual.BindingGeneric.Attribution.Text); - Assert.AreEqual(testAttributionTextLanguage, builder.Content.Visual.BindingGeneric.Attribution.Language); - } - - [TestMethod] - public void AddAppLogoOverrideTest_WithLogoUriOnly_ReturnSelfWithCustomLogoAdded() - { - // Arrange - Uri testAppLogoUriSrc = new Uri("C:/justatesturi.jpg"); + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddAudio(testAudioUriSrc); - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddAppLogoOverride(testAppLogoUriSrc); + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testAudioUriSrc.OriginalString, builder.Content.Audio.Src.OriginalString); + } - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testAppLogoUriSrc.OriginalString, builder.Content.Visual.BindingGeneric.AppLogoOverride.Source); - } + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void AddAudioTest_WithInvalidMsUri_ThrowException() + { + // Arrange + Uri testAudioUriSrc = new Uri("ms-doesntexist:Notification.Reminder"); - [TestMethod] - public void AddAppLogoOverrideTest_WithCustomLogoAndFullOptions_ReturnSelfWithCustomLogoAndOptionsAdded() - { - // Arrange - Uri testAppLogoUriSrc = new Uri("C:/justatesturi.jpg"); - ToastGenericAppLogoCrop testCropOption = ToastGenericAppLogoCrop.Circle; - string testLogoAltText = "Test Logo Alt Text"; - bool testLogoAddImageQuery = true; - - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddAppLogoOverride(testAppLogoUriSrc, testCropOption, testLogoAltText, testLogoAddImageQuery); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testAppLogoUriSrc.OriginalString, builder.Content.Visual.BindingGeneric.AppLogoOverride.Source); - Assert.AreEqual(testCropOption, builder.Content.Visual.BindingGeneric.AppLogoOverride.HintCrop); - Assert.AreEqual(testLogoAltText, builder.Content.Visual.BindingGeneric.AppLogoOverride.AlternateText); - Assert.AreEqual(testLogoAddImageQuery, builder.Content.Visual.BindingGeneric.AppLogoOverride.AddImageQuery); - } - - [TestMethod] - public void AddHeroImageTest_WithHeroImageUriOnly_ReturnSelfWithHeroImageAdded() - { - // Arrange - Uri testHeroImageUriSrc = new Uri("C:/justatesturi.jpg"); + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + builder.AddAudio(testAudioUriSrc); + } - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddHeroImage(testHeroImageUriSrc); + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void AddAudioTest_WithInvalidAppDataUri_ThrowException() + { + // Arrange (ms-appdata isn't currently supported) + Uri testAudioUriSrc = new Uri("ms-appdata:///local/Sound.mp3"); - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testHeroImageUriSrc.OriginalString, builder.Content.Visual.BindingGeneric.HeroImage.Source); - } + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + builder.AddAudio(testAudioUriSrc); + } - [TestMethod] - public void AddHeroImageTest_WithHeroImageUriAndFullOptions_ReturnSelfWithHeroImageAndOptionsAdded() - { - // Arrange - Uri testHeroImageUriSrc = new Uri("C:/justatesturi.jpg"); - string testHeroImageAltText = "Test Hero Image Text"; - bool testHeroImageAddImageQuery = true; - - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddHeroImage(testHeroImageUriSrc, testHeroImageAltText, testHeroImageAddImageQuery); - - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testHeroImageUriSrc.OriginalString, builder.Content.Visual.BindingGeneric.HeroImage.Source); - Assert.AreEqual(testHeroImageAltText, builder.Content.Visual.BindingGeneric.HeroImage.AlternateText); - Assert.AreEqual(testHeroImageAddImageQuery, builder.Content.Visual.BindingGeneric.HeroImage.AddImageQuery); - } - - [TestMethod] - public void AddInlineImageTest_WithInlineImageUriOnly_ReturnSelfWithInlineImageAdded() + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void AddAudioTest_WithInvalidHttpUri_ThrowException() + { + // Arrange + Uri testAudioUriSrc = new Uri("https://myaudio.com/song.mp3"); + + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + builder.AddAudio(testAudioUriSrc); + } + + [TestMethod] + public void AddAudioTest_WithAudioObject_ReturnSelfWithCustomAudioAdded() + { + // Arrange + var audio = new ToastAudio() { - // Arrange - Uri testInlineImageUriSrc = new Uri("C:/justatesturi.jpg"); + Silent = true + }; - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddInlineImage(testInlineImageUriSrc); + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddAudio(audio); - // Assert - Assert.AreSame(builder, anotherReference); - Assert.AreEqual(testInlineImageUriSrc.OriginalString, (builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveImage).Source); - } + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreSame(audio, builder.Content.Audio); + } - [TestMethod] - public void AddInlineImageTest_WithInlineImageAndFullOptions_ReturnSelfWithInlineImageAndOptionsAdded() - { - // Arrange - Uri testInlineImageUriSrc = new Uri("C:/justatesturi.jpg"); - string testInlineImageAltText = "Test Inline Image Text"; - bool testInlineImageAddImageQuery = true; + [TestMethod] + public void AddAttributionTextTest_WithSimpleText_ReturnSelfWithCustomAttributionTextAdded() + { + // Arrange + string testAttributionText = "Test Attribution Text"; - // Act - ToastContentBuilder builder = new ToastContentBuilder(); - ToastContentBuilder anotherReference = builder.AddInlineImage(testInlineImageUriSrc, testInlineImageAltText, testInlineImageAddImageQuery); + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddAttributionText(testAttributionText); - // Assert - Assert.AreSame(builder, anotherReference); + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testAttributionText, builder.Content.Visual.BindingGeneric.Attribution.Text); + } - var image = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveImage; + [TestMethod] + public void AddAttributionTextTest_WithTextAndLanguage_ReturnSelfWithCustomAttributionTextAndLanguageAdded() + { + // Arrange + string testAttributionText = "Test Attribution Text"; + string testAttributionTextLanguage = "en-US"; + + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddAttributionText(testAttributionText, testAttributionTextLanguage); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testAttributionText, builder.Content.Visual.BindingGeneric.Attribution.Text); + Assert.AreEqual(testAttributionTextLanguage, builder.Content.Visual.BindingGeneric.Attribution.Language); + } - Assert.AreEqual(testInlineImageUriSrc.OriginalString, image.Source); - Assert.AreEqual(testInlineImageAltText, image.AlternateText); - Assert.AreEqual(testInlineImageAddImageQuery, image.AddImageQuery); - } + [TestMethod] + public void AddAppLogoOverrideTest_WithLogoUriOnly_ReturnSelfWithCustomLogoAdded() + { + // Arrange + Uri testAppLogoUriSrc = new Uri("C:/justatesturi.jpg"); - [TestMethod] - public void AddProgressBarTest_WithoutInputArgs_ReturnSelfWithNonIndeterminateBindableProgressBarAdded() - { - // Arrange - ToastContentBuilder builder = new ToastContentBuilder(); + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddAppLogoOverride(testAppLogoUriSrc); - // Act - ToastContentBuilder anotherReference = builder.AddProgressBar(); + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testAppLogoUriSrc.OriginalString, builder.Content.Visual.BindingGeneric.AppLogoOverride.Source); + } - // Assert - Assert.AreSame(builder, anotherReference); - var progressBar = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveProgressBar; + [TestMethod] + public void AddAppLogoOverrideTest_WithCustomLogoAndFullOptions_ReturnSelfWithCustomLogoAndOptionsAdded() + { + // Arrange + Uri testAppLogoUriSrc = new Uri("C:/justatesturi.jpg"); + ToastGenericAppLogoCrop testCropOption = ToastGenericAppLogoCrop.Circle; + string testLogoAltText = "Test Logo Alt Text"; + bool testLogoAddImageQuery = true; + + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddAppLogoOverride(testAppLogoUriSrc, testCropOption, testLogoAltText, testLogoAddImageQuery); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testAppLogoUriSrc.OriginalString, builder.Content.Visual.BindingGeneric.AppLogoOverride.Source); + Assert.AreEqual(testCropOption, builder.Content.Visual.BindingGeneric.AppLogoOverride.HintCrop); + Assert.AreEqual(testLogoAltText, builder.Content.Visual.BindingGeneric.AppLogoOverride.AlternateText); + Assert.AreEqual(testLogoAddImageQuery, builder.Content.Visual.BindingGeneric.AppLogoOverride.AddImageQuery); + } - Assert.IsNotNull(progressBar.Title.BindingName); - Assert.IsNotNull(progressBar.Value.BindingName); - Assert.IsNotNull(progressBar.ValueStringOverride.BindingName); - Assert.IsNotNull(progressBar.Status.BindingName); - } + [TestMethod] + public void AddHeroImageTest_WithHeroImageUriOnly_ReturnSelfWithHeroImageAdded() + { + // Arrange + Uri testHeroImageUriSrc = new Uri("C:/justatesturi.jpg"); - [TestMethod] - public void AddProgressBarTest_WithFixedPropertiesAndDeterminateValue_ReturnSelfWithFixedValueAndPropertiesProgressBarAdded() - { - // Arrange - string testProgressBarTitle = "Test Progress Bar Title"; - double testProgressBarValue = 0.25; - string testValueStringOverride = "Test Value String Override"; - string testProgressBarStatus = "Test Progress Bar Status"; + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddHeroImage(testHeroImageUriSrc); - ToastContentBuilder builder = new ToastContentBuilder(); + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testHeroImageUriSrc.OriginalString, builder.Content.Visual.BindingGeneric.HeroImage.Source); + } - // Act - ToastContentBuilder anotherReference = builder.AddProgressBar(testProgressBarTitle, testProgressBarValue, false, testValueStringOverride, testProgressBarStatus); + [TestMethod] + public void AddHeroImageTest_WithHeroImageUriAndFullOptions_ReturnSelfWithHeroImageAndOptionsAdded() + { + // Arrange + Uri testHeroImageUriSrc = new Uri("C:/justatesturi.jpg"); + string testHeroImageAltText = "Test Hero Image Text"; + bool testHeroImageAddImageQuery = true; + + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddHeroImage(testHeroImageUriSrc, testHeroImageAltText, testHeroImageAddImageQuery); + + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testHeroImageUriSrc.OriginalString, builder.Content.Visual.BindingGeneric.HeroImage.Source); + Assert.AreEqual(testHeroImageAltText, builder.Content.Visual.BindingGeneric.HeroImage.AlternateText); + Assert.AreEqual(testHeroImageAddImageQuery, builder.Content.Visual.BindingGeneric.HeroImage.AddImageQuery); + } - // Assert - Assert.AreSame(builder, anotherReference); - var progressBar = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveProgressBar; + [TestMethod] + public void AddInlineImageTest_WithInlineImageUriOnly_ReturnSelfWithInlineImageAdded() + { + // Arrange + Uri testInlineImageUriSrc = new Uri("C:/justatesturi.jpg"); - Assert.IsNull(progressBar.Title.BindingName); - Assert.AreEqual(testProgressBarTitle, (string)progressBar.Title); + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddInlineImage(testInlineImageUriSrc); - Assert.IsNull(progressBar.Value.BindingName); - Assert.AreEqual(testProgressBarValue, ((AdaptiveProgressBarValue)progressBar.Value).Value); + // Assert + Assert.AreSame(builder, anotherReference); + Assert.AreEqual(testInlineImageUriSrc.OriginalString, (builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveImage).Source); + } - Assert.IsNull(progressBar.ValueStringOverride.BindingName); - Assert.AreEqual(testValueStringOverride, (string)progressBar.ValueStringOverride); + [TestMethod] + public void AddInlineImageTest_WithInlineImageAndFullOptions_ReturnSelfWithInlineImageAndOptionsAdded() + { + // Arrange + Uri testInlineImageUriSrc = new Uri("C:/justatesturi.jpg"); + string testInlineImageAltText = "Test Inline Image Text"; + bool testInlineImageAddImageQuery = true; - Assert.IsNull(progressBar.Status.BindingName); - Assert.AreEqual(testProgressBarStatus, (string)progressBar.Status); - } + // Act + ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder anotherReference = builder.AddInlineImage(testInlineImageUriSrc, testInlineImageAltText, testInlineImageAddImageQuery); - [TestMethod] - public void AddProgressBarTest_WithIndeterminateValue_ReturnSelfWithIndeterminateProgressBarAdded() - { - // Arrange - ToastContentBuilder builder = new ToastContentBuilder(); + // Assert + Assert.AreSame(builder, anotherReference); - // Act - ToastContentBuilder anotherReference = builder.AddProgressBar(isIndeterminate: true); + var image = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveImage; - // Assert - Assert.AreSame(builder, anotherReference); - var progressBar = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveProgressBar; + Assert.AreEqual(testInlineImageUriSrc.OriginalString, image.Source); + Assert.AreEqual(testInlineImageAltText, image.AlternateText); + Assert.AreEqual(testInlineImageAddImageQuery, image.AddImageQuery); + } - Assert.IsTrue(((AdaptiveProgressBarValue)progressBar.Value).IsIndeterminate); - } + [TestMethod] + public void AddProgressBarTest_WithoutInputArgs_ReturnSelfWithNonIndeterminateBindableProgressBarAdded() + { + // Arrange + ToastContentBuilder builder = new ToastContentBuilder(); - [TestMethod] - public void AddTextTest_WithSimpleText_ReturnSelfWithTextAdded() - { - // Arrange - string testText = "Test Text"; - ToastContentBuilder builder = new ToastContentBuilder(); + // Act + ToastContentBuilder anotherReference = builder.AddProgressBar(); - // Act - ToastContentBuilder anotherReference = builder.AddText(testText); + // Assert + Assert.AreSame(builder, anotherReference); + var progressBar = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveProgressBar; - // Assert - Assert.AreSame(builder, anotherReference); - var text = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveText; + Assert.IsNotNull(progressBar.Title.BindingName); + Assert.IsNotNull(progressBar.Value.BindingName); + Assert.IsNotNull(progressBar.ValueStringOverride.BindingName); + Assert.IsNotNull(progressBar.Status.BindingName); + } - Assert.AreEqual(testText, (string)text.Text); - } + [TestMethod] + public void AddProgressBarTest_WithFixedPropertiesAndDeterminateValue_ReturnSelfWithFixedValueAndPropertiesProgressBarAdded() + { + // Arrange + string testProgressBarTitle = "Test Progress Bar Title"; + double testProgressBarValue = 0.25; + string testValueStringOverride = "Test Value String Override"; + string testProgressBarStatus = "Test Progress Bar Status"; - [TestMethod] - public void AddTextTest_WithMultipleTexts_ReturnSelfWithAllTextsAdded() - { - // Arrange - string testText1 = "Test Header"; - string testText2 = "Test Text"; - string testText3 = "Test Text Again"; - ToastContentBuilder builder = new ToastContentBuilder(); - - // Act - ToastContentBuilder anotherReference = builder.AddText(testText1) - .AddText(testText2) - .AddText(testText3); - - // Assert - Assert.AreSame(builder, anotherReference); - var texts = builder.Content.Visual.BindingGeneric.Children.Take(3).Cast().ToList(); - - Assert.AreEqual(testText1, (string)texts[0].Text); - Assert.AreEqual(testText2, (string)texts[1].Text); - Assert.AreEqual(testText3, (string)texts[2].Text); - } - - [TestMethod] - public void AddTextTest_WithTextAndFullOptions_ReturnSelfWithTextAndAllOptionsAdded() - { - // Arrange - string testText = "Test Text"; - AdaptiveTextStyle testStyle = AdaptiveTextStyle.Header; - bool testWrapHint = true; - int testHintMaxLine = 2; - int testHintMinLine = 1; - AdaptiveTextAlign testAlign = AdaptiveTextAlign.Auto; - string testLanguage = "en-US"; - - ToastContentBuilder builder = new ToastContentBuilder(); - - // Act - ToastContentBuilder anotherReference = builder.AddText(testText, testStyle, testWrapHint, testHintMaxLine, testHintMinLine, testAlign, testLanguage); - - // Assert - Assert.AreSame(builder, anotherReference); - var text = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveText; - - Assert.AreEqual(testText, (string)text.Text); - Assert.AreEqual(testHintMaxLine, text.HintMaxLines); - Assert.AreEqual(testLanguage, text.Language); - - // These values should still be the default values, since they aren't used for top-level text - Assert.AreEqual(AdaptiveTextStyle.Default, text.HintStyle); - Assert.IsNull(text.HintWrap); - Assert.IsNull(text.HintMinLines); - Assert.AreEqual(AdaptiveTextAlign.Default, text.HintAlign); - } - - [TestMethod] - [ExpectedException(typeof(InvalidOperationException))] - public void AddTextTest_WithMoreThan4LinesOfText_ThrowInvalidOperationException() - { - // Arrange - string testText1 = "Test Header"; - string testText2 = "Test Text"; - string testText3 = "Test Text Again"; - string testText4 = "Test Text Again x2"; - ToastContentBuilder builder = new ToastContentBuilder(); - - // Act - _ = builder.AddText(testText1) - .AddText(testText2) - .AddText(testText3) - .AddText(testText4); - } - - [TestMethod] - [ExpectedException(typeof(ArgumentOutOfRangeException))] - public void AddTextTest_WithMaxLinesValueLargerThan2_ThrowArgumentOutOfRangeException() - { - // Arrange - string testText1 = "Test Header"; - ToastContentBuilder builder = new ToastContentBuilder(); + ToastContentBuilder builder = new ToastContentBuilder(); + + // Act + ToastContentBuilder anotherReference = builder.AddProgressBar(testProgressBarTitle, testProgressBarValue, false, testValueStringOverride, testProgressBarStatus); + + // Assert + Assert.AreSame(builder, anotherReference); + var progressBar = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveProgressBar; + + Assert.IsNull(progressBar.Title.BindingName); + Assert.AreEqual(testProgressBarTitle, (string)progressBar.Title); + + Assert.IsNull(progressBar.Value.BindingName); + Assert.AreEqual(testProgressBarValue, ((AdaptiveProgressBarValue)progressBar.Value).Value); + + Assert.IsNull(progressBar.ValueStringOverride.BindingName); + Assert.AreEqual(testValueStringOverride, (string)progressBar.ValueStringOverride); + + Assert.IsNull(progressBar.Status.BindingName); + Assert.AreEqual(testProgressBarStatus, (string)progressBar.Status); + } + + [TestMethod] + public void AddProgressBarTest_WithIndeterminateValue_ReturnSelfWithIndeterminateProgressBarAdded() + { + // Arrange + ToastContentBuilder builder = new ToastContentBuilder(); - // Act - _ = builder.AddText(testText1, hintMaxLines: 3); - } + // Act + ToastContentBuilder anotherReference = builder.AddProgressBar(isIndeterminate: true); - [TestMethod] - public void AddVisualChildTest_WithCustomVisual_ReturnSelfWithCustomVisualAdded() + // Assert + Assert.AreSame(builder, anotherReference); + var progressBar = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveProgressBar; + + Assert.IsTrue(((AdaptiveProgressBarValue)progressBar.Value).IsIndeterminate); + } + + [TestMethod] + public void AddTextTest_WithSimpleText_ReturnSelfWithTextAdded() + { + // Arrange + string testText = "Test Text"; + ToastContentBuilder builder = new ToastContentBuilder(); + + // Act + ToastContentBuilder anotherReference = builder.AddText(testText); + + // Assert + Assert.AreSame(builder, anotherReference); + var text = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveText; + + Assert.AreEqual(testText, (string)text.Text); + } + + [TestMethod] + public void AddTextTest_WithMultipleTexts_ReturnSelfWithAllTextsAdded() + { + // Arrange + string testText1 = "Test Header"; + string testText2 = "Test Text"; + string testText3 = "Test Text Again"; + ToastContentBuilder builder = new ToastContentBuilder(); + + // Act + ToastContentBuilder anotherReference = builder.AddText(testText1) + .AddText(testText2) + .AddText(testText3); + + // Assert + Assert.AreSame(builder, anotherReference); + var texts = builder.Content.Visual.BindingGeneric.Children.Take(3).Cast().ToList(); + + Assert.AreEqual(testText1, (string)texts[0].Text); + Assert.AreEqual(testText2, (string)texts[1].Text); + Assert.AreEqual(testText3, (string)texts[2].Text); + } + + [TestMethod] + public void AddTextTest_WithTextAndFullOptions_ReturnSelfWithTextAndAllOptionsAdded() + { + // Arrange + string testText = "Test Text"; + AdaptiveTextStyle testStyle = AdaptiveTextStyle.Header; + bool testWrapHint = true; + int testHintMaxLine = 2; + int testHintMinLine = 1; + AdaptiveTextAlign testAlign = AdaptiveTextAlign.Auto; + string testLanguage = "en-US"; + + ToastContentBuilder builder = new ToastContentBuilder(); + + // Act + ToastContentBuilder anotherReference = builder.AddText(testText, testStyle, testWrapHint, testHintMaxLine, testHintMinLine, testAlign, testLanguage); + + // Assert + Assert.AreSame(builder, anotherReference); + var text = builder.Content.Visual.BindingGeneric.Children.First() as AdaptiveText; + + Assert.AreEqual(testText, (string)text.Text); + Assert.AreEqual(testHintMaxLine, text.HintMaxLines); + Assert.AreEqual(testLanguage, text.Language); + + // These values should still be the default values, since they aren't used for top-level text + Assert.AreEqual(AdaptiveTextStyle.Default, text.HintStyle); + Assert.IsNull(text.HintWrap); + Assert.IsNull(text.HintMinLines); + Assert.AreEqual(AdaptiveTextAlign.Default, text.HintAlign); + } + + [TestMethod] + [ExpectedException(typeof(InvalidOperationException))] + public void AddTextTest_WithMoreThan4LinesOfText_ThrowInvalidOperationException() + { + // Arrange + string testText1 = "Test Header"; + string testText2 = "Test Text"; + string testText3 = "Test Text Again"; + string testText4 = "Test Text Again x2"; + ToastContentBuilder builder = new ToastContentBuilder(); + + // Act + _ = builder.AddText(testText1) + .AddText(testText2) + .AddText(testText3) + .AddText(testText4); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentOutOfRangeException))] + public void AddTextTest_WithMaxLinesValueLargerThan2_ThrowArgumentOutOfRangeException() + { + // Arrange + string testText1 = "Test Header"; + ToastContentBuilder builder = new ToastContentBuilder(); + + // Act + _ = builder.AddText(testText1, hintMaxLines: 3); + } + + [TestMethod] + public void AddVisualChildTest_WithCustomVisual_ReturnSelfWithCustomVisualAdded() + { + // Arrange + // Taken from : https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts#adaptive-content + AdaptiveGroup group = new AdaptiveGroup() { - // Arrange - // Taken from : https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts#adaptive-content - AdaptiveGroup group = new AdaptiveGroup() + Children = { - Children = + new AdaptiveSubgroup() { - new AdaptiveSubgroup() + Children = { - Children = + new AdaptiveText() + { + Text = "52 attendees", + HintStyle = AdaptiveTextStyle.Base + }, + new AdaptiveText() { - new AdaptiveText() - { - Text = "52 attendees", - HintStyle = AdaptiveTextStyle.Base - }, - new AdaptiveText() - { - Text = "23 minute drive", - HintStyle = AdaptiveTextStyle.CaptionSubtle - } + Text = "23 minute drive", + HintStyle = AdaptiveTextStyle.CaptionSubtle } - }, - new AdaptiveSubgroup() + } + }, + new AdaptiveSubgroup() + { + Children = { - Children = + new AdaptiveText() + { + Text = "1 Microsoft Way", + HintStyle = AdaptiveTextStyle.CaptionSubtle, + HintAlign = AdaptiveTextAlign.Right + }, + new AdaptiveText() { - new AdaptiveText() - { - Text = "1 Microsoft Way", - HintStyle = AdaptiveTextStyle.CaptionSubtle, - HintAlign = AdaptiveTextAlign.Right - }, - new AdaptiveText() - { - Text = "Bellevue, WA 98008", - HintStyle = AdaptiveTextStyle.CaptionSubtle, - HintAlign = AdaptiveTextAlign.Right - } + Text = "Bellevue, WA 98008", + HintStyle = AdaptiveTextStyle.CaptionSubtle, + HintAlign = AdaptiveTextAlign.Right } } } - }; - ToastContentBuilder builder = new ToastContentBuilder(); + } + }; + ToastContentBuilder builder = new ToastContentBuilder(); - // Act - ToastContentBuilder anotherReference = builder.AddVisualChild(group); + // Act + ToastContentBuilder anotherReference = builder.AddVisualChild(group); - // Assert - Assert.AreSame(builder, anotherReference); - Assert.IsInstanceOfType(builder.Content.Visual.BindingGeneric.Children.First(), typeof(AdaptiveGroup)); - } + // Assert + Assert.AreSame(builder, anotherReference); + Assert.IsInstanceOfType(builder.Content.Visual.BindingGeneric.Children.First(), typeof(AdaptiveGroup)); + } - [TestMethod] - public void AddButtonTest_WithTextOnlyButton_ReturnSelfWithButtonAdded() - { - // Arrange - string testButtonContent = "Test Button Content"; - ToastActivationType testToastActivationType = ToastActivationType.Background; - string testButtonLaunchArgs = "Test Launch Args"; - ToastContentBuilder builder = new ToastContentBuilder(); - - // Act - ToastContentBuilder anotherReference = builder.AddButton(testButtonContent, testToastActivationType, testButtonLaunchArgs); - - // Assert - Assert.AreSame(builder, anotherReference); - - var button = (builder.Content.Actions as ToastActionsCustom).Buttons.First() as ToastButton; - Assert.AreEqual(testButtonContent, button.Content); - Assert.AreEqual(testToastActivationType, button.ActivationType); - Assert.AreEqual(testButtonLaunchArgs, button.Arguments); - } - - [TestMethod] - public void AddButtonTest_WithCustomImageAndTextButton_ReturnSelfWithButtonAdded() - { - // Arrange - string testButtonContent = "Test Button Content"; - ToastActivationType testToastActivationType = ToastActivationType.Background; - string testButtonLaunchArgs = "Test Launch Args"; - Uri testImageUriSrc = new Uri("C:/justatesturi.jpg"); + [TestMethod] + public void AddButtonTest_WithTextOnlyButton_ReturnSelfWithButtonAdded() + { + // Arrange + string testButtonContent = "Test Button Content"; + ToastActivationType testToastActivationType = ToastActivationType.Background; + string testButtonLaunchArgs = "Test Launch Args"; + ToastContentBuilder builder = new ToastContentBuilder(); + + // Act + ToastContentBuilder anotherReference = builder.AddButton(testButtonContent, testToastActivationType, testButtonLaunchArgs); + + // Assert + Assert.AreSame(builder, anotherReference); + + var button = (builder.Content.Actions as ToastActionsCustom).Buttons.First() as ToastButton; + Assert.AreEqual(testButtonContent, button.Content); + Assert.AreEqual(testToastActivationType, button.ActivationType); + Assert.AreEqual(testButtonLaunchArgs, button.Arguments); + } - ToastContentBuilder builder = new ToastContentBuilder(); + [TestMethod] + public void AddButtonTest_WithCustomImageAndTextButton_ReturnSelfWithButtonAdded() + { + // Arrange + string testButtonContent = "Test Button Content"; + ToastActivationType testToastActivationType = ToastActivationType.Background; + string testButtonLaunchArgs = "Test Launch Args"; + Uri testImageUriSrc = new Uri("C:/justatesturi.jpg"); - // Act - ToastContentBuilder anotherReference = builder.AddButton(testButtonContent, testToastActivationType, testButtonLaunchArgs, testImageUriSrc); + ToastContentBuilder builder = new ToastContentBuilder(); - // Assert - Assert.AreSame(builder, anotherReference); + // Act + ToastContentBuilder anotherReference = builder.AddButton(testButtonContent, testToastActivationType, testButtonLaunchArgs, testImageUriSrc); - var button = (builder.Content.Actions as ToastActionsCustom).Buttons.First() as ToastButton; - Assert.AreEqual(testButtonContent, button.Content); - Assert.AreEqual(testToastActivationType, button.ActivationType); - Assert.AreEqual(testButtonLaunchArgs, button.Arguments); - Assert.AreEqual(testImageUriSrc.OriginalString, button.ImageUri); - } + // Assert + Assert.AreSame(builder, anotherReference); - [TestMethod] - public void AddButtonTest_WithTextBoxId_ReturnSelfWithButtonAdded() - { - // Arrange - string testInputTextBoxId = Guid.NewGuid().ToString(); - string testButtonContent = "Test Button Content"; - ToastActivationType testToastActivationType = ToastActivationType.Background; - string testButtonLaunchArgs = "Test Launch Args"; - Uri testImageUriSrc = new Uri("C:/justatesturi.jpg"); - - ToastContentBuilder builder = new ToastContentBuilder(); - - // Act - ToastContentBuilder anotherReference = builder.AddButton(testInputTextBoxId, testButtonContent, testToastActivationType, testButtonLaunchArgs, testImageUriSrc); - - // Assert - Assert.AreSame(builder, anotherReference); - - var button = (builder.Content.Actions as ToastActionsCustom).Buttons.First() as ToastButton; - Assert.AreEqual(testInputTextBoxId, button.TextBoxId); - Assert.AreEqual(testButtonContent, button.Content); - Assert.AreEqual(testToastActivationType, button.ActivationType); - Assert.AreEqual(testButtonLaunchArgs, button.Arguments); - Assert.AreEqual(testImageUriSrc.OriginalString, button.ImageUri); - } - - [TestMethod] - public void AddInputTextBoxTest_WithStringIdOnly_ReturnSelfWithInputTextBoxAdded() - { - // Arrange - string testInputTextBoxId = Guid.NewGuid().ToString(); - ToastContentBuilder builder = new ToastContentBuilder(); + var button = (builder.Content.Actions as ToastActionsCustom).Buttons.First() as ToastButton; + Assert.AreEqual(testButtonContent, button.Content); + Assert.AreEqual(testToastActivationType, button.ActivationType); + Assert.AreEqual(testButtonLaunchArgs, button.Arguments); + Assert.AreEqual(testImageUriSrc.OriginalString, button.ImageUri); + } - // Act - ToastContentBuilder anotherReference = builder.AddInputTextBox(testInputTextBoxId); + [TestMethod] + public void AddButtonTest_WithTextBoxId_ReturnSelfWithButtonAdded() + { + // Arrange + string testInputTextBoxId = Guid.NewGuid().ToString(); + string testButtonContent = "Test Button Content"; + ToastActivationType testToastActivationType = ToastActivationType.Background; + string testButtonLaunchArgs = "Test Launch Args"; + Uri testImageUriSrc = new Uri("C:/justatesturi.jpg"); + + ToastContentBuilder builder = new ToastContentBuilder(); + + // Act + ToastContentBuilder anotherReference = builder.AddButton(testInputTextBoxId, testButtonContent, testToastActivationType, testButtonLaunchArgs, testImageUriSrc); + + // Assert + Assert.AreSame(builder, anotherReference); + + var button = (builder.Content.Actions as ToastActionsCustom).Buttons.First() as ToastButton; + Assert.AreEqual(testInputTextBoxId, button.TextBoxId); + Assert.AreEqual(testButtonContent, button.Content); + Assert.AreEqual(testToastActivationType, button.ActivationType); + Assert.AreEqual(testButtonLaunchArgs, button.Arguments); + Assert.AreEqual(testImageUriSrc.OriginalString, button.ImageUri); + } - // Assert - Assert.AreSame(builder, anotherReference); - var inputTextBox = (builder.Content.Actions as ToastActionsCustom).Inputs.First() as ToastTextBox; + [TestMethod] + public void AddInputTextBoxTest_WithStringIdOnly_ReturnSelfWithInputTextBoxAdded() + { + // Arrange + string testInputTextBoxId = Guid.NewGuid().ToString(); + ToastContentBuilder builder = new ToastContentBuilder(); - Assert.AreEqual(testInputTextBoxId, inputTextBox.Id); - } + // Act + ToastContentBuilder anotherReference = builder.AddInputTextBox(testInputTextBoxId); - [TestMethod] - public void AddInputTextBoxTest_WithPlaceHolderContentAndTitle_ReturnSelfWithInputTextBoxAndAllOptionsAdded() - { - // Arrange - string testInputTextBoxId = Guid.NewGuid().ToString(); - string testInputTextBoxPlaceHolderContent = "Placeholder Content"; - string testInputTextBoxTitle = "Test Title"; - ToastContentBuilder builder = new ToastContentBuilder(); - - // Act - ToastContentBuilder anotherReference = builder.AddInputTextBox(testInputTextBoxId, testInputTextBoxPlaceHolderContent, testInputTextBoxTitle); - - // Assert - Assert.AreSame(builder, anotherReference); - var inputTextBox = (builder.Content.Actions as ToastActionsCustom).Inputs.First() as ToastTextBox; - - Assert.AreEqual(testInputTextBoxId, inputTextBox.Id); - Assert.AreEqual(testInputTextBoxPlaceHolderContent, inputTextBox.PlaceholderContent); - Assert.AreEqual(testInputTextBoxTitle, inputTextBox.Title); - } - - [TestMethod] - public void AddComboBoxTest_WithMultipleChoices_ReturnSelfWithComboBoxAndAllChoicesAdded() - { - // Arrange - string testComboBoxId = Guid.NewGuid().ToString(); - var choice1 = (Guid.NewGuid().ToString(), "Test Choice 1"); - var choice2 = (Guid.NewGuid().ToString(), "Test Choice 2"); - var choice3 = (Guid.NewGuid().ToString(), "Test Choice 3"); + // Assert + Assert.AreSame(builder, anotherReference); + var inputTextBox = (builder.Content.Actions as ToastActionsCustom).Inputs.First() as ToastTextBox; - ToastContentBuilder builder = new ToastContentBuilder(); + Assert.AreEqual(testInputTextBoxId, inputTextBox.Id); + } - // Act - ToastContentBuilder anotherReference = builder.AddComboBox(testComboBoxId, choice1, choice2, choice3); + [TestMethod] + public void AddInputTextBoxTest_WithPlaceHolderContentAndTitle_ReturnSelfWithInputTextBoxAndAllOptionsAdded() + { + // Arrange + string testInputTextBoxId = Guid.NewGuid().ToString(); + string testInputTextBoxPlaceHolderContent = "Placeholder Content"; + string testInputTextBoxTitle = "Test Title"; + ToastContentBuilder builder = new ToastContentBuilder(); + + // Act + ToastContentBuilder anotherReference = builder.AddInputTextBox(testInputTextBoxId, testInputTextBoxPlaceHolderContent, testInputTextBoxTitle); + + // Assert + Assert.AreSame(builder, anotherReference); + var inputTextBox = (builder.Content.Actions as ToastActionsCustom).Inputs.First() as ToastTextBox; + + Assert.AreEqual(testInputTextBoxId, inputTextBox.Id); + Assert.AreEqual(testInputTextBoxPlaceHolderContent, inputTextBox.PlaceholderContent); + Assert.AreEqual(testInputTextBoxTitle, inputTextBox.Title); + } - // Assert - Assert.AreSame(builder, anotherReference); - var comboBox = (builder.Content.Actions as ToastActionsCustom).Inputs.First() as ToastSelectionBox; + [TestMethod] + public void AddComboBoxTest_WithMultipleChoices_ReturnSelfWithComboBoxAndAllChoicesAdded() + { + // Arrange + string testComboBoxId = Guid.NewGuid().ToString(); + var choice1 = (Guid.NewGuid().ToString(), "Test Choice 1"); + var choice2 = (Guid.NewGuid().ToString(), "Test Choice 2"); + var choice3 = (Guid.NewGuid().ToString(), "Test Choice 3"); - Assert.AreEqual(testComboBoxId, comboBox.Id); - Assert.AreEqual(choice1.Item1, comboBox.Items[0].Id); - Assert.AreEqual(choice2.Item1, comboBox.Items[1].Id); - Assert.AreEqual(choice3.Item1, comboBox.Items[2].Id); + ToastContentBuilder builder = new ToastContentBuilder(); - Assert.AreEqual(choice1.Item2, comboBox.Items[0].Content); - Assert.AreEqual(choice2.Item2, comboBox.Items[1].Content); - Assert.AreEqual(choice3.Item2, comboBox.Items[2].Content); - } + // Act + ToastContentBuilder anotherReference = builder.AddComboBox(testComboBoxId, choice1, choice2, choice3); - [TestMethod] - public void AddComboBoxTest_WithMultipleChoicesAndDefaultSelected_ReturnSelfWithComboBoxAddedWithAllChoicesAndDefaultSelection() - { - // Arrange - string testComboBoxId = Guid.NewGuid().ToString(); - var choice1 = (Guid.NewGuid().ToString(), "Test Choice 1"); - var choice2 = (Guid.NewGuid().ToString(), "Test Choice 2"); - var choice3 = (Guid.NewGuid().ToString(), "Test Choice 3"); - string defaultChoice = choice2.Item1; + // Assert + Assert.AreSame(builder, anotherReference); + var comboBox = (builder.Content.Actions as ToastActionsCustom).Inputs.First() as ToastSelectionBox; - ToastContentBuilder builder = new ToastContentBuilder(); + Assert.AreEqual(testComboBoxId, comboBox.Id); + Assert.AreEqual(choice1.Item1, comboBox.Items[0].Id); + Assert.AreEqual(choice2.Item1, comboBox.Items[1].Id); + Assert.AreEqual(choice3.Item1, comboBox.Items[2].Id); - // Act - ToastContentBuilder anotherReference = builder.AddComboBox(testComboBoxId, defaultChoice, choice1, choice2, choice3); + Assert.AreEqual(choice1.Item2, comboBox.Items[0].Content); + Assert.AreEqual(choice2.Item2, comboBox.Items[1].Content); + Assert.AreEqual(choice3.Item2, comboBox.Items[2].Content); + } - // Assert - Assert.AreSame(builder, anotherReference); - var comboBox = (builder.Content.Actions as ToastActionsCustom).Inputs.First() as ToastSelectionBox; + [TestMethod] + public void AddComboBoxTest_WithMultipleChoicesAndDefaultSelected_ReturnSelfWithComboBoxAddedWithAllChoicesAndDefaultSelection() + { + // Arrange + string testComboBoxId = Guid.NewGuid().ToString(); + var choice1 = (Guid.NewGuid().ToString(), "Test Choice 1"); + var choice2 = (Guid.NewGuid().ToString(), "Test Choice 2"); + var choice3 = (Guid.NewGuid().ToString(), "Test Choice 3"); + string defaultChoice = choice2.Item1; - Assert.AreEqual(testComboBoxId, comboBox.Id); - Assert.AreEqual(choice1.Item1, comboBox.Items[0].Id); - Assert.AreEqual(choice2.Item1, comboBox.Items[1].Id); - Assert.AreEqual(choice3.Item1, comboBox.Items[2].Id); + ToastContentBuilder builder = new ToastContentBuilder(); - Assert.AreEqual(choice1.Item2, comboBox.Items[0].Content); - Assert.AreEqual(choice2.Item2, comboBox.Items[1].Content); - Assert.AreEqual(choice3.Item2, comboBox.Items[2].Content); + // Act + ToastContentBuilder anotherReference = builder.AddComboBox(testComboBoxId, defaultChoice, choice1, choice2, choice3); - Assert.AreEqual(defaultChoice, comboBox.DefaultSelectionBoxItemId); - } + // Assert + Assert.AreSame(builder, anotherReference); + var comboBox = (builder.Content.Actions as ToastActionsCustom).Inputs.First() as ToastSelectionBox; - [TestMethod] - public void AddComboBoxTest_WithMultipleChoiceAndDefaultSelectedAndTitle_ReturnSelfWithComboBoxAddedWithAllChoicesAndDefaultSelectionAndTitle() - { - // Arrange - string testComboBoxId = Guid.NewGuid().ToString(); - var choice1 = (Guid.NewGuid().ToString(), "Test Choice 1"); - var choice2 = (Guid.NewGuid().ToString(), "Test Choice 2"); - var choice3 = (Guid.NewGuid().ToString(), "Test Choice 3"); - string defaultChoice = choice2.Item1; - string testComboBoxTitle = "Test Title"; - - ToastContentBuilder builder = new ToastContentBuilder(); - - // Act - ToastContentBuilder anotherReference = builder.AddComboBox(testComboBoxId, testComboBoxTitle, defaultChoice, choice1, choice2, choice3); - - // Assert - Assert.AreSame(builder, anotherReference); - var comboBox = (builder.Content.Actions as ToastActionsCustom).Inputs.First() as ToastSelectionBox; - - Assert.AreEqual(testComboBoxId, comboBox.Id); - Assert.AreEqual(choice1.Item1, comboBox.Items[0].Id); - Assert.AreEqual(choice2.Item1, comboBox.Items[1].Id); - Assert.AreEqual(choice3.Item1, comboBox.Items[2].Id); - - Assert.AreEqual(choice1.Item2, comboBox.Items[0].Content); - Assert.AreEqual(choice2.Item2, comboBox.Items[1].Content); - Assert.AreEqual(choice3.Item2, comboBox.Items[2].Content); - - Assert.AreEqual(defaultChoice, comboBox.DefaultSelectionBoxItemId); - Assert.AreEqual(testComboBoxTitle, comboBox.Title); - } + Assert.AreEqual(testComboBoxId, comboBox.Id); + Assert.AreEqual(choice1.Item1, comboBox.Items[0].Id); + Assert.AreEqual(choice2.Item1, comboBox.Items[1].Id); + Assert.AreEqual(choice3.Item1, comboBox.Items[2].Id); + + Assert.AreEqual(choice1.Item2, comboBox.Items[0].Content); + Assert.AreEqual(choice2.Item2, comboBox.Items[1].Content); + Assert.AreEqual(choice3.Item2, comboBox.Items[2].Content); + + Assert.AreEqual(defaultChoice, comboBox.DefaultSelectionBoxItemId); + } + + [TestMethod] + public void AddComboBoxTest_WithMultipleChoiceAndDefaultSelectedAndTitle_ReturnSelfWithComboBoxAddedWithAllChoicesAndDefaultSelectionAndTitle() + { + // Arrange + string testComboBoxId = Guid.NewGuid().ToString(); + var choice1 = (Guid.NewGuid().ToString(), "Test Choice 1"); + var choice2 = (Guid.NewGuid().ToString(), "Test Choice 2"); + var choice3 = (Guid.NewGuid().ToString(), "Test Choice 3"); + string defaultChoice = choice2.Item1; + string testComboBoxTitle = "Test Title"; + + ToastContentBuilder builder = new ToastContentBuilder(); + + // Act + ToastContentBuilder anotherReference = builder.AddComboBox(testComboBoxId, testComboBoxTitle, defaultChoice, choice1, choice2, choice3); + + // Assert + Assert.AreSame(builder, anotherReference); + var comboBox = (builder.Content.Actions as ToastActionsCustom).Inputs.First() as ToastSelectionBox; + + Assert.AreEqual(testComboBoxId, comboBox.Id); + Assert.AreEqual(choice1.Item1, comboBox.Items[0].Id); + Assert.AreEqual(choice2.Item1, comboBox.Items[1].Id); + Assert.AreEqual(choice3.Item1, comboBox.Items[2].Id); + + Assert.AreEqual(choice1.Item2, comboBox.Items[0].Content); + Assert.AreEqual(choice2.Item2, comboBox.Items[1].Content); + Assert.AreEqual(choice3.Item2, comboBox.Items[2].Content); + + Assert.AreEqual(defaultChoice, comboBox.DefaultSelectionBoxItemId); + Assert.AreEqual(testComboBoxTitle, comboBox.Title); } } #endif diff --git a/components/Notifications/tests/TestWeather.cs b/components/Notifications/tests/TestWeather.cs index a171dfabb..f7b1cd0e4 100644 --- a/components/Notifications/tests/TestWeather.cs +++ b/components/Notifications/tests/TestWeather.cs @@ -8,288 +8,287 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; #nullable disable -namespace NotificationsExperiment.Tests +namespace NotificationsExperiment.Tests; + +[TestClass] +public class TestWeather { - [TestClass] - public class TestWeather - { - private const string ImageMostlyCloudy = "Assets\\Tiles\\Mostly Cloudy.png"; - private const string ImageSunny = "Assets\\Tiles\\Sunny.png"; - private const string ImageCloudy = "Assets\\Tiles\\Cloudy.png"; + private const string ImageMostlyCloudy = "Assets\\Tiles\\Mostly Cloudy.png"; + private const string ImageSunny = "Assets\\Tiles\\Sunny.png"; + private const string ImageCloudy = "Assets\\Tiles\\Cloudy.png"; - private const string BackgroundImageMostlyCloudy = "Assets\\Tiles\\Mostly Cloudy-Background.jpg"; + private const string BackgroundImageMostlyCloudy = "Assets\\Tiles\\Mostly Cloudy-Background.jpg"; - [TestMethod] - public void TestWeatherTile() - { - var backgroundImage = BackgroundImageMostlyCloudy; - int overlay = 30; + [TestMethod] + public void TestWeatherTile() + { + var backgroundImage = BackgroundImageMostlyCloudy; + int overlay = 30; - TileBindingContentAdaptive smallContent = new TileBindingContentAdaptive() + TileBindingContentAdaptive smallContent = new TileBindingContentAdaptive() + { + TextStacking = TileTextStacking.Center, + BackgroundImage = new TileBackgroundImage() { Source = backgroundImage, HintOverlay = overlay }, + Children = { - TextStacking = TileTextStacking.Center, - BackgroundImage = new TileBackgroundImage() { Source = backgroundImage, HintOverlay = overlay }, - Children = + new AdaptiveText() { - new AdaptiveText() - { - Text = "Mon", - HintStyle = AdaptiveTextStyle.Body, - HintAlign = AdaptiveTextAlign.Center - }, + Text = "Mon", + HintStyle = AdaptiveTextStyle.Body, + HintAlign = AdaptiveTextAlign.Center + }, - new AdaptiveText() - { - Text = "63°", - HintStyle = AdaptiveTextStyle.Base, - HintAlign = AdaptiveTextAlign.Center - } + new AdaptiveText() + { + Text = "63°", + HintStyle = AdaptiveTextStyle.Base, + HintAlign = AdaptiveTextAlign.Center } - }; + } + }; - TileBindingContentAdaptive mediumContent = new TileBindingContentAdaptive() + TileBindingContentAdaptive mediumContent = new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() { Source = backgroundImage, HintOverlay = overlay }, + Children = { - BackgroundImage = new TileBackgroundImage() { Source = backgroundImage, HintOverlay = overlay }, - Children = + new AdaptiveGroup() { - new AdaptiveGroup() + Children = { - Children = - { - GenerateMediumSubgroup("Mon", ImageMostlyCloudy, 63, 42), - GenerateMediumSubgroup("Tue", ImageCloudy, 57, 38) - } + GenerateMediumSubgroup("Mon", ImageMostlyCloudy, 63, 42), + GenerateMediumSubgroup("Tue", ImageCloudy, 57, 38) } } - }; + } + }; - TileBindingContentAdaptive wideContent = new TileBindingContentAdaptive() + TileBindingContentAdaptive wideContent = new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() { Source = backgroundImage, HintOverlay = overlay }, + Children = { - BackgroundImage = new TileBackgroundImage() { Source = backgroundImage, HintOverlay = overlay }, - Children = + new AdaptiveGroup() { - new AdaptiveGroup() + Children = { - Children = - { - GenerateWideSubgroup("Mon", ImageMostlyCloudy, 63, 42), - GenerateWideSubgroup("Tue", ImageCloudy, 57, 38), - GenerateWideSubgroup("Wed", ImageSunny, 59, 43), - GenerateWideSubgroup("Thu", ImageSunny, 62, 42), - GenerateWideSubgroup("Fri", ImageSunny, 71, 66) - } + GenerateWideSubgroup("Mon", ImageMostlyCloudy, 63, 42), + GenerateWideSubgroup("Tue", ImageCloudy, 57, 38), + GenerateWideSubgroup("Wed", ImageSunny, 59, 43), + GenerateWideSubgroup("Thu", ImageSunny, 62, 42), + GenerateWideSubgroup("Fri", ImageSunny, 71, 66) } } - }; + } + }; - TileBindingContentAdaptive largeContent = new TileBindingContentAdaptive() + TileBindingContentAdaptive largeContent = new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() { Source = backgroundImage, HintOverlay = overlay }, + Children = { - BackgroundImage = new TileBackgroundImage() { Source = backgroundImage, HintOverlay = overlay }, - Children = + new AdaptiveGroup() { - new AdaptiveGroup() + Children = { - Children = + new AdaptiveSubgroup() { - new AdaptiveSubgroup() + HintWeight = 30, + Children = { - HintWeight = 30, - Children = - { - new AdaptiveImage() { Source = ImageMostlyCloudy } - } - }, + new AdaptiveImage() { Source = ImageMostlyCloudy } + } + }, - new AdaptiveSubgroup() + new AdaptiveSubgroup() + { + Children = { - Children = + new AdaptiveText() { - new AdaptiveText() - { - Text = "Monday", - HintStyle = AdaptiveTextStyle.Base - }, - - new AdaptiveText() - { - Text = "63° / 42°" - }, - - new AdaptiveText() - { - Text = "20% chance of rain", - HintStyle = AdaptiveTextStyle.CaptionSubtle - }, - - new AdaptiveText() - { - Text = "Winds 5 mph NE", - HintStyle = AdaptiveTextStyle.CaptionSubtle - } + Text = "Monday", + HintStyle = AdaptiveTextStyle.Base + }, + + new AdaptiveText() + { + Text = "63° / 42°" + }, + + new AdaptiveText() + { + Text = "20% chance of rain", + HintStyle = AdaptiveTextStyle.CaptionSubtle + }, + + new AdaptiveText() + { + Text = "Winds 5 mph NE", + HintStyle = AdaptiveTextStyle.CaptionSubtle } } } - }, + } + }, - // For spacing - new AdaptiveText(), + // For spacing + new AdaptiveText(), - new AdaptiveGroup() + new AdaptiveGroup() + { + Children = { - Children = - { - GenerateLargeSubgroup("Tue", ImageCloudy, 57, 38), - GenerateLargeSubgroup("Wed", ImageSunny, 59, 43), - GenerateLargeSubgroup("Thu", ImageSunny, 62, 42), - GenerateLargeSubgroup("Fri", ImageSunny, 71, 66) - } + GenerateLargeSubgroup("Tue", ImageCloudy, 57, 38), + GenerateLargeSubgroup("Wed", ImageSunny, 59, 43), + GenerateLargeSubgroup("Thu", ImageSunny, 62, 42), + GenerateLargeSubgroup("Fri", ImageSunny, 71, 66) } } - }; + } + }; - TileContent content = new TileContent() + TileContent content = new TileContent() + { + Visual = new TileVisual() { - Visual = new TileVisual() - { - DisplayName = "Seattle", + DisplayName = "Seattle", - TileSmall = new TileBinding() - { - Content = smallContent - }, + TileSmall = new TileBinding() + { + Content = smallContent + }, - TileMedium = new TileBinding() - { - Content = mediumContent, - Branding = TileBranding.Name - }, + TileMedium = new TileBinding() + { + Content = mediumContent, + Branding = TileBranding.Name + }, - TileWide = new TileBinding() - { - Content = wideContent, - Branding = TileBranding.NameAndLogo - }, + TileWide = new TileBinding() + { + Content = wideContent, + Branding = TileBranding.NameAndLogo + }, - TileLarge = new TileBinding() - { - Content = largeContent, - Branding = TileBranding.NameAndLogo - } + TileLarge = new TileBinding() + { + Content = largeContent, + Branding = TileBranding.NameAndLogo } - }; + } + }; - string expectedPayload = $@"{GenerateStringBackgroundImage()}Mon63°{GenerateStringBackgroundImage()}"; + string expectedPayload = $@"{GenerateStringBackgroundImage()}Mon63°{GenerateStringBackgroundImage()}"; - // Medium tile subgroups - expectedPayload += GenerateStringMediumSubgroup("Mon", ImageMostlyCloudy, 63, 42); - expectedPayload += GenerateStringMediumSubgroup("Tue", ImageCloudy, 57, 38); + // Medium tile subgroups + expectedPayload += GenerateStringMediumSubgroup("Mon", ImageMostlyCloudy, 63, 42); + expectedPayload += GenerateStringMediumSubgroup("Tue", ImageCloudy, 57, 38); - expectedPayload += ""; + expectedPayload += ""; - // Wide tile - expectedPayload += @""; - expectedPayload += GenerateStringBackgroundImage(); - expectedPayload += ""; + // Wide tile + expectedPayload += @""; + expectedPayload += GenerateStringBackgroundImage(); + expectedPayload += ""; - // Wide tile subgroups - expectedPayload += GenerateStringWideSubgroup("Mon", ImageMostlyCloudy, 63, 42); - expectedPayload += GenerateStringWideSubgroup("Tue", ImageCloudy, 57, 38); - expectedPayload += GenerateStringWideSubgroup("Wed", ImageSunny, 59, 43); - expectedPayload += GenerateStringWideSubgroup("Thu", ImageSunny, 62, 42); - expectedPayload += GenerateStringWideSubgroup("Fri", ImageSunny, 71, 66); + // Wide tile subgroups + expectedPayload += GenerateStringWideSubgroup("Mon", ImageMostlyCloudy, 63, 42); + expectedPayload += GenerateStringWideSubgroup("Tue", ImageCloudy, 57, 38); + expectedPayload += GenerateStringWideSubgroup("Wed", ImageSunny, 59, 43); + expectedPayload += GenerateStringWideSubgroup("Thu", ImageSunny, 62, 42); + expectedPayload += GenerateStringWideSubgroup("Fri", ImageSunny, 71, 66); - expectedPayload += ""; + expectedPayload += ""; - // Large tile - expectedPayload += @""; - expectedPayload += GenerateStringBackgroundImage(); - expectedPayload += $@"Monday63° / 42°20% chance of rainWinds 5 mph NE"; + // Large tile + expectedPayload += @""; + expectedPayload += GenerateStringBackgroundImage(); + expectedPayload += $@"Monday63° / 42°20% chance of rainWinds 5 mph NE"; - expectedPayload += ""; - expectedPayload += ""; + expectedPayload += ""; + expectedPayload += ""; - // Large tile subgroups - expectedPayload += GenerateStringLargeSubgroup("Tue", ImageCloudy, 57, 38); - expectedPayload += GenerateStringLargeSubgroup("Wed", ImageSunny, 59, 43); - expectedPayload += GenerateStringLargeSubgroup("Thu", ImageSunny, 62, 42); - expectedPayload += GenerateStringLargeSubgroup("Fri", ImageSunny, 71, 66); + // Large tile subgroups + expectedPayload += GenerateStringLargeSubgroup("Tue", ImageCloudy, 57, 38); + expectedPayload += GenerateStringLargeSubgroup("Wed", ImageSunny, 59, 43); + expectedPayload += GenerateStringLargeSubgroup("Thu", ImageSunny, 62, 42); + expectedPayload += GenerateStringLargeSubgroup("Fri", ImageSunny, 71, 66); - expectedPayload += ""; + expectedPayload += ""; - AssertHelper.AssertTile(expectedPayload, content); - } + AssertHelper.AssertTile(expectedPayload, content); + } - private static string GenerateStringBackgroundImage() - { - return $@""; - } + private static string GenerateStringBackgroundImage() + { + return $@""; + } - private static string GenerateStringMediumSubgroup(string day, string image, int high, int low) - { - return $@"{day}{high}°{low}°"; - } + private static string GenerateStringMediumSubgroup(string day, string image, int high, int low) + { + return $@"{day}{high}°{low}°"; + } - private static string GenerateStringWideSubgroup(string day, string image, int high, int low) - { - return $@"{day}{high}°{low}°"; - } + private static string GenerateStringWideSubgroup(string day, string image, int high, int low) + { + return $@"{day}{high}°{low}°"; + } - private static string GenerateStringLargeSubgroup(string day, string image, int high, int low) - { - return $@"{day}{high}°{low}°"; - } + private static string GenerateStringLargeSubgroup(string day, string image, int high, int low) + { + return $@"{day}{high}°{low}°"; + } - private static AdaptiveSubgroup GenerateMediumSubgroup(string day, string image, int high, int low) + private static AdaptiveSubgroup GenerateMediumSubgroup(string day, string image, int high, int low) + { + return new AdaptiveSubgroup() { - return new AdaptiveSubgroup() + Children = { - Children = + new AdaptiveText() { - new AdaptiveText() - { - Text = day, - HintAlign = AdaptiveTextAlign.Center - }, + Text = day, + HintAlign = AdaptiveTextAlign.Center + }, - new AdaptiveImage() - { - Source = image, - HintRemoveMargin = true - }, + new AdaptiveImage() + { + Source = image, + HintRemoveMargin = true + }, - new AdaptiveText() - { - Text = high + "°", - HintAlign = AdaptiveTextAlign.Center - }, + new AdaptiveText() + { + Text = high + "°", + HintAlign = AdaptiveTextAlign.Center + }, - new AdaptiveText() - { - Text = low + "°", - HintAlign = AdaptiveTextAlign.Center, - HintStyle = AdaptiveTextStyle.CaptionSubtle - } + new AdaptiveText() + { + Text = low + "°", + HintAlign = AdaptiveTextAlign.Center, + HintStyle = AdaptiveTextStyle.CaptionSubtle } - }; - } + } + }; + } - private static AdaptiveSubgroup GenerateWideSubgroup(string day, string image, int high, int low) - { - var subgroup = GenerateMediumSubgroup(day, image, high, low); + private static AdaptiveSubgroup GenerateWideSubgroup(string day, string image, int high, int low) + { + var subgroup = GenerateMediumSubgroup(day, image, high, low); - subgroup.HintWeight = 1; + subgroup.HintWeight = 1; - return subgroup; - } + return subgroup; + } - private static AdaptiveSubgroup GenerateLargeSubgroup(string day, string image, int high, int low) - { - var subgroup = GenerateWideSubgroup(day, image, high, low); + private static AdaptiveSubgroup GenerateLargeSubgroup(string day, string image, int high, int low) + { + var subgroup = GenerateWideSubgroup(day, image, high, low); - (subgroup.Children[1] as AdaptiveImage).HintRemoveMargin = null; + (subgroup.Children[1] as AdaptiveImage).HintRemoveMargin = null; - return subgroup; - } + return subgroup; } } #endif diff --git a/components/Notifications/tests/Test_Adaptive_Xml.cs b/components/Notifications/tests/Test_Adaptive_Xml.cs index bbf50d7cf..e347ef82d 100644 --- a/components/Notifications/tests/Test_Adaptive_Xml.cs +++ b/components/Notifications/tests/Test_Adaptive_Xml.cs @@ -9,592 +9,591 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; #nullable disable -namespace NotificationsExperiment.Tests +namespace NotificationsExperiment.Tests; + +[TestClass] +public class Test_Adaptive_Xml { - [TestClass] - public class Test_Adaptive_Xml + [TestMethod] + public void Test_Adaptive_Text_Defaults() { - [TestMethod] - public void Test_Adaptive_Text_Defaults() - { - AssertAdaptiveChild("", new AdaptiveText()); - } + AssertAdaptiveChild("", new AdaptiveText()); + } - [TestMethod] - public void Test_Adaptive_Text_Text() + [TestMethod] + public void Test_Adaptive_Text_Text() + { + AssertAdaptiveChild("Hello & Goodbye", new AdaptiveText() { - AssertAdaptiveChild("Hello & Goodbye", new AdaptiveText() - { - Text = "Hello & Goodbye" - }); + Text = "Hello & Goodbye" + }); - // Data binding should work - AssertAdaptiveChild("{title}", new AdaptiveText() - { - Text = new BindableString("title") - }); - } + // Data binding should work + AssertAdaptiveChild("{title}", new AdaptiveText() + { + Text = new BindableString("title") + }); + } - [TestMethod] - public void Test_Adaptive_Text_HintStyle_Values() - { - AssertAdaptiveTextStyle("caption", AdaptiveTextStyle.Caption); - AssertAdaptiveTextStyle("captionSubtle", AdaptiveTextStyle.CaptionSubtle); - AssertAdaptiveTextStyle("base", AdaptiveTextStyle.Base); - AssertAdaptiveTextStyle("baseSubtle", AdaptiveTextStyle.BaseSubtle); - AssertAdaptiveTextStyle("body", AdaptiveTextStyle.Body); - AssertAdaptiveTextStyle("bodySubtle", AdaptiveTextStyle.BodySubtle); - AssertAdaptiveTextStyle("subtitle", AdaptiveTextStyle.Subtitle); - AssertAdaptiveTextStyle("subtitleSubtle", AdaptiveTextStyle.SubtitleSubtle); - AssertAdaptiveTextStyle("title", AdaptiveTextStyle.Title); - AssertAdaptiveTextStyle("titleSubtle", AdaptiveTextStyle.TitleSubtle); - AssertAdaptiveTextStyle("titleNumeral", AdaptiveTextStyle.TitleNumeral); - AssertAdaptiveTextStyle("subheader", AdaptiveTextStyle.Subheader); - AssertAdaptiveTextStyle("subheaderSubtle", AdaptiveTextStyle.SubheaderSubtle); - AssertAdaptiveTextStyle("subheaderNumeral", AdaptiveTextStyle.SubheaderNumeral); - AssertAdaptiveTextStyle("header", AdaptiveTextStyle.Header); - AssertAdaptiveTextStyle("headerSubtle", AdaptiveTextStyle.HeaderSubtle); - AssertAdaptiveTextStyle("headerNumeral", AdaptiveTextStyle.HeaderNumeral); - } + [TestMethod] + public void Test_Adaptive_Text_HintStyle_Values() + { + AssertAdaptiveTextStyle("caption", AdaptiveTextStyle.Caption); + AssertAdaptiveTextStyle("captionSubtle", AdaptiveTextStyle.CaptionSubtle); + AssertAdaptiveTextStyle("base", AdaptiveTextStyle.Base); + AssertAdaptiveTextStyle("baseSubtle", AdaptiveTextStyle.BaseSubtle); + AssertAdaptiveTextStyle("body", AdaptiveTextStyle.Body); + AssertAdaptiveTextStyle("bodySubtle", AdaptiveTextStyle.BodySubtle); + AssertAdaptiveTextStyle("subtitle", AdaptiveTextStyle.Subtitle); + AssertAdaptiveTextStyle("subtitleSubtle", AdaptiveTextStyle.SubtitleSubtle); + AssertAdaptiveTextStyle("title", AdaptiveTextStyle.Title); + AssertAdaptiveTextStyle("titleSubtle", AdaptiveTextStyle.TitleSubtle); + AssertAdaptiveTextStyle("titleNumeral", AdaptiveTextStyle.TitleNumeral); + AssertAdaptiveTextStyle("subheader", AdaptiveTextStyle.Subheader); + AssertAdaptiveTextStyle("subheaderSubtle", AdaptiveTextStyle.SubheaderSubtle); + AssertAdaptiveTextStyle("subheaderNumeral", AdaptiveTextStyle.SubheaderNumeral); + AssertAdaptiveTextStyle("header", AdaptiveTextStyle.Header); + AssertAdaptiveTextStyle("headerSubtle", AdaptiveTextStyle.HeaderSubtle); + AssertAdaptiveTextStyle("headerNumeral", AdaptiveTextStyle.HeaderNumeral); + } - private static void AssertAdaptiveTextStyle(string expectedPropertyValue, AdaptiveTextStyle style) + private static void AssertAdaptiveTextStyle(string expectedPropertyValue, AdaptiveTextStyle style) + { + AssertAdaptiveTextPropertyValue("hint-style", expectedPropertyValue, new AdaptiveText() { - AssertAdaptiveTextPropertyValue("hint-style", expectedPropertyValue, new AdaptiveText() - { - HintStyle = style - }); - } + HintStyle = style + }); + } + + [TestMethod] + public void Test_Adaptive_Text_HintAlign_Values() + { + AssertAdaptiveTextAlign("auto", AdaptiveTextAlign.Auto); + AssertAdaptiveTextAlign("left", AdaptiveTextAlign.Left); + AssertAdaptiveTextAlign("center", AdaptiveTextAlign.Center); + AssertAdaptiveTextAlign("right", AdaptiveTextAlign.Right); + } - [TestMethod] - public void Test_Adaptive_Text_HintAlign_Values() + private static void AssertAdaptiveTextAlign(string expectedPropertyValue, AdaptiveTextAlign align) + { + AssertAdaptiveTextPropertyValue("hint-align", expectedPropertyValue, new AdaptiveText() { - AssertAdaptiveTextAlign("auto", AdaptiveTextAlign.Auto); - AssertAdaptiveTextAlign("left", AdaptiveTextAlign.Left); - AssertAdaptiveTextAlign("center", AdaptiveTextAlign.Center); - AssertAdaptiveTextAlign("right", AdaptiveTextAlign.Right); - } + HintAlign = align + }); + } - private static void AssertAdaptiveTextAlign(string expectedPropertyValue, AdaptiveTextAlign align) + [TestMethod] + public void Test_Adaptive_Text_HintMaxLines_MinValue() + { + AssertAdaptiveTextPropertyValue("hint-maxLines", "1", new AdaptiveText() { - AssertAdaptiveTextPropertyValue("hint-align", expectedPropertyValue, new AdaptiveText() - { - HintAlign = align - }); - } + HintMaxLines = 1 + }); + } - [TestMethod] - public void Test_Adaptive_Text_HintMaxLines_MinValue() + [TestMethod] + public void Test_Adaptive_Text_HintMaxLines_NormalValue() + { + AssertAdaptiveTextPropertyValue("hint-maxLines", "3", new AdaptiveText() { - AssertAdaptiveTextPropertyValue("hint-maxLines", "1", new AdaptiveText() - { - HintMaxLines = 1 - }); - } + HintMaxLines = 3 + }); + } - [TestMethod] - public void Test_Adaptive_Text_HintMaxLines_NormalValue() + [TestMethod] + public void Test_Adaptive_Text_HintMaxLines_MaxValue() + { + AssertAdaptiveTextPropertyValue("hint-maxLines", int.MaxValue.ToString(), new AdaptiveText() { - AssertAdaptiveTextPropertyValue("hint-maxLines", "3", new AdaptiveText() + HintMaxLines = int.MaxValue + }); + } + + [TestMethod] + public void Test_Adaptive_Text_HintMaxLines_BelowMin() + { + Assert.ThrowsException( + () => { - HintMaxLines = 3 - }); - } + new AdaptiveText() { HintMaxLines = 0 }; + }, "ArgumentOutOfRangeExceptions should have been thrown."); + } - [TestMethod] - public void Test_Adaptive_Text_HintMaxLines_MaxValue() - { - AssertAdaptiveTextPropertyValue("hint-maxLines", int.MaxValue.ToString(), new AdaptiveText() + [TestMethod] + public void Test_Adaptive_Text_HintMaxLines_AboveMax() + { + Assert.ThrowsException( + () => { - HintMaxLines = int.MaxValue - }); - } + new AdaptiveText() { HintMaxLines = -54 }; + }, "ArgumentOutOfRangeExceptions should have been thrown."); + } - [TestMethod] - public void Test_Adaptive_Text_HintMaxLines_BelowMin() + [TestMethod] + public void Test_Adaptive_Text_HintMinLines_MinValue() + { + AssertAdaptiveTextPropertyValue("hint-minLines", "1", new AdaptiveText() { - Assert.ThrowsException( - () => - { - new AdaptiveText() { HintMaxLines = 0 }; - }, "ArgumentOutOfRangeExceptions should have been thrown."); - } + HintMinLines = 1 + }); + } - [TestMethod] - public void Test_Adaptive_Text_HintMaxLines_AboveMax() + [TestMethod] + public void Test_Adaptive_Text_HintMinLines_NormalValue() + { + AssertAdaptiveTextPropertyValue("hint-minLines", "3", new AdaptiveText() { - Assert.ThrowsException( - () => - { - new AdaptiveText() { HintMaxLines = -54 }; - }, "ArgumentOutOfRangeExceptions should have been thrown."); - } + HintMinLines = 3 + }); + } - [TestMethod] - public void Test_Adaptive_Text_HintMinLines_MinValue() + [TestMethod] + public void Test_Adaptive_Text_HintMinLines_MaxValue() + { + AssertAdaptiveTextPropertyValue("hint-minLines", int.MaxValue.ToString(), new AdaptiveText() { - AssertAdaptiveTextPropertyValue("hint-minLines", "1", new AdaptiveText() - { - HintMinLines = 1 - }); - } + HintMinLines = int.MaxValue + }); + } - [TestMethod] - public void Test_Adaptive_Text_HintMinLines_NormalValue() - { - AssertAdaptiveTextPropertyValue("hint-minLines", "3", new AdaptiveText() + [TestMethod] + public void Test_Adaptive_Text_HintMinLines_BelowMin() + { + Assert.ThrowsException( + () => { - HintMinLines = 3 - }); - } + new AdaptiveText() { HintMinLines = 0 }; + }, "ArgumentOutOfRangeExceptions should have been thrown."); + } - [TestMethod] - public void Test_Adaptive_Text_HintMinLines_MaxValue() - { - AssertAdaptiveTextPropertyValue("hint-minLines", int.MaxValue.ToString(), new AdaptiveText() + [TestMethod] + public void Test_Adaptive_Text_HintMinLines_AboveMax() + { + Assert.ThrowsException( + () => { - HintMinLines = int.MaxValue - }); - } + new AdaptiveText() { HintMinLines = -54 }; + }, "ArgumentOutOfRangeExceptions should have been thrown."); + } - [TestMethod] - public void Test_Adaptive_Text_HintMinLines_BelowMin() + [TestMethod] + public void Test_Adaptive_Text_HintWrap_Values() + { + AssertAdaptiveTextPropertyValue("hint-wrap", "false", new AdaptiveText() { - Assert.ThrowsException( - () => - { - new AdaptiveText() { HintMinLines = 0 }; - }, "ArgumentOutOfRangeExceptions should have been thrown."); - } + HintWrap = false + }); - [TestMethod] - public void Test_Adaptive_Text_HintMinLines_AboveMax() + AssertAdaptiveTextPropertyValue("hint-wrap", "true", new AdaptiveText() { - Assert.ThrowsException( - () => - { - new AdaptiveText() { HintMinLines = -54 }; - }, "ArgumentOutOfRangeExceptions should have been thrown."); - } + HintWrap = true + }); + } - [TestMethod] - public void Test_Adaptive_Text_HintWrap_Values() - { - AssertAdaptiveTextPropertyValue("hint-wrap", "false", new AdaptiveText() - { - HintWrap = false - }); + [TestMethod] + public void Test_Adaptive_Text_DefaultNullValues() + { + AssertAdaptiveChild("", new AdaptiveText() + { + HintAlign = AdaptiveTextAlign.Default, + HintStyle = AdaptiveTextStyle.Default, + HintMaxLines = null, + HintMinLines = null, + HintWrap = null, + Language = null, + Text = null + }); + } + + private static void AssertAdaptiveTextPropertyValue(string expectedPropertyName, string expectedPropertyValue, AdaptiveText text) + { + AssertAdaptiveChild($"", text); + } - AssertAdaptiveTextPropertyValue("hint-wrap", "true", new AdaptiveText() + [TestMethod] + public void Test_Adaptive_Image_Defaults() + { + Assert.ThrowsException( + () => { - HintWrap = true - }); - } + AssertAdaptiveChild("exception should be thrown", new AdaptiveImage()); + }, "NullReferenceException should have been thrown."); + } - [TestMethod] - public void Test_Adaptive_Text_DefaultNullValues() + [TestMethod] + public void Test_Adaptive_Image_Source() + { + AssertAdaptiveImagePropertyValue("src", "ms-appdata:///local/MyImage.png", new AdaptiveImage() { - AssertAdaptiveChild("", new AdaptiveText() - { - HintAlign = AdaptiveTextAlign.Default, - HintStyle = AdaptiveTextStyle.Default, - HintMaxLines = null, - HintMinLines = null, - HintWrap = null, - Language = null, - Text = null - }); - } + Source = "ms-appdata:///local/MyImage.png" + }); - private static void AssertAdaptiveTextPropertyValue(string expectedPropertyName, string expectedPropertyValue, AdaptiveText text) + AssertAdaptiveImagePropertyValue("src", "ms-appx:///Assets/MyImage.png", new AdaptiveImage() { - AssertAdaptiveChild($"", text); - } + Source = "ms-appx:///Assets/MyImage.png" + }); - [TestMethod] - public void Test_Adaptive_Image_Defaults() + AssertAdaptiveImagePropertyValue("src", "http://msn.com/img.png", new AdaptiveImage() { - Assert.ThrowsException( - () => - { - AssertAdaptiveChild("exception should be thrown", new AdaptiveImage()); - }, "NullReferenceException should have been thrown."); - } + Source = "http://msn.com/img.png" + }); - [TestMethod] - public void Test_Adaptive_Image_Source() + AssertAdaptiveImagePropertyValue("src", "Assets/MyImage.png", new AdaptiveImage() { - AssertAdaptiveImagePropertyValue("src", "ms-appdata:///local/MyImage.png", new AdaptiveImage() - { - Source = "ms-appdata:///local/MyImage.png" - }); + Source = "Assets/MyImage.png" + }); + } - AssertAdaptiveImagePropertyValue("src", "ms-appx:///Assets/MyImage.png", new AdaptiveImage() + [TestMethod] + public void Test_Adaptive_Image_Source_Null() + { + Assert.ThrowsException( + () => { - Source = "ms-appx:///Assets/MyImage.png" - }); + new AdaptiveImage() + { + Source = null + }; + }, "ArgumentNullException should have been thrown."); + } - AssertAdaptiveImagePropertyValue("src", "http://msn.com/img.png", new AdaptiveImage() - { - Source = "http://msn.com/img.png" - }); + [TestMethod] + public void Test_Adaptive_Image_AddImageQuery() + { + AssertAdaptiveImagePropertyValue("addImageQuery", "false", new AdaptiveImage() + { + AddImageQuery = false + }); - AssertAdaptiveImagePropertyValue("src", "Assets/MyImage.png", new AdaptiveImage() - { - Source = "Assets/MyImage.png" - }); - } + AssertAdaptiveImagePropertyValue("addImageQuery", "true", new AdaptiveImage() + { + AddImageQuery = true + }); + } - [TestMethod] - public void Test_Adaptive_Image_Source_Null() + [TestMethod] + public void Test_Adaptive_Image_AlternateText() + { + AssertAdaptiveImagePropertyValue("alt", "image of puppies", new AdaptiveImage() { - Assert.ThrowsException( - () => - { - new AdaptiveImage() - { - Source = null - }; - }, "ArgumentNullException should have been thrown."); - } + AlternateText = "image of puppies" + }); + } + + [TestMethod] + public void Test_Adaptive_Image_HintAlign() + { + AssertAdaptiveImageAlign("stretch", AdaptiveImageAlign.Stretch); + AssertAdaptiveImageAlign("left", AdaptiveImageAlign.Left); + AssertAdaptiveImageAlign("center", AdaptiveImageAlign.Center); + AssertAdaptiveImageAlign("right", AdaptiveImageAlign.Right); + } - [TestMethod] - public void Test_Adaptive_Image_AddImageQuery() + private static void AssertAdaptiveImageAlign(string expectedValue, AdaptiveImageAlign align) + { + AssertAdaptiveImagePropertyValue("hint-align", expectedValue, new AdaptiveImage() { - AssertAdaptiveImagePropertyValue("addImageQuery", "false", new AdaptiveImage() - { - AddImageQuery = false - }); + HintAlign = align + }); + } - AssertAdaptiveImagePropertyValue("addImageQuery", "true", new AdaptiveImage() - { - AddImageQuery = true - }); - } + [TestMethod] + public void Test_Adaptive_Image_HintCrop() + { + AssertAdaptiveImageCrop("none", AdaptiveImageCrop.None); + AssertAdaptiveImageCrop("circle", AdaptiveImageCrop.Circle); + } - [TestMethod] - public void Test_Adaptive_Image_AlternateText() + private static void AssertAdaptiveImageCrop(string expectedValue, AdaptiveImageCrop crop) + { + AssertAdaptiveImagePropertyValue("hint-crop", expectedValue, new AdaptiveImage() { - AssertAdaptiveImagePropertyValue("alt", "image of puppies", new AdaptiveImage() - { - AlternateText = "image of puppies" - }); - } + HintCrop = crop + }); + } - [TestMethod] - public void Test_Adaptive_Image_HintAlign() + [TestMethod] + public void Test_Adaptive_Image_HintRemoveMargin() + { + AssertAdaptiveImagePropertyValue("hint-removeMargin", "false", new AdaptiveImage() { - AssertAdaptiveImageAlign("stretch", AdaptiveImageAlign.Stretch); - AssertAdaptiveImageAlign("left", AdaptiveImageAlign.Left); - AssertAdaptiveImageAlign("center", AdaptiveImageAlign.Center); - AssertAdaptiveImageAlign("right", AdaptiveImageAlign.Right); - } + HintRemoveMargin = false + }); - private static void AssertAdaptiveImageAlign(string expectedValue, AdaptiveImageAlign align) + AssertAdaptiveImagePropertyValue("hint-removeMargin", "true", new AdaptiveImage() { - AssertAdaptiveImagePropertyValue("hint-align", expectedValue, new AdaptiveImage() - { - HintAlign = align - }); - } + HintRemoveMargin = true + }); + } + + [TestMethod] + public void Test_Adaptive_Image_DefaultNullValues() + { + AssertAdaptiveChild("", new AdaptiveImage() + { + Source = "img.png", + AddImageQuery = null, + AlternateText = null, + HintAlign = AdaptiveImageAlign.Default, + HintCrop = AdaptiveImageCrop.Default, + HintRemoveMargin = null + }); + } - [TestMethod] - public void Test_Adaptive_Image_HintCrop() + private static void AssertAdaptiveImagePropertyValue(string expectedPropertyName, string expectedPropertyValue, AdaptiveImage image) + { + bool addedSource = false; + if (image.Source == null) { - AssertAdaptiveImageCrop("none", AdaptiveImageCrop.None); - AssertAdaptiveImageCrop("circle", AdaptiveImageCrop.Circle); + image.Source = "img.png"; + addedSource = true; } - private static void AssertAdaptiveImageCrop(string expectedValue, AdaptiveImageCrop crop) + string xml = $"( + () => { - HintRemoveMargin = true - }); - } + AssertAdaptiveChild("exception should be thrown since groups need at least one subgroup child", new AdaptiveGroup()); + }, "InvalidOperationException should have been thrown."); + } - [TestMethod] - public void Test_Adaptive_Image_DefaultNullValues() + [TestMethod] + public void Test_Adaptive_Group_OneChild() + { + AssertAdaptiveChild("", new AdaptiveGroup() { - AssertAdaptiveChild("", new AdaptiveImage() + Children = { - Source = "img.png", - AddImageQuery = null, - AlternateText = null, - HintAlign = AdaptiveImageAlign.Default, - HintCrop = AdaptiveImageCrop.Default, - HintRemoveMargin = null - }); - } + new AdaptiveSubgroup() + } + }); + } - private static void AssertAdaptiveImagePropertyValue(string expectedPropertyName, string expectedPropertyValue, AdaptiveImage image) + [TestMethod] + public void Test_Adaptive_Group_TwoChildren() + { + AssertAdaptiveChild("", new AdaptiveGroup() { - bool addedSource = false; - if (image.Source == null) + Children = { - image.Source = "img.png"; - addedSource = true; + new AdaptiveSubgroup(), + new AdaptiveSubgroup() } + }); + } - string xml = $"", new AdaptiveGroup() + { + Children = { - xml += " src='img.png'"; + new AdaptiveSubgroup(), + new AdaptiveSubgroup(), + new AdaptiveSubgroup() } + }); + } - xml += "/>"; - - AssertAdaptiveChild(xml, image); - } + [TestMethod] + public void Test_Adaptive_Subgroup_Defaults() + { + AssertAdaptiveSubgroup("", new AdaptiveSubgroup()); + } - [TestMethod] - public void Test_Adaptive_Group_Defaults() + [TestMethod] + public void Test_Adaptive_Subgroup_HintWeight_MinValue() + { + AssertAdaptiveSubgroupProperty("hint-weight", "1", new AdaptiveSubgroup() { - Assert.ThrowsException( - () => - { - AssertAdaptiveChild("exception should be thrown since groups need at least one subgroup child", new AdaptiveGroup()); - }, "InvalidOperationException should have been thrown."); - } + HintWeight = 1 + }); + } - [TestMethod] - public void Test_Adaptive_Group_OneChild() + [TestMethod] + public void Test_Adaptive_Subgroup_HintWeight_NormalValue() + { + AssertAdaptiveSubgroupProperty("hint-weight", "20", new AdaptiveSubgroup() { - AssertAdaptiveChild("", new AdaptiveGroup() - { - Children = - { - new AdaptiveSubgroup() - } - }); - } + HintWeight = 20 + }); + } - [TestMethod] - public void Test_Adaptive_Group_TwoChildren() + [TestMethod] + public void Test_Adaptive_Subgroup_HintWeight_MaxValue() + { + AssertAdaptiveSubgroupProperty("hint-weight", int.MaxValue.ToString(), new AdaptiveSubgroup() { - AssertAdaptiveChild("", new AdaptiveGroup() - { - Children = - { - new AdaptiveSubgroup(), - new AdaptiveSubgroup() - } - }); - } + HintWeight = int.MaxValue + }); + } - [TestMethod] - public void Test_Adaptive_Group_ThreeChildren() - { - AssertAdaptiveChild("", new AdaptiveGroup() + [TestMethod] + public void Test_Adaptive_Subgroup_HintWeight_JustBelowMin() + { + Assert.ThrowsException( + () => { - Children = + AssertAdaptiveSubgroup("exception should be thrown", new AdaptiveSubgroup() { - new AdaptiveSubgroup(), - new AdaptiveSubgroup(), - new AdaptiveSubgroup() - } - }); - } - - [TestMethod] - public void Test_Adaptive_Subgroup_Defaults() - { - AssertAdaptiveSubgroup("", new AdaptiveSubgroup()); - } - - [TestMethod] - public void Test_Adaptive_Subgroup_HintWeight_MinValue() - { - AssertAdaptiveSubgroupProperty("hint-weight", "1", new AdaptiveSubgroup() - { - HintWeight = 1 - }); - } + HintWeight = 0 + }); + }, "ArgumentOutOfRangeException should have been thrown."); + } - [TestMethod] - public void Test_Adaptive_Subgroup_HintWeight_NormalValue() - { - AssertAdaptiveSubgroupProperty("hint-weight", "20", new AdaptiveSubgroup() + [TestMethod] + public void Test_Adaptive_Subgroup_HintWeight_BelowMin() + { + Assert.ThrowsException( + () => { - HintWeight = 20 - }); - } + AssertAdaptiveSubgroup("exception should be thrown", new AdaptiveSubgroup() + { + HintWeight = -53 + }); + }, "ArgumentOutOfRangeException should have been thrown."); + } - [TestMethod] - public void Test_Adaptive_Subgroup_HintWeight_MaxValue() - { - AssertAdaptiveSubgroupProperty("hint-weight", int.MaxValue.ToString(), new AdaptiveSubgroup() - { - HintWeight = int.MaxValue - }); - } + [TestMethod] + public void Test_Adaptive_Subgroup_HintTextStacking() + { + AssertAdaptiveSubgroupTextStacking("top", AdaptiveSubgroupTextStacking.Top); + AssertAdaptiveSubgroupTextStacking("center", AdaptiveSubgroupTextStacking.Center); + AssertAdaptiveSubgroupTextStacking("bottom", AdaptiveSubgroupTextStacking.Bottom); + } - [TestMethod] - public void Test_Adaptive_Subgroup_HintWeight_JustBelowMin() + private static void AssertAdaptiveSubgroupTextStacking(string expectedValue, AdaptiveSubgroupTextStacking textStacking) + { + AssertAdaptiveSubgroupProperty("hint-textStacking", expectedValue, new AdaptiveSubgroup() { - Assert.ThrowsException( - () => - { - AssertAdaptiveSubgroup("exception should be thrown", new AdaptiveSubgroup() - { - HintWeight = 0 - }); - }, "ArgumentOutOfRangeException should have been thrown."); - } + HintTextStacking = textStacking + }); + } - [TestMethod] - public void Test_Adaptive_Subgroup_HintWeight_BelowMin() + [TestMethod] + public void Test_Adaptive_Subgroup_DefaultNullValues() + { + AssertAdaptiveSubgroup("", new AdaptiveSubgroup() { - Assert.ThrowsException( - () => - { - AssertAdaptiveSubgroup("exception should be thrown", new AdaptiveSubgroup() - { - HintWeight = -53 - }); - }, "ArgumentOutOfRangeException should have been thrown."); - } + HintTextStacking = AdaptiveSubgroupTextStacking.Default, + HintWeight = null + }); + } - [TestMethod] - public void Test_Adaptive_Subgroup_HintTextStacking() - { - AssertAdaptiveSubgroupTextStacking("top", AdaptiveSubgroupTextStacking.Top); - AssertAdaptiveSubgroupTextStacking("center", AdaptiveSubgroupTextStacking.Center); - AssertAdaptiveSubgroupTextStacking("bottom", AdaptiveSubgroupTextStacking.Bottom); - } + private static void AssertAdaptiveSubgroupProperty(string expectedPropertyName, string expectedPropertyValue, AdaptiveSubgroup subgroup) + { + AssertAdaptiveSubgroup($"", subgroup); + } - private static void AssertAdaptiveSubgroupTextStacking(string expectedValue, AdaptiveSubgroupTextStacking textStacking) + private static void AssertAdaptiveSubgroup(string expectedSubgroupXml, AdaptiveSubgroup subgroup) + { + AdaptiveGroup group = new AdaptiveGroup() { - AssertAdaptiveSubgroupProperty("hint-textStacking", expectedValue, new AdaptiveSubgroup() + Children = { - HintTextStacking = textStacking - }); - } + subgroup + } + }; - [TestMethod] - public void Test_Adaptive_Subgroup_DefaultNullValues() - { - AssertAdaptiveSubgroup("", new AdaptiveSubgroup() - { - HintTextStacking = AdaptiveSubgroupTextStacking.Default, - HintWeight = null - }); - } + AssertAdaptiveChild("" + expectedSubgroupXml + "", group); + } - private static void AssertAdaptiveSubgroupProperty(string expectedPropertyName, string expectedPropertyValue, AdaptiveSubgroup subgroup) - { - AssertAdaptiveSubgroup($"", subgroup); - } + private static void AssertAdaptiveChild(string expectedAdaptiveChildXml, IAdaptiveChild child) + { + AssertAdaptiveChildInToast(expectedAdaptiveChildXml, child); + AssertAdaptiveChildInTile(expectedAdaptiveChildXml, child); - private static void AssertAdaptiveSubgroup(string expectedSubgroupXml, AdaptiveSubgroup subgroup) + // Also assert them within group/subgroup if possible! + if (child is IAdaptiveSubgroupChild) { AdaptiveGroup group = new AdaptiveGroup() { Children = { - subgroup - } - }; - - AssertAdaptiveChild("" + expectedSubgroupXml + "", group); - } - - private static void AssertAdaptiveChild(string expectedAdaptiveChildXml, IAdaptiveChild child) - { - AssertAdaptiveChildInToast(expectedAdaptiveChildXml, child); - AssertAdaptiveChildInTile(expectedAdaptiveChildXml, child); - - // Also assert them within group/subgroup if possible! - if (child is IAdaptiveSubgroupChild) - { - AdaptiveGroup group = new AdaptiveGroup() - { - Children = + new AdaptiveSubgroup() { - new AdaptiveSubgroup() + Children = { - Children = - { - child as IAdaptiveSubgroupChild - } + child as IAdaptiveSubgroupChild } } - }; + } + }; - string expectedGroupXml = "" + expectedAdaptiveChildXml + ""; + string expectedGroupXml = "" + expectedAdaptiveChildXml + ""; - AssertAdaptiveChildInToast(expectedGroupXml, group); - AssertAdaptiveChildInTile(expectedGroupXml, group); - } + AssertAdaptiveChildInToast(expectedGroupXml, group); + AssertAdaptiveChildInTile(expectedGroupXml, group); } + } - private static void AssertAdaptiveChildInToast(string expectedAdaptiveChildXml, IAdaptiveChild child) - { - var binding = new ToastBindingGeneric(); + private static void AssertAdaptiveChildInToast(string expectedAdaptiveChildXml, IAdaptiveChild child) + { + var binding = new ToastBindingGeneric(); - // If the child isn't text, we need to add a text element so notification is valid - if (!(child is AdaptiveText)) + // If the child isn't text, we need to add a text element so notification is valid + if (!(child is AdaptiveText)) + { + binding.Children.Add(new AdaptiveText() { - binding.Children.Add(new AdaptiveText() - { - Text = "Required text element" - }); + Text = "Required text element" + }); - expectedAdaptiveChildXml = "Required text element" + expectedAdaptiveChildXml; - } + expectedAdaptiveChildXml = "Required text element" + expectedAdaptiveChildXml; + } - binding.Children.Add((IToastBindingGenericChild)child); + binding.Children.Add((IToastBindingGenericChild)child); - var content = new ToastContent() + var content = new ToastContent() + { + Visual = new ToastVisual() { - Visual = new ToastVisual() - { - BindingGeneric = binding - } - }; + BindingGeneric = binding + } + }; - string expectedFinalXml = "" + expectedAdaptiveChildXml + ""; + string expectedFinalXml = "" + expectedAdaptiveChildXml + ""; - AssertHelper.AssertToast(expectedFinalXml, content); - } + AssertHelper.AssertToast(expectedFinalXml, content); + } - private static void AssertAdaptiveChildInTile(string expectedAdaptiveChildXml, IAdaptiveChild child) + private static void AssertAdaptiveChildInTile(string expectedAdaptiveChildXml, IAdaptiveChild child) + { + var content = new TileContent() { - var content = new TileContent() + Visual = new TileVisual() { - Visual = new TileVisual() + TileMedium = new TileBinding() { - TileMedium = new TileBinding() + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + Children = { - Children = - { - (ITileBindingContentAdaptiveChild)child - } + (ITileBindingContentAdaptiveChild)child } } } - }; + } + }; - string expectedFinalXml = "" + expectedAdaptiveChildXml + ""; + string expectedFinalXml = "" + expectedAdaptiveChildXml + ""; - AssertHelper.AssertTile(expectedFinalXml, content); - } + AssertHelper.AssertTile(expectedFinalXml, content); } } #endif diff --git a/components/Notifications/tests/Test_Badge_Xml.cs b/components/Notifications/tests/Test_Badge_Xml.cs index 5ed17506f..392f986ac 100644 --- a/components/Notifications/tests/Test_Badge_Xml.cs +++ b/components/Notifications/tests/Test_Badge_Xml.cs @@ -8,70 +8,69 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; #nullable disable -namespace NotificationsExperiment.Tests +namespace NotificationsExperiment.Tests; + +[TestClass] +public class Test_Badge_Xml { - [TestClass] - public class Test_Badge_Xml + [TestMethod] + public void Test_Badge_Xml_Numeric_0() { - [TestMethod] - public void Test_Badge_Xml_Numeric_0() - { - AssertBadgeValue("0", new BadgeNumericContent(0)); - } + AssertBadgeValue("0", new BadgeNumericContent(0)); + } - [TestMethod] - public void Test_Badge_Xml_Numeric_1() - { - AssertBadgeValue("1", new BadgeNumericContent(1)); - } + [TestMethod] + public void Test_Badge_Xml_Numeric_1() + { + AssertBadgeValue("1", new BadgeNumericContent(1)); + } - [TestMethod] - public void Test_Badge_Xml_Numeric_2() - { - AssertBadgeValue("2", new BadgeNumericContent(2)); - } + [TestMethod] + public void Test_Badge_Xml_Numeric_2() + { + AssertBadgeValue("2", new BadgeNumericContent(2)); + } - [TestMethod] - public void Test_Badge_Xml_Numeric_546() - { - AssertBadgeValue("546", new BadgeNumericContent(546)); - } + [TestMethod] + public void Test_Badge_Xml_Numeric_546() + { + AssertBadgeValue("546", new BadgeNumericContent(546)); + } - [TestMethod] - public void Test_Badge_Xml_Numeric_Max() - { - AssertBadgeValue(uint.MaxValue.ToString(), new BadgeNumericContent(uint.MaxValue)); - } + [TestMethod] + public void Test_Badge_Xml_Numeric_Max() + { + AssertBadgeValue(uint.MaxValue.ToString(), new BadgeNumericContent(uint.MaxValue)); + } - [TestMethod] - public void Test_Badge_Xml_Glyph_None() - { - AssertBadgeValue("none", new BadgeGlyphContent(BadgeGlyphValue.None)); - } + [TestMethod] + public void Test_Badge_Xml_Glyph_None() + { + AssertBadgeValue("none", new BadgeGlyphContent(BadgeGlyphValue.None)); + } - [TestMethod] - public void Test_Badge_Xml_Glyph_Alert() - { - AssertBadgeValue("alert", new BadgeGlyphContent(BadgeGlyphValue.Alert)); - } + [TestMethod] + public void Test_Badge_Xml_Glyph_Alert() + { + AssertBadgeValue("alert", new BadgeGlyphContent(BadgeGlyphValue.Alert)); + } - [TestMethod] - public void Test_Badge_Xml_Glyph_Error() - { - AssertBadgeValue("error", new BadgeGlyphContent(BadgeGlyphValue.Error)); - } + [TestMethod] + public void Test_Badge_Xml_Glyph_Error() + { + AssertBadgeValue("error", new BadgeGlyphContent(BadgeGlyphValue.Error)); + } - private static void AssertBadgeValue(string expectedValue, INotificationContent notificationContent) - { - AssertPayload("", notificationContent); - } + private static void AssertBadgeValue(string expectedValue, INotificationContent notificationContent) + { + AssertPayload("", notificationContent); + } - private static void AssertPayload(string expectedXml, INotificationContent notificationContent) - { - AssertHelper.AssertXml(expectedXml, notificationContent.GetContent()); + private static void AssertPayload(string expectedXml, INotificationContent notificationContent) + { + AssertHelper.AssertXml(expectedXml, notificationContent.GetContent()); - AssertHelper.AssertXml(expectedXml, notificationContent.GetXml().GetXml()); - } + AssertHelper.AssertXml(expectedXml, notificationContent.GetXml().GetXml()); } } #endif diff --git a/components/Notifications/tests/Test_Tile_Xml.cs b/components/Notifications/tests/Test_Tile_Xml.cs index f648c2b69..2657b2c08 100644 --- a/components/Notifications/tests/Test_Tile_Xml.cs +++ b/components/Notifications/tests/Test_Tile_Xml.cs @@ -9,1395 +9,1395 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; #nullable disable -namespace NotificationsExperiment.Tests +namespace NotificationsExperiment.Tests; + +[TestClass] +public class Test_Tile_Xml { - [TestClass] - public class Test_Tile_Xml + [TestMethod] + public void Test_Tile_Xml_Tile_Default() { - [TestMethod] - public void Test_Tile_Xml_Tile_Default() - { - TileContent tile = new TileContent(); + TileContent tile = new TileContent(); - AssertPayload("", tile); - } + AssertPayload("", tile); + } - [TestMethod] - public void Test_Tile_Xml_Visual_Default() - { - // Assert the defaults - AssertVisual("", new TileVisual()); - } + [TestMethod] + public void Test_Tile_Xml_Visual_Default() + { + // Assert the defaults + AssertVisual("", new TileVisual()); + } - [TestMethod] - public void Test_Tile_Xml_Visual_AddImageQuery_False() - { - AssertVisual( - "", - new TileVisual() - { - AddImageQuery = false - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_AddImageQuery_False() + { + AssertVisual( + "", + new TileVisual() + { + AddImageQuery = false + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_AddImageQuery_True() - { - AssertVisual( - "", - new TileVisual() - { - AddImageQuery = true - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_AddImageQuery_True() + { + AssertVisual( + "", + new TileVisual() + { + AddImageQuery = true + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_BaseUri_Null() - { - AssertVisual( - "", - new TileVisual() - { - BaseUri = null - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_BaseUri_Null() + { + AssertVisual( + "", + new TileVisual() + { + BaseUri = null + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_BaseUri_Value() - { - AssertVisual( - "", - new TileVisual() - { - BaseUri = new Uri("http://msn.com") - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_BaseUri_Value() + { + AssertVisual( + "", + new TileVisual() + { + BaseUri = new Uri("http://msn.com") + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_Branding_Auto() - { - AssertVisual( - "", - new TileVisual() - { - Branding = TileBranding.Auto - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_Branding_Auto() + { + AssertVisual( + "", + new TileVisual() + { + Branding = TileBranding.Auto + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_Branding_Name() - { - AssertVisual( - "", - new TileVisual() - { - Branding = TileBranding.Name - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_Branding_Name() + { + AssertVisual( + "", + new TileVisual() + { + Branding = TileBranding.Name + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_Branding_Logo() - { - AssertVisual( - "", - new TileVisual() - { - Branding = TileBranding.Logo - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_Branding_Logo() + { + AssertVisual( + "", + new TileVisual() + { + Branding = TileBranding.Logo + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_Branding_NameAndLogo() - { - AssertVisual( - "", - new TileVisual() - { - Branding = TileBranding.NameAndLogo - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_Branding_NameAndLogo() + { + AssertVisual( + "", + new TileVisual() + { + Branding = TileBranding.NameAndLogo + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_Branding_None() - { - AssertVisual( - "", - new TileVisual() - { - Branding = TileBranding.None - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_Branding_None() + { + AssertVisual( + "", + new TileVisual() + { + Branding = TileBranding.None + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_ContentId_Null() - { - AssertVisual( - "", - new TileVisual() - { - ContentId = null - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_ContentId_Null() + { + AssertVisual( + "", + new TileVisual() + { + ContentId = null + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_ContentId_Value() - { - AssertVisual( - "", - new TileVisual() - { - ContentId = "tsla" - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_ContentId_Value() + { + AssertVisual( + "", + new TileVisual() + { + ContentId = "tsla" + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_DisplayName_Null() - { - AssertVisual( - "", - new TileVisual() - { - DisplayName = null - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_DisplayName_Null() + { + AssertVisual( + "", + new TileVisual() + { + DisplayName = null + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_DisplayName_Value() - { - AssertVisual( - "", - new TileVisual() - { - DisplayName = "My name" - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_DisplayName_Value() + { + AssertVisual( + "", + new TileVisual() + { + DisplayName = "My name" + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_Language_Null() - { - AssertVisual( - "", - new TileVisual() - { - Language = null - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_Language_Null() + { + AssertVisual( + "", + new TileVisual() + { + Language = null + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_Language_Value() - { - AssertVisual( - "", - new TileVisual() - { - Language = "en-US" - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_Language_Value() + { + AssertVisual( + "", + new TileVisual() + { + Language = "en-US" + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_Arguments_Null() - { - AssertVisual( - "", - new TileVisual() - { - Arguments = null - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_Arguments_Null() + { + AssertVisual( + "", + new TileVisual() + { + Arguments = null + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_Arguments_EmptyString() - { - AssertVisual( - "", - new TileVisual() - { - Arguments = string.Empty - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_Arguments_EmptyString() + { + AssertVisual( + "", + new TileVisual() + { + Arguments = string.Empty + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_Arguments_Value() - { - AssertVisual( - "", - new TileVisual() - { - Arguments = "action=viewStory&story=53" - }); - } + [TestMethod] + public void Test_Tile_Xml_Visual_Arguments_Value() + { + AssertVisual( + "", + new TileVisual() + { + Arguments = "action=viewStory&story=53" + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_LockDetailedStatus1_NoMatchingText() - { - AssertVisual( - "AwesomeCool", - new TileVisual() - { - LockDetailedStatus1 = "Status 1", + [TestMethod] + public void Test_Tile_Xml_Visual_LockDetailedStatus1_NoMatchingText() + { + AssertVisual( + "AwesomeCool", + new TileVisual() + { + LockDetailedStatus1 = "Status 1", - TileWide = new TileBinding() + TileWide = new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + Children = { - Children = - { - new AdaptiveText() { Text = "Awesome" }, - new AdaptiveText() { Text = "Cool" } - } + new AdaptiveText() { Text = "Awesome" }, + new AdaptiveText() { Text = "Cool" } } } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_LockDetailedStatus1_MatchingText_InBinding() - { - AssertVisual( - "AwesomeCoolStatus 1Blah", - new TileVisual() - { - LockDetailedStatus1 = "Status 1", + [TestMethod] + public void Test_Tile_Xml_Visual_LockDetailedStatus1_MatchingText_InBinding() + { + AssertVisual( + "AwesomeCoolStatus 1Blah", + new TileVisual() + { + LockDetailedStatus1 = "Status 1", - TileWide = new TileBinding() + TileWide = new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + Children = { - Children = - { - new AdaptiveText() { Text = "Awesome" }, - new AdaptiveText() { Text = "Cool" }, - new AdaptiveText() { Text = "Status 1" }, - new AdaptiveText() { Text = "Blah" } - } + new AdaptiveText() { Text = "Awesome" }, + new AdaptiveText() { Text = "Cool" }, + new AdaptiveText() { Text = "Status 1" }, + new AdaptiveText() { Text = "Blah" } } } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_LockDetailedStatus1_MatchingText_InSubgroup() - { - // The lockscreen only looks at ID's in the immediate binding children. So anything in the groups/subgroups are - // ignored. Thus, if text matches there, it still has to be placed as a hint. - AssertVisual( - "AwesomeStatus 1CoolBlah", - new TileVisual() - { - LockDetailedStatus1 = "Status 1", + [TestMethod] + public void Test_Tile_Xml_Visual_LockDetailedStatus1_MatchingText_InSubgroup() + { + // The lockscreen only looks at ID's in the immediate binding children. So anything in the groups/subgroups are + // ignored. Thus, if text matches there, it still has to be placed as a hint. + AssertVisual( + "AwesomeStatus 1CoolBlah", + new TileVisual() + { + LockDetailedStatus1 = "Status 1", - TileWide = new TileBinding() + TileWide = new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + Children = { - Children = + new AdaptiveText() { Text = "Awesome" }, + new AdaptiveGroup() { - new AdaptiveText() { Text = "Awesome" }, - new AdaptiveGroup() + Children = { - Children = + new AdaptiveSubgroup() { - new AdaptiveSubgroup() + Children = { - Children = + new AdaptiveImage() { - new AdaptiveImage() - { - Source = "Fable.jpg" - }, - new AdaptiveText() { Text = "Status 1" }, - new AdaptiveText() { Text = "Cool" } - } + Source = "Fable.jpg" + }, + new AdaptiveText() { Text = "Status 1" }, + new AdaptiveText() { Text = "Cool" } } } - }, - new AdaptiveText() { Text = "Blah" } - } + } + }, + new AdaptiveText() { Text = "Blah" } } } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_LockDetailedStatus2_NoMatchingText() - { - AssertVisual( - "AwesomeCool", - new TileVisual() - { - LockDetailedStatus2 = "Status 2", + [TestMethod] + public void Test_Tile_Xml_Visual_LockDetailedStatus2_NoMatchingText() + { + AssertVisual( + "AwesomeCool", + new TileVisual() + { + LockDetailedStatus2 = "Status 2", - TileWide = new TileBinding() + TileWide = new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + Children = { - Children = - { - new AdaptiveText() { Text = "Awesome" }, - new AdaptiveText() { Text = "Cool" } - } + new AdaptiveText() { Text = "Awesome" }, + new AdaptiveText() { Text = "Cool" } } } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_LockDetailedStatus2_MatchingText_InBinding() - { - AssertVisual( - "AwesomeCoolStatus 2Blah", - new TileVisual() - { - LockDetailedStatus2 = "Status 2", + [TestMethod] + public void Test_Tile_Xml_Visual_LockDetailedStatus2_MatchingText_InBinding() + { + AssertVisual( + "AwesomeCoolStatus 2Blah", + new TileVisual() + { + LockDetailedStatus2 = "Status 2", - TileWide = new TileBinding() + TileWide = new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + Children = { - Children = - { - new AdaptiveText() { Text = "Awesome" }, - new AdaptiveText() { Text = "Cool" }, - new AdaptiveText() { Text = "Status 2" }, - new AdaptiveText() { Text = "Blah" } - } + new AdaptiveText() { Text = "Awesome" }, + new AdaptiveText() { Text = "Cool" }, + new AdaptiveText() { Text = "Status 2" }, + new AdaptiveText() { Text = "Blah" } } } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_LockDetailedStatus2_MatchingText_InSubgroup() - { - AssertVisual( - "AwesomeStatus 2CoolBlah", - new TileVisual() - { - LockDetailedStatus2 = "Status 2", + [TestMethod] + public void Test_Tile_Xml_Visual_LockDetailedStatus2_MatchingText_InSubgroup() + { + AssertVisual( + "AwesomeStatus 2CoolBlah", + new TileVisual() + { + LockDetailedStatus2 = "Status 2", - TileWide = new TileBinding() + TileWide = new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + Children = { - Children = + new AdaptiveText() { Text = "Awesome" }, + new AdaptiveGroup() { - new AdaptiveText() { Text = "Awesome" }, - new AdaptiveGroup() + Children = { - Children = + new AdaptiveSubgroup() { - new AdaptiveSubgroup() + Children = { - Children = + new AdaptiveImage() { - new AdaptiveImage() - { - Source = "Fable.jpg" - }, - new AdaptiveText() { Text = "Status 2" }, - new AdaptiveText() { Text = "Cool" } - } + Source = "Fable.jpg" + }, + new AdaptiveText() { Text = "Status 2" }, + new AdaptiveText() { Text = "Cool" } } } - }, - new AdaptiveText() { Text = "Blah" } - } + } + }, + new AdaptiveText() { Text = "Blah" } } } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_LockDetailedStatus3_NoMatchingText() - { - AssertVisual( - "AwesomeCool", - new TileVisual() - { - LockDetailedStatus3 = "Status 3", + [TestMethod] + public void Test_Tile_Xml_Visual_LockDetailedStatus3_NoMatchingText() + { + AssertVisual( + "AwesomeCool", + new TileVisual() + { + LockDetailedStatus3 = "Status 3", - TileWide = new TileBinding() + TileWide = new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + Children = { - Children = - { - new AdaptiveText() { Text = "Awesome" }, - new AdaptiveText() { Text = "Cool" } - } + new AdaptiveText() { Text = "Awesome" }, + new AdaptiveText() { Text = "Cool" } } } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_LockDetailedStatus3_MatchingText_InBinding() - { - AssertVisual( - "AwesomeCoolStatus 3Blah", - new TileVisual() - { - LockDetailedStatus3 = "Status 3", + [TestMethod] + public void Test_Tile_Xml_Visual_LockDetailedStatus3_MatchingText_InBinding() + { + AssertVisual( + "AwesomeCoolStatus 3Blah", + new TileVisual() + { + LockDetailedStatus3 = "Status 3", - TileWide = new TileBinding() + TileWide = new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + Children = { - Children = - { - new AdaptiveText() { Text = "Awesome" }, - new AdaptiveText() { Text = "Cool" }, - new AdaptiveText() { Text = "Status 3" }, - new AdaptiveText() { Text = "Blah" } - } + new AdaptiveText() { Text = "Awesome" }, + new AdaptiveText() { Text = "Cool" }, + new AdaptiveText() { Text = "Status 3" }, + new AdaptiveText() { Text = "Blah" } } } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Visual_LockDetailedStatus3_MatchingText_InSubgroup() - { - AssertVisual( - "AwesomeStatus 3CoolBlah", - new TileVisual() - { - LockDetailedStatus3 = "Status 3", + [TestMethod] + public void Test_Tile_Xml_Visual_LockDetailedStatus3_MatchingText_InSubgroup() + { + AssertVisual( + "AwesomeStatus 3CoolBlah", + new TileVisual() + { + LockDetailedStatus3 = "Status 3", - TileWide = new TileBinding() + TileWide = new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + Children = { - Children = + new AdaptiveText() { Text = "Awesome" }, + new AdaptiveGroup() { - new AdaptiveText() { Text = "Awesome" }, - new AdaptiveGroup() + Children = { - Children = + new AdaptiveSubgroup() { - new AdaptiveSubgroup() + Children = { - Children = + new AdaptiveImage() { - new AdaptiveImage() - { - Source = "Fable.jpg" - }, - new AdaptiveText() { Text = "Status 3" }, - new AdaptiveText() { Text = "Cool" } - } + Source = "Fable.jpg" + }, + new AdaptiveText() { Text = "Status 3" }, + new AdaptiveText() { Text = "Cool" } } } - }, - new AdaptiveText() { Text = "Blah" } - } + } + }, + new AdaptiveText() { Text = "Blah" } } } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_Default() - { - AssertBindingMedium("", new TileBinding()); - } + [TestMethod] + public void Test_Tile_Xml_Binding_Default() + { + AssertBindingMedium("", new TileBinding()); + } - [TestMethod] - public void Test_Tile_Xml_Binding_AddImageQuery_False() - { - AssertBindingMedium( - "", - new TileBinding() - { - AddImageQuery = false - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_AddImageQuery_False() + { + AssertBindingMedium( + "", + new TileBinding() + { + AddImageQuery = false + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_AddImageQuery_True() - { - AssertBindingMedium( - "", - new TileBinding() - { - AddImageQuery = true - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_AddImageQuery_True() + { + AssertBindingMedium( + "", + new TileBinding() + { + AddImageQuery = true + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_BaseUri_Null() - { - AssertBindingMedium( - "", - new TileBinding() - { - BaseUri = null - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_BaseUri_Null() + { + AssertBindingMedium( + "", + new TileBinding() + { + BaseUri = null + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_BaseUri_Value() - { - AssertBindingMedium( - "", - new TileBinding() - { - BaseUri = new Uri("http://msn.com") - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_BaseUri_Value() + { + AssertBindingMedium( + "", + new TileBinding() + { + BaseUri = new Uri("http://msn.com") + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_Branding_Auto() - { - AssertBindingMedium( - "", - new TileBinding() - { - Branding = TileBranding.Auto - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_Branding_Auto() + { + AssertBindingMedium( + "", + new TileBinding() + { + Branding = TileBranding.Auto + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_Branding_None() - { - AssertBindingMedium( - "", - new TileBinding() - { - Branding = TileBranding.None - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_Branding_None() + { + AssertBindingMedium( + "", + new TileBinding() + { + Branding = TileBranding.None + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_Branding_Name() - { - AssertBindingMedium( - "", - new TileBinding() - { - Branding = TileBranding.Name - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_Branding_Name() + { + AssertBindingMedium( + "", + new TileBinding() + { + Branding = TileBranding.Name + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_Branding_Logo() - { - AssertBindingMedium( - "", - new TileBinding() - { - Branding = TileBranding.Logo - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_Branding_Logo() + { + AssertBindingMedium( + "", + new TileBinding() + { + Branding = TileBranding.Logo + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_Branding_NameAndLogo() - { - AssertBindingMedium( - "", - new TileBinding() - { - Branding = TileBranding.NameAndLogo - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_Branding_NameAndLogo() + { + AssertBindingMedium( + "", + new TileBinding() + { + Branding = TileBranding.NameAndLogo + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_ContentId_Null() - { - AssertBindingMedium( - "", - new TileBinding() - { - ContentId = null - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_ContentId_Null() + { + AssertBindingMedium( + "", + new TileBinding() + { + ContentId = null + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_ContentId_Value() - { - AssertBindingMedium( - "", - new TileBinding() - { - ContentId = "myId" - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_ContentId_Value() + { + AssertBindingMedium( + "", + new TileBinding() + { + ContentId = "myId" + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_DisplayName_Null() - { - AssertBindingMedium( - "", - new TileBinding() - { - DisplayName = null - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_DisplayName_Null() + { + AssertBindingMedium( + "", + new TileBinding() + { + DisplayName = null + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_DisplayName_Value() - { - AssertBindingMedium( - "", - new TileBinding() - { - DisplayName = "My name" - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_DisplayName_Value() + { + AssertBindingMedium( + "", + new TileBinding() + { + DisplayName = "My name" + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_Language_Null() - { - AssertBindingMedium( - "", - new TileBinding() - { - Language = null - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_Language_Null() + { + AssertBindingMedium( + "", + new TileBinding() + { + Language = null + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_Language_Value() - { - AssertBindingMedium( - "", - new TileBinding() - { - Language = "en-US" - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_Language_Value() + { + AssertBindingMedium( + "", + new TileBinding() + { + Language = "en-US" + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_Arguments_Null() - { - AssertBindingMedium( - "", - new TileBinding() - { - Arguments = null - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_Arguments_Null() + { + AssertBindingMedium( + "", + new TileBinding() + { + Arguments = null + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_Arguments_EmptyString() - { - AssertBindingMedium( - "", - new TileBinding() - { - Arguments = string.Empty - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_Arguments_EmptyString() + { + AssertBindingMedium( + "", + new TileBinding() + { + Arguments = string.Empty + }); + } - [TestMethod] - public void Test_Tile_Xml_Binding_Arguments_Value() - { - AssertBindingMedium( - "", - new TileBinding() - { - Arguments = "action=viewStory&storyId=52" - }); - } + [TestMethod] + public void Test_Tile_Xml_Binding_Arguments_Value() + { + AssertBindingMedium( + "", + new TileBinding() + { + Arguments = "action=viewStory&storyId=52" + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_Defaults() - { - AssertBindingMedium( - "", - new TileBinding() - { - Content = new TileBindingContentAdaptive() - }); - } + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_Defaults() + { + AssertBindingMedium( + "", + new TileBinding() + { + Content = new TileBindingContentAdaptive() + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_BackgroundImage_Value() - { - AssertBindingMedium( - "", - new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_BackgroundImage_Value() + { + AssertBindingMedium( + "", + new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - Source = "http://msn.com/image.png" - } + Source = "http://msn.com/image.png" } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_Overlay_Default() - { - AssertBindingMedium( - "", - new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_Overlay_Default() + { + AssertBindingMedium( + "", + new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - HintOverlay = 20, - Source = "Fable.jpg" - } + HintOverlay = 20, + Source = "Fable.jpg" } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_Overlay_Min() - { - AssertBindingMedium( - "", - new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_Overlay_Min() + { + AssertBindingMedium( + "", + new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - HintOverlay = 0, - Source = "Fable.jpg" - } + HintOverlay = 0, + Source = "Fable.jpg" } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_Overlay_Max() - { - AssertBindingMedium( - "", - new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_Overlay_Max() + { + AssertBindingMedium( + "", + new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - HintOverlay = 100, - Source = "Fable.jpg" - } + HintOverlay = 100, + Source = "Fable.jpg" } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_Overlay_AboveDefault() - { - AssertBindingMedium( - "", - new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_Overlay_AboveDefault() + { + AssertBindingMedium( + "", + new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - HintOverlay = 40, - Source = "Fable.jpg" - } + HintOverlay = 40, + Source = "Fable.jpg" } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_Overlay_BelowDefault() - { - AssertBindingMedium( - "", - new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_Overlay_BelowDefault() + { + AssertBindingMedium( + "", + new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - HintOverlay = 10, - Source = "Fable.jpg" - } + HintOverlay = 10, + Source = "Fable.jpg" } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_BackgroundImage_Overlay_BelowMin() + [TestMethod] + public void Test_Tile_Xml_BackgroundImage_Overlay_BelowMin() + { + try { - try + new TileBackgroundImage() { - new TileBackgroundImage() - { - HintOverlay = -1, - Source = "Fable.jpg" - }; - } - catch - { - return; - } - - Assert.Fail("Exception should have been thrown."); + HintOverlay = -1, + Source = "Fable.jpg" + }; + } + catch + { + return; } - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_Overlay_AboveMax() + Assert.Fail("Exception should have been thrown."); + } + + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_Overlay_AboveMax() + { + try { - try - { - new TileBackgroundImage() - { - HintOverlay = 101, - Source = "Fable.jpg" - }; - } - catch + new TileBackgroundImage() { - return; - } - - Assert.Fail("Exception should have been thrown."); + HintOverlay = 101, + Source = "Fable.jpg" + }; } - - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_PeekImage_Value() + catch { - AssertBindingMedium( - "alt", - new TileBinding() - { - Content = new TileBindingContentAdaptive() - { - PeekImage = new TilePeekImage() - { - Source = "http://msn.com", - AlternateText = "alt", - AddImageQuery = true - } - } - }); + return; } - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_TextStacking_Top() - { - AssertBindingMedium( - "", - new TileBinding() + Assert.Fail("Exception should have been thrown."); + } + + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_PeekImage_Value() + { + AssertBindingMedium( + "alt", + new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + PeekImage = new TilePeekImage() { - TextStacking = TileTextStacking.Top + Source = "http://msn.com", + AlternateText = "alt", + AddImageQuery = true } - }); - } + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_TextStacking_Center() - { - AssertBindingMedium( - "", - new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_TextStacking_Top() + { + AssertBindingMedium( + "", + new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() - { - TextStacking = TileTextStacking.Center - } - }); - } + TextStacking = TileTextStacking.Top + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_Root_TextStacking_Bottom() - { - AssertBindingMedium( - "", - new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_TextStacking_Center() + { + AssertBindingMedium( + "", + new TileBinding() + { + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() - { - TextStacking = TileTextStacking.Bottom - } - }); - } + TextStacking = TileTextStacking.Center + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundImage_Defaults() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_Root_TextStacking_Bottom() + { + AssertBindingMedium( + "", + new TileBinding() + { + Content = new TileBindingContentAdaptive() { - BackgroundImage = new TileBackgroundImage() - { - Source = "http://msn.com" - } - }); - } + TextStacking = TileTextStacking.Bottom + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundImage_Source() - { - AssertBindingMediumAdaptive( - "MSN Image", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundImage_Defaults() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - Source = "http://msn.com", - AddImageQuery = true, - AlternateText = "MSN Image" - } - }); - } + Source = "http://msn.com" + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundImage_Crop_None() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundImage_Source() + { + AssertBindingMediumAdaptive( + "MSN Image", + new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - Source = "http://msn.com", - HintCrop = TileBackgroundImageCrop.None - } - }); - } + Source = "http://msn.com", + AddImageQuery = true, + AlternateText = "MSN Image" + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundImage_Crop_Circle() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundImage_Crop_None() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - Source = "http://msn.com", - HintCrop = TileBackgroundImageCrop.Circle - } - }); - } + Source = "http://msn.com", + HintCrop = TileBackgroundImageCrop.None + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundImage_Overlay_0() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundImage_Crop_Circle() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - Source = "http://msn.com", - HintOverlay = 0 - } - }); - } + Source = "http://msn.com", + HintCrop = TileBackgroundImageCrop.Circle + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundImage_Overlay_20() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundImage_Overlay_0() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - Source = "http://msn.com", - HintOverlay = 20 - } - }); - } + Source = "http://msn.com", + HintOverlay = 0 + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundImage_Overlay_80() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundImage_Overlay_20() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - Source = "http://msn.com", - HintOverlay = 80 - } - }); - } + Source = "http://msn.com", + HintOverlay = 20 + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundImage_NoImageSource() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundImage_Overlay_80() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() + { + Source = "http://msn.com", + HintOverlay = 80 + } + }); + } + + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundImage_NoImageSource() + { + try { - try + TileContent c = new TileContent() { - TileContent c = new TileContent() + Visual = new TileVisual() { - Visual = new TileVisual() + TileMedium = new TileBinding() { - TileMedium = new TileBinding() + Content = new TileBindingContentAdaptive() { - Content = new TileBindingContentAdaptive() + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - // No source, which should throw exception - } + // No source, which should throw exception } } } - }; - - c.GetContent(); - } - catch (NullReferenceException) - { - return; - } - - Assert.Fail("Exception should have been thrown"); - } + } + }; - [TestMethod] - public void Test_Tile_Xml_Adaptive_PeekImage_Defaults() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() - { - PeekImage = new TilePeekImage() - { - Source = "http://msn.com" - } - }); + c.GetContent(); } - - [TestMethod] - public void Test_Tile_Xml_Adaptive_PeekImage_Source() + catch (NullReferenceException) { - AssertBindingMediumAdaptive( - "MSN Image", - new TileBindingContentAdaptive() - { - PeekImage = new TilePeekImage() - { - Source = "http://msn.com", - AddImageQuery = true, - AlternateText = "MSN Image" - } - }); + return; } - [TestMethod] - public void Test_Tile_Xml_Adaptive_PeekImage_Crop_None() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() - { - PeekImage = new TilePeekImage() - { - Source = "http://msn.com", - HintCrop = TilePeekImageCrop.None - } - }); - } + Assert.Fail("Exception should have been thrown"); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_PeekImage_Crop_Circle() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_PeekImage_Defaults() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + PeekImage = new TilePeekImage() { - PeekImage = new TilePeekImage() - { - Source = "http://msn.com", - HintCrop = TilePeekImageCrop.Circle - } - }); - } + Source = "http://msn.com" + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_PeekImage_Overlay_0() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_PeekImage_Source() + { + AssertBindingMediumAdaptive( + "MSN Image", + new TileBindingContentAdaptive() + { + PeekImage = new TilePeekImage() { - PeekImage = new TilePeekImage() - { - Source = "http://msn.com", - HintOverlay = 0 - } - }); - } + Source = "http://msn.com", + AddImageQuery = true, + AlternateText = "MSN Image" + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_PeekImage_Overlay_20() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_PeekImage_Crop_None() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + PeekImage = new TilePeekImage() { - PeekImage = new TilePeekImage() - { - Source = "http://msn.com", - HintOverlay = 20 - } - }); - } + Source = "http://msn.com", + HintCrop = TilePeekImageCrop.None + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_PeekImage_Overlay_80() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_PeekImage_Crop_Circle() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + PeekImage = new TilePeekImage() { - PeekImage = new TilePeekImage() - { - Source = "http://msn.com", - HintOverlay = 80 - } - }); - } + Source = "http://msn.com", + HintCrop = TilePeekImageCrop.Circle + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_PeekImage_NoImageSource() - { - try + [TestMethod] + public void Test_Tile_Xml_Adaptive_PeekImage_Overlay_0() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() { - TileContent c = new TileContent() + PeekImage = new TilePeekImage() { - Visual = new TileVisual() - { - TileMedium = new TileBinding() - { - Content = new TileBindingContentAdaptive() - { - PeekImage = new TilePeekImage() - { - // No source, which should throw exception when content retrieved - } - } - } - } - }; + Source = "http://msn.com", + HintOverlay = 0 + } + }); + } - c.GetContent(); - } - catch (NullReferenceException) + [TestMethod] + public void Test_Tile_Xml_Adaptive_PeekImage_Overlay_20() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() { - return; - } - - Assert.Fail("Exception should have been thrown"); - } - - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Defaults() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + PeekImage = new TilePeekImage() { - BackgroundImage = new TileBackgroundImage() - { - Source = "Background.jpg" - }, - - PeekImage = new TilePeekImage() - { - Source = "Peek.jpg" - } - }); - } + Source = "http://msn.com", + HintOverlay = 20 + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Overlay_0and0() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_PeekImage_Overlay_80() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + PeekImage = new TilePeekImage() { - BackgroundImage = new TileBackgroundImage() - { - Source = "Background.jpg", - HintOverlay = 0 - }, - - PeekImage = new TilePeekImage() - { - Source = "Peek.jpg", - HintOverlay = 0 - } - }); - } + Source = "http://msn.com", + HintOverlay = 80 + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Overlay_20and20() + [TestMethod] + public void Test_Tile_Xml_Adaptive_PeekImage_NoImageSource() + { + try { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + TileContent c = new TileContent() + { + Visual = new TileVisual() { - BackgroundImage = new TileBackgroundImage() + TileMedium = new TileBinding() { - Source = "Background.jpg", - HintOverlay = 20 - }, - - PeekImage = new TilePeekImage() - { - Source = "Peek.jpg", - HintOverlay = 20 + Content = new TileBindingContentAdaptive() + { + PeekImage = new TilePeekImage() + { + // No source, which should throw exception when content retrieved + } + } } - }); - } + } + }; - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Overlay_20and30() + c.GetContent(); + } + catch (NullReferenceException) { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() - { - BackgroundImage = new TileBackgroundImage() - { - Source = "Background.jpg", - HintOverlay = 20 - }, - - PeekImage = new TilePeekImage() - { - Source = "Peek.jpg", - HintOverlay = 30 - } - }); + return; } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Overlay_30and20() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + Assert.Fail("Exception should have been thrown"); + } + + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Defaults() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - Source = "Background.jpg", - HintOverlay = 30 - }, + Source = "Background.jpg" + }, - PeekImage = new TilePeekImage() - { - Source = "Peek.jpg", - HintOverlay = 20 - } - }); - } + PeekImage = new TilePeekImage() + { + Source = "Peek.jpg" + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Overlay_0and20() - { - AssertBindingMediumAdaptive( - "", - new TileBindingContentAdaptive() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Overlay_0and0() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() + { + BackgroundImage = new TileBackgroundImage() { - BackgroundImage = new TileBackgroundImage() - { - Source = "Background.jpg", - HintOverlay = 0 - }, + Source = "Background.jpg", + HintOverlay = 0 + }, - PeekImage = new TilePeekImage() - { - Source = "Peek.jpg", - HintOverlay = 20 - } - }); - } + PeekImage = new TilePeekImage() + { + Source = "Peek.jpg", + HintOverlay = 0 + } + }); + } - [TestMethod] - public void Test_Tile_Xml_Special_Photos_Default() - { - TileBindingContentPhotos content = new TileBindingContentPhotos() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Overlay_20and20() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() { - }; + BackgroundImage = new TileBackgroundImage() + { + Source = "Background.jpg", + HintOverlay = 20 + }, + + PeekImage = new TilePeekImage() + { + Source = "Peek.jpg", + HintOverlay = 20 + } + }); + } - AssertBindingMedium("", new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Overlay_20and30() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() { - Content = content + BackgroundImage = new TileBackgroundImage() + { + Source = "Background.jpg", + HintOverlay = 20 + }, + + PeekImage = new TilePeekImage() + { + Source = "Peek.jpg", + HintOverlay = 30 + } }); - } + } - [TestMethod] - public void Test_Tile_Xml_Special_Photos_OneImage() - { - TileBindingContentPhotos content = new TileBindingContentPhotos() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Overlay_30and20() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() { - Images = + BackgroundImage = new TileBackgroundImage() { - new TileBasicImage() - { - Source = "http://msn.com/1.jpg", - AddImageQuery = true, - AlternateText = "alternate" - } + Source = "Background.jpg", + HintOverlay = 30 + }, + + PeekImage = new TilePeekImage() + { + Source = "Peek.jpg", + HintOverlay = 20 } - }; + }); + } - AssertBindingMedium("alternate", new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Adaptive_BackgroundAndPeekImage_Overlay_0and20() + { + AssertBindingMediumAdaptive( + "", + new TileBindingContentAdaptive() { - Content = content + BackgroundImage = new TileBackgroundImage() + { + Source = "Background.jpg", + HintOverlay = 0 + }, + + PeekImage = new TilePeekImage() + { + Source = "Peek.jpg", + HintOverlay = 20 + } }); - } + } + + [TestMethod] + public void Test_Tile_Xml_Special_Photos_Default() + { + TileBindingContentPhotos content = new TileBindingContentPhotos() + { + }; + + AssertBindingMedium("", new TileBinding() + { + Content = content + }); + } - [TestMethod] - public void Test_Tile_Xml_Special_Photos_TwoImages() + [TestMethod] + public void Test_Tile_Xml_Special_Photos_OneImage() + { + TileBindingContentPhotos content = new TileBindingContentPhotos() { - TileBindingContentPhotos content = new TileBindingContentPhotos() + Images = { - Images = + new TileBasicImage() { - new TileBasicImage() - { - Source = "Assets/1.jpg" - }, - new TileBasicImage() - { - Source = "Assets/2.jpg" - } + Source = "http://msn.com/1.jpg", + AddImageQuery = true, + AlternateText = "alternate" } - }; + } + }; - AssertBindingMedium("", new TileBinding() - { - Content = content - }); - } + AssertBindingMedium("alternate", new TileBinding() + { + Content = content + }); + } - [TestMethod] - public void Test_Tile_Xml_Special_Photos_MaxImages() + [TestMethod] + public void Test_Tile_Xml_Special_Photos_TwoImages() + { + TileBindingContentPhotos content = new TileBindingContentPhotos() { - TileBindingContentPhotos content = new TileBindingContentPhotos() + Images = { - Images = + new TileBasicImage() + { + Source = "Assets/1.jpg" + }, + new TileBasicImage() { - new TileBasicImage() { Source = "1.jpg" }, - new TileBasicImage() { Source = "2.jpg" }, - new TileBasicImage() { Source = "3.jpg" }, - new TileBasicImage() { Source = "4.jpg" }, - new TileBasicImage() { Source = "5.jpg" }, - new TileBasicImage() { Source = "6.jpg" }, - new TileBasicImage() { Source = "7.jpg" }, - new TileBasicImage() { Source = "8.jpg" }, - new TileBasicImage() { Source = "9.jpg" }, - new TileBasicImage() { Source = "10.jpg" }, - new TileBasicImage() { Source = "11.jpg" }, - new TileBasicImage() { Source = "12.jpg" } + Source = "Assets/2.jpg" } - }; + } + }; + + AssertBindingMedium("", new TileBinding() + { + Content = content + }); + } + + [TestMethod] + public void Test_Tile_Xml_Special_Photos_MaxImages() + { + TileBindingContentPhotos content = new TileBindingContentPhotos() + { + Images = + { + new TileBasicImage() { Source = "1.jpg" }, + new TileBasicImage() { Source = "2.jpg" }, + new TileBasicImage() { Source = "3.jpg" }, + new TileBasicImage() { Source = "4.jpg" }, + new TileBasicImage() { Source = "5.jpg" }, + new TileBasicImage() { Source = "6.jpg" }, + new TileBasicImage() { Source = "7.jpg" }, + new TileBasicImage() { Source = "8.jpg" }, + new TileBasicImage() { Source = "9.jpg" }, + new TileBasicImage() { Source = "10.jpg" }, + new TileBasicImage() { Source = "11.jpg" }, + new TileBasicImage() { Source = "12.jpg" } + } + }; - AssertBindingMedium( - @" + AssertBindingMedium( + @" @@ -1411,269 +1411,268 @@ public void Test_Tile_Xml_Special_Photos_MaxImages() ", new TileBinding() - { - Content = content - }); - } - - [TestMethod] - public void Test_Tile_Xml_Special_Photos_TooManyImages() - { - try - { - new TileBindingContentPhotos() - { - Images = - { - new TileBasicImage(), - new TileBasicImage(), - new TileBasicImage(), - new TileBasicImage(), - new TileBasicImage(), - new TileBasicImage(), - new TileBasicImage(), - new TileBasicImage(), - new TileBasicImage(), - new TileBasicImage(), - new TileBasicImage(), - new TileBasicImage(), - new TileBasicImage() - } - }; - } - catch - { - return; - } - - Assert.Fail("Exception should have been thrown, adding more than 12 images isn't supported."); - } - - [TestMethod] - public void Test_Tile_Xml_Special_People_Defaults() - { - TileBindingContentPeople content = new TileBindingContentPeople(); - - AssertBindingMedium("", new TileBinding() { Content = content }); - } + } - [TestMethod] - public void Test_Tile_Xml_Special_People_OneImage() + [TestMethod] + public void Test_Tile_Xml_Special_Photos_TooManyImages() + { + try { - TileBindingContentPeople content = new TileBindingContentPeople() + new TileBindingContentPhotos() { Images = { + new TileBasicImage(), + new TileBasicImage(), + new TileBasicImage(), + new TileBasicImage(), + new TileBasicImage(), + new TileBasicImage(), + new TileBasicImage(), + new TileBasicImage(), + new TileBasicImage(), + new TileBasicImage(), + new TileBasicImage(), + new TileBasicImage(), new TileBasicImage() - { - Source = "http://msn.com/1.jpg", - AddImageQuery = true, - AlternateText = "alternate" - } } }; - - AssertBindingMedium("alternate", new TileBinding() - { - Content = content - }); } + catch + { + return; + } + + Assert.Fail("Exception should have been thrown, adding more than 12 images isn't supported."); + } + + [TestMethod] + public void Test_Tile_Xml_Special_People_Defaults() + { + TileBindingContentPeople content = new TileBindingContentPeople(); + + AssertBindingMedium("", new TileBinding() + { + Content = content + }); + } - [TestMethod] - public void Test_Tile_Xml_Special_People_TwoImages() + [TestMethod] + public void Test_Tile_Xml_Special_People_OneImage() + { + TileBindingContentPeople content = new TileBindingContentPeople() { - TileBindingContentPeople content = new TileBindingContentPeople() + Images = { - Images = + new TileBasicImage() { - new TileBasicImage() { Source = "Assets/1.jpg" }, - new TileBasicImage() { Source = "Assets/2.jpg" } + Source = "http://msn.com/1.jpg", + AddImageQuery = true, + AlternateText = "alternate" } - }; + } + }; - AssertBindingMedium("", new TileBinding() - { - Content = content - }); - } + AssertBindingMedium("alternate", new TileBinding() + { + Content = content + }); + } - [TestMethod] - public void Test_Tile_Xml_Special_People_ManyImages() + [TestMethod] + public void Test_Tile_Xml_Special_People_TwoImages() + { + TileBindingContentPeople content = new TileBindingContentPeople() { - string payload = ""; + Images = + { + new TileBasicImage() { Source = "Assets/1.jpg" }, + new TileBasicImage() { Source = "Assets/2.jpg" } + } + }; - TileBindingContentPeople content = new TileBindingContentPeople(); + AssertBindingMedium("", new TileBinding() + { + Content = content + }); + } - // Add 30 images - for (int i = 1; i <= 30; i++) - { - string src = i + ".jpg"; + [TestMethod] + public void Test_Tile_Xml_Special_People_ManyImages() + { + string payload = ""; - content.Images.Add(new TileBasicImage() { Source = src }); - payload += $""; - } + TileBindingContentPeople content = new TileBindingContentPeople(); - payload += ""; + // Add 30 images + for (int i = 1; i <= 30; i++) + { + string src = i + ".jpg"; - AssertBindingMedium(payload, new TileBinding() - { - Content = content - }); + content.Images.Add(new TileBasicImage() { Source = src }); + payload += $""; } - [TestMethod] - public void Test_Tile_Xml_Special_Contact_Defaults() + payload += ""; + + AssertBindingMedium(payload, new TileBinding() { - TileBindingContentContact content = new TileBindingContentContact(); + Content = content + }); + } - AssertBindingMedium("", new TileBinding() - { - Content = content - }); - } + [TestMethod] + public void Test_Tile_Xml_Special_Contact_Defaults() + { + TileBindingContentContact content = new TileBindingContentContact(); - [TestMethod] - public void Test_Tile_Xml_Special_Contact_Text() + AssertBindingMedium("", new TileBinding() { - TileBindingContentContact content = new TileBindingContentContact() - { - Text = new TileBasicText() - { - Text = "Hello world", - Lang = "en-US" - } - }; + Content = content + }); + } - AssertBindingMedium("Hello world", new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Special_Contact_Text() + { + TileBindingContentContact content = new TileBindingContentContact() + { + Text = new TileBasicText() { - Content = content - }); - } + Text = "Hello world", + Lang = "en-US" + } + }; - [TestMethod] - public void Test_Tile_Xml_Special_Contact_Image() + AssertBindingMedium("Hello world", new TileBinding() { - TileBindingContentContact content = new TileBindingContentContact() - { - Image = new TileBasicImage() - { - Source = "http://msn.com/img.jpg", - AddImageQuery = true, - AlternateText = "John Smith" - } - }; + Content = content + }); + } - AssertBindingMedium("John Smith", new TileBinding() + [TestMethod] + public void Test_Tile_Xml_Special_Contact_Image() + { + TileBindingContentContact content = new TileBindingContentContact() + { + Image = new TileBasicImage() { - Content = content - }); - } + Source = "http://msn.com/img.jpg", + AddImageQuery = true, + AlternateText = "John Smith" + } + }; + + AssertBindingMedium("John Smith", new TileBinding() + { + Content = content + }); + } - [TestMethod] - public void Test_Tile_Xml_Special_Contact_Both_Small() + [TestMethod] + public void Test_Tile_Xml_Special_Contact_Both_Small() + { + TileBindingContentContact content = new TileBindingContentContact() { - TileBindingContentContact content = new TileBindingContentContact() + Text = new TileBasicText() { - Text = new TileBasicText() - { - Text = "Hello world" - }, + Text = "Hello world" + }, - Image = new TileBasicImage() { Source = "Assets/img.jpg" } - }; + Image = new TileBasicImage() { Source = "Assets/img.jpg" } + }; - // Small doesn't support the text, so it doesn't output the text element when rendered for small - AssertVisual("", new TileVisual() - { - TileSmall = new TileBinding() { Content = content } - }); - } + // Small doesn't support the text, so it doesn't output the text element when rendered for small + AssertVisual("", new TileVisual() + { + TileSmall = new TileBinding() { Content = content } + }); + } - [TestMethod] - public void Test_Tile_Xml_Special_Contact_Both_Medium() + [TestMethod] + public void Test_Tile_Xml_Special_Contact_Both_Medium() + { + TileBindingContentContact content = new TileBindingContentContact() { - TileBindingContentContact content = new TileBindingContentContact() + Text = new TileBasicText() { - Text = new TileBasicText() - { - Text = "Hello world" - }, + Text = "Hello world" + }, - Image = new TileBasicImage() { Source = "Assets/img.jpg" } - }; + Image = new TileBasicImage() { Source = "Assets/img.jpg" } + }; - // Text is written before the image element - AssertVisual("Hello world", new TileVisual() - { - TileMedium = new TileBinding() { Content = content } - }); - } + // Text is written before the image element + AssertVisual("Hello world", new TileVisual() + { + TileMedium = new TileBinding() { Content = content } + }); + } - [TestMethod] - public void Test_Tile_Xml_Special_Iconic_Small() + [TestMethod] + public void Test_Tile_Xml_Special_Iconic_Small() + { + AssertVisual("", new TileVisual() { - AssertVisual("", new TileVisual() - { - TileSmall = new TileBinding() { Content = new TileBindingContentIconic() } - }); - } + TileSmall = new TileBinding() { Content = new TileBindingContentIconic() } + }); + } - [TestMethod] - public void Test_Tile_Xml_Special_Iconic_Medium() + [TestMethod] + public void Test_Tile_Xml_Special_Iconic_Medium() + { + AssertVisual("", new TileVisual() { - AssertVisual("", new TileVisual() - { - TileMedium = new TileBinding() { Content = new TileBindingContentIconic() } - }); - } + TileMedium = new TileBinding() { Content = new TileBindingContentIconic() } + }); + } - [TestMethod] - public void Test_Tile_Xml_Special_Iconic_Image() + [TestMethod] + public void Test_Tile_Xml_Special_Iconic_Image() + { + AssertVisual("iconic", new TileVisual() { - AssertVisual("iconic", new TileVisual() + TileMedium = new TileBinding() { - TileMedium = new TileBinding() + Content = new TileBindingContentIconic() { - Content = new TileBindingContentIconic() + Icon = new TileBasicImage() { - Icon = new TileBasicImage() - { - Source = "Assets/Iconic.png", - AlternateText = "iconic" - } + Source = "Assets/Iconic.png", + AlternateText = "iconic" } } - }); - } + } + }); + } - private static void AssertBindingMediumAdaptive(string expectedBindingXml, TileBindingContentAdaptive content) - { - AssertBindingMedium(expectedBindingXml, new TileBinding() { Content = content }); - } + private static void AssertBindingMediumAdaptive(string expectedBindingXml, TileBindingContentAdaptive content) + { + AssertBindingMedium(expectedBindingXml, new TileBinding() { Content = content }); + } - private static void AssertBindingMedium(string expectedBindingXml, TileBinding binding) + private static void AssertBindingMedium(string expectedBindingXml, TileBinding binding) + { + AssertVisual("" + expectedBindingXml + "", new TileVisual() { - AssertVisual("" + expectedBindingXml + "", new TileVisual() - { - TileMedium = binding - }); - } + TileMedium = binding + }); + } - private static void AssertVisual(string expectedVisualXml, TileVisual visual) + private static void AssertVisual(string expectedVisualXml, TileVisual visual) + { + AssertPayload("" + expectedVisualXml + "", new TileContent() { - AssertPayload("" + expectedVisualXml + "", new TileContent() - { - Visual = visual - }); - } + Visual = visual + }); + } - private static void AssertPayload(string expectedXml, TileContent tile) - { - AssertHelper.AssertTile(expectedXml, tile); - } + private static void AssertPayload(string expectedXml, TileContent tile) + { + AssertHelper.AssertTile(expectedXml, tile); } } #endif diff --git a/components/Notifications/tests/Test_Toast_Xml.cs b/components/Notifications/tests/Test_Toast_Xml.cs index e1144a6ec..0ee620d39 100644 --- a/components/Notifications/tests/Test_Toast_Xml.cs +++ b/components/Notifications/tests/Test_Toast_Xml.cs @@ -9,859 +9,877 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; #nullable disable -namespace NotificationsExperiment.Tests +namespace NotificationsExperiment.Tests; + +[TestClass] +public class Test_Toast_Xml { - [TestClass] - public class Test_Toast_Xml + [TestMethod] + public void Test_Toast_XML_Toast_Defaults() { - [TestMethod] - public void Test_Toast_XML_Toast_Defaults() - { - AssertPayload("", new ToastContent()); - } + AssertPayload("", new ToastContent()); + } - [TestMethod] - public void Test_Toast_XML_Toast_Launch_Value() + [TestMethod] + public void Test_Toast_XML_Toast_Launch_Value() + { + var toast = new ToastContent() { - var toast = new ToastContent() - { - Launch = "tacos" - }; + Launch = "tacos" + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_ActivationType_Foreground() + [TestMethod] + public void Test_Toast_XML_Toast_ActivationType_Foreground() + { + var toast = new ToastContent() { - var toast = new ToastContent() - { - ActivationType = ToastActivationType.Foreground - }; + ActivationType = ToastActivationType.Foreground + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_ActivationType_Background() + [TestMethod] + public void Test_Toast_XML_Toast_ActivationType_Background() + { + var toast = new ToastContent() { - var toast = new ToastContent() - { - ActivationType = ToastActivationType.Background - }; + ActivationType = ToastActivationType.Background + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_ActivationType_Protocol() + [TestMethod] + public void Test_Toast_XML_Toast_ActivationType_Protocol() + { + var toast = new ToastContent() { - var toast = new ToastContent() - { - ActivationType = ToastActivationType.Protocol - }; + ActivationType = ToastActivationType.Protocol + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_Scenario_Default() + [TestMethod] + public void Test_Toast_XML_Toast_Scenario_Default() + { + var toast = new ToastContent() { - var toast = new ToastContent() - { - Scenario = ToastScenario.Default - }; + Scenario = ToastScenario.Default + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_Scenarios() - { - AssertToastScenario(ToastScenario.Reminder, "reminder"); - AssertToastScenario(ToastScenario.Alarm, "alarm"); - AssertToastScenario(ToastScenario.IncomingCall, "incomingCall"); - } + [TestMethod] + public void Test_Toast_XML_Toast_Scenarios() + { + AssertToastScenario(ToastScenario.Reminder, "reminder"); + AssertToastScenario(ToastScenario.Alarm, "alarm"); + AssertToastScenario(ToastScenario.IncomingCall, "incomingCall"); + } - private void AssertToastScenario(ToastScenario scenario, string scenarioText) + private void AssertToastScenario(ToastScenario scenario, string scenarioText) + { + var toast = new ToastContent() { - var toast = new ToastContent() - { - Scenario = scenario - }; + Scenario = scenario + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_Duration_Short() + [TestMethod] + public void Test_Toast_XML_Toast_Duration_Short() + { + var toast = new ToastContent() { - var toast = new ToastContent() - { - Duration = ToastDuration.Short - }; + Duration = ToastDuration.Short + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_Duration_Long() + [TestMethod] + public void Test_Toast_XML_Toast_Duration_Long() + { + var toast = new ToastContent() { - var toast = new ToastContent() - { - Duration = ToastDuration.Long - }; + Duration = ToastDuration.Long + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_HintToastId() + [TestMethod] + public void Test_Toast_XML_Toast_HintToastId() + { + var toast = new ToastContent() { - var toast = new ToastContent() - { - HintToastId = "AppointmentReminder" - }; + HintToastId = "AppointmentReminder" + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_HintPeople_RemoteId() + [TestMethod] + public void Test_Toast_XML_Toast_HintPeople_RemoteId() + { + var toast = new ToastContent() { - var toast = new ToastContent() + HintPeople = new ToastPeople() { - HintPeople = new ToastPeople() - { - RemoteId = "1234" - } - }; + RemoteId = "1234" + } + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_HintPeople_EmailAddress() + [TestMethod] + public void Test_Toast_XML_Toast_HintPeople_EmailAddress() + { + var toast = new ToastContent() { - var toast = new ToastContent() + HintPeople = new ToastPeople() { - HintPeople = new ToastPeople() - { - EmailAddress = "johndoe@mydomain.com" - } - }; + EmailAddress = "johndoe@mydomain.com" + } + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_HintPeople_PhoneNumber() + [TestMethod] + public void Test_Toast_XML_Toast_HintPeople_PhoneNumber() + { + var toast = new ToastContent() { - var toast = new ToastContent() + HintPeople = new ToastPeople() { - HintPeople = new ToastPeople() - { - PhoneNumber = "888-888-8888" - } - }; + PhoneNumber = "888-888-8888" + } + }; - AssertPayload("", toast); - } + AssertPayload("", toast); + } - [TestMethod] - public void Test_Toast_XML_Toast_HintPeople_Precedence() + [TestMethod] + public void Test_Toast_XML_Toast_HintPeople_Precedence() + { + // Email should take precedence over phone number + var toast = new ToastContent() { - // Email should take precedence over phone number - var toast = new ToastContent() - { - HintPeople = new ToastPeople() - { - EmailAddress = "johndoe@mydomain.com", - PhoneNumber = "888-888-8888" - } - }; - - AssertPayload("", toast); - - // RemoteId should take precedence over phone number - toast.HintPeople = new ToastPeople() + HintPeople = new ToastPeople() { - RemoteId = "1234", + EmailAddress = "johndoe@mydomain.com", PhoneNumber = "888-888-8888" - }; + } + }; - AssertPayload("", toast); + AssertPayload("", toast); - // RemoteId should take precedence over all - toast.HintPeople = new ToastPeople() - { - RemoteId = "1234", - PhoneNumber = "888-888-8888", - EmailAddress = "johndoe@mydomain.com" - }; + // RemoteId should take precedence over phone number + toast.HintPeople = new ToastPeople() + { + RemoteId = "1234", + PhoneNumber = "888-888-8888" + }; - AssertPayload("", toast); - } + AssertPayload("", toast); - [TestMethod] - public void Test_Toast_XML_Toast_AdditionalProperties() + // RemoteId should take precedence over all + toast.HintPeople = new ToastPeople() { - AssertPayload("", new ToastContent() - { - AdditionalProperties = - { - { "hint-tacos", "yummy://kind=beans,c=0" } - } - }); + RemoteId = "1234", + PhoneNumber = "888-888-8888", + EmailAddress = "johndoe@mydomain.com" + }; - // Multiple - AssertPayload("", new ToastContent() - { - AdditionalProperties = - { - { "burrito", "true" }, - { "avacado", "definitely" } - } - }); + AssertPayload("", toast); + } - // XML encoding - AssertPayload("", new ToastContent() + [TestMethod] + public void Test_Toast_XML_Toast_AdditionalProperties() + { + AssertPayload("", new ToastContent() + { + AdditionalProperties = { - AdditionalProperties = - { - { "request", "eggs & beans" } - } - }); - } + { "hint-tacos", "yummy://kind=beans,c=0" } + } + }); - [TestMethod] - public void Test_ToastV2_Visual_Defaults() + // Multiple + AssertPayload("", new ToastContent() { - AssertPayload("", new ToastContent()); - } + AdditionalProperties = + { + { "burrito", "true" }, + { "avacado", "definitely" } + } + }); - [TestMethod] - public void Test_ToastV2_Visual_AddImageQuery_False() + // XML encoding + AssertPayload("", new ToastContent() { - var visual = new ToastVisual() + AdditionalProperties = { - AddImageQuery = false - }; + { "request", "eggs & beans" } + } + }); + } - AssertVisualPayloadProperties(@"addImageQuery='false'", visual); - } + [TestMethod] + public void Test_ToastV2_Visual_Defaults() + { + AssertPayload("", new ToastContent()); + } - [TestMethod] - public void Test_ToastV2_Visual_AddImageQuery_True() + [TestMethod] + public void Test_ToastV2_Visual_AddImageQuery_False() + { + var visual = new ToastVisual() { - var visual = new ToastVisual() - { - AddImageQuery = true - }; + AddImageQuery = false + }; - AssertVisualPayloadProperties(@"addImageQuery=""true""", visual); - } + AssertVisualPayloadProperties(@"addImageQuery='false'", visual); + } - [TestMethod] - public void Test_ToastV2_Visual_BaseUri_Value() + [TestMethod] + public void Test_ToastV2_Visual_AddImageQuery_True() + { + var visual = new ToastVisual() { - var visual = new ToastVisual() - { - BaseUri = new Uri("http://msn.com") - }; + AddImageQuery = true + }; - AssertVisualPayloadProperties(@"baseUri=""http://msn.com/""", visual); - } + AssertVisualPayloadProperties(@"addImageQuery=""true""", visual); + } - [TestMethod] - public void Test_ToastV2_Visual_Language_Value() + [TestMethod] + public void Test_ToastV2_Visual_BaseUri_Value() + { + var visual = new ToastVisual() { - var visual = new ToastVisual() - { - Language = "en-US" - }; + BaseUri = new Uri("http://msn.com") + }; - AssertVisualPayloadProperties(@"lang=""en-US""", visual); - } + AssertVisualPayloadProperties(@"baseUri=""http://msn.com/""", visual); + } - [TestMethod] - public void Test_ToastV2_Visual_AdaptiveText_Defaults() + [TestMethod] + public void Test_ToastV2_Visual_Language_Value() + { + var visual = new ToastVisual() { - AssertAdaptiveText(@"", new AdaptiveText()); - } + Language = "en-US" + }; - [TestMethod] - public void Test_ToastV2_Visual_AdaptiveText_All() - { - AssertAdaptiveText(@"Hi, I am a title", new AdaptiveText() - { - Text = "Hi, I am a title", - Language = "en-US", - HintAlign = AdaptiveTextAlign.Right, - HintMaxLines = 3, - HintMinLines = 2, - HintStyle = AdaptiveTextStyle.Header, - HintWrap = true - }); - } + AssertVisualPayloadProperties(@"lang=""en-US""", visual); + } + + [TestMethod] + public void Test_ToastV2_Visual_AdaptiveText_Defaults() + { + AssertAdaptiveText(@"", new AdaptiveText()); + } - [TestMethod] - public void Test_ToastV2_Xml_Attribution() + [TestMethod] + public void Test_ToastV2_Visual_AdaptiveText_All() + { + AssertAdaptiveText(@"Hi, I am a title", new AdaptiveText() + { + Text = "Hi, I am a title", + Language = "en-US", + HintAlign = AdaptiveTextAlign.Right, + HintMaxLines = 3, + HintMinLines = 2, + HintStyle = AdaptiveTextStyle.Header, + HintWrap = true + }); + } + + [TestMethod] + public void Test_ToastV2_Xml_Attribution() + { + var visual = new ToastVisual() { - var visual = new ToastVisual() + BindingGeneric = new ToastBindingGeneric() { - BindingGeneric = new ToastBindingGeneric() + Children = { - Children = + new AdaptiveText() { - new AdaptiveText() - { - Text = "My title" - }, - - new AdaptiveText() - { - Text = "My body 1" - } + Text = "My title" }, - Attribution = new ToastGenericAttributionText() + new AdaptiveText() { - Text = "cnn.com" + Text = "My body 1" } + }, + + Attribution = new ToastGenericAttributionText() + { + Text = "cnn.com" } - }; + } + }; - AssertVisualPayload(@"My titleMy body 1cnn.com", visual); - } + AssertVisualPayload(@"My titleMy body 1cnn.com", visual); + } - [TestMethod] - public void Test_ToastV2_Xml_Attribution_Lang() + [TestMethod] + public void Test_ToastV2_Xml_Attribution_Lang() + { + var visual = new ToastVisual() { - var visual = new ToastVisual() + BindingGeneric = new ToastBindingGeneric() { - BindingGeneric = new ToastBindingGeneric() + Children = { - Children = + new AdaptiveText() { - new AdaptiveText() - { - Text = "My title" - }, - - new AdaptiveText() - { - Text = "My body 1" - } + Text = "My title" }, - Attribution = new ToastGenericAttributionText() + new AdaptiveText() { - Text = "cnn.com", - Language = "en-US" + Text = "My body 1" } + }, + + Attribution = new ToastGenericAttributionText() + { + Text = "cnn.com", + Language = "en-US" } - }; + } + }; - AssertVisualPayload(@"My titleMy body 1cnn.com", visual); - } + AssertVisualPayload(@"My titleMy body 1cnn.com", visual); + } - [TestMethod] - public void Test_ToastV2_BindingGeneric_BaseUri() + [TestMethod] + public void Test_ToastV2_BindingGeneric_BaseUri() + { + AssertBindingGenericProperty("baseUri", "http://msn.com/images/", new ToastBindingGeneric() { - AssertBindingGenericProperty("baseUri", "http://msn.com/images/", new ToastBindingGeneric() - { - BaseUri = new Uri("http://msn.com/images/", UriKind.Absolute) - }); - } + BaseUri = new Uri("http://msn.com/images/", UriKind.Absolute) + }); + } - [TestMethod] - public void Test_ToastV2_BindingGeneric_AddImageQuery() + [TestMethod] + public void Test_ToastV2_BindingGeneric_AddImageQuery() + { + AssertBindingGenericProperty("addImageQuery", "false", new ToastBindingGeneric() { - AssertBindingGenericProperty("addImageQuery", "false", new ToastBindingGeneric() - { - AddImageQuery = false - }); + AddImageQuery = false + }); - AssertBindingGenericProperty("addImageQuery", "true", new ToastBindingGeneric() - { - AddImageQuery = true - }); - } + AssertBindingGenericProperty("addImageQuery", "true", new ToastBindingGeneric() + { + AddImageQuery = true + }); + } - [TestMethod] - public void Test_ToastV2_BindingGeneric_Language() + [TestMethod] + public void Test_ToastV2_BindingGeneric_Language() + { + AssertBindingGenericProperty("lang", "en-US", new ToastBindingGeneric() { - AssertBindingGenericProperty("lang", "en-US", new ToastBindingGeneric() - { - Language = "en-US" - }); - } + Language = "en-US" + }); + } + + [TestMethod] + public void Test_ToastV2_BindingGeneric_DefaultNullValues() + { + AssertBindingGenericPayload("", new ToastBindingGeneric() + { + AddImageQuery = null, + AppLogoOverride = null, + BaseUri = null, + Language = null, + HeroImage = null, + Attribution = null + }); + } - [TestMethod] - public void Test_ToastV2_BindingGeneric_DefaultNullValues() + private static void AssertBindingGenericProperty(string expectedPropertyName, string expectedPropertyValue, ToastBindingGeneric binding) + { + AssertBindingGenericPayload($"", binding); + } + + [TestMethod] + public void Test_ToastV2_BindingShoulderTap_BaseUri() + { + AssertBindingShoulderTapProperty("baseUri", "http://msn.com/images/", new ToastBindingShoulderTap() { - AssertBindingGenericPayload("", new ToastBindingGeneric() - { - AddImageQuery = null, - AppLogoOverride = null, - BaseUri = null, - Language = null, - HeroImage = null, - Attribution = null - }); - } + BaseUri = new Uri("http://msn.com/images/", UriKind.Absolute) + }); + } - private static void AssertBindingGenericProperty(string expectedPropertyName, string expectedPropertyValue, ToastBindingGeneric binding) + [TestMethod] + public void Test_ToastV2_BindingShoulderTap_AddImageQuery() + { + AssertBindingShoulderTapProperty("addImageQuery", "false", new ToastBindingShoulderTap() { - AssertBindingGenericPayload($"", binding); - } + AddImageQuery = false + }); - [TestMethod] - public void Test_ToastV2_BindingShoulderTap_BaseUri() + AssertBindingShoulderTapProperty("addImageQuery", "true", new ToastBindingShoulderTap() { - AssertBindingShoulderTapProperty("baseUri", "http://msn.com/images/", new ToastBindingShoulderTap() - { - BaseUri = new Uri("http://msn.com/images/", UriKind.Absolute) - }); - } + AddImageQuery = true + }); + } - [TestMethod] - public void Test_ToastV2_BindingShoulderTap_AddImageQuery() + [TestMethod] + public void Test_ToastV2_BindingShoulderTap_Language() + { + AssertBindingShoulderTapProperty("lang", "en-US", new ToastBindingShoulderTap() { - AssertBindingShoulderTapProperty("addImageQuery", "false", new ToastBindingShoulderTap() - { - AddImageQuery = false - }); + Language = "en-US" + }); + } - AssertBindingShoulderTapProperty("addImageQuery", "true", new ToastBindingShoulderTap() - { - AddImageQuery = true - }); - } + private static void AssertBindingShoulderTapProperty(string expectedPropertyName, string expectedPropertyValue, ToastBindingShoulderTap binding) + { + AssertBindingShoulderTapPayload($"", binding); + } - [TestMethod] - public void Test_ToastV2_BindingShoulderTap_Language() + [TestMethod] + public void Test_ToastV2_ShoulderTapImage() + { + AssertShoulderTapImagePayload("alt text", new ToastShoulderTapImage() { - AssertBindingShoulderTapProperty("lang", "en-US", new ToastBindingShoulderTap() - { - Language = "en-US" - }); - } + Source = "img.png", + AddImageQuery = true, + AlternateText = "alt text" + }); - private static void AssertBindingShoulderTapProperty(string expectedPropertyName, string expectedPropertyValue, ToastBindingShoulderTap binding) + // Defaults shouldn't have anything assigned + AssertShoulderTapImagePayload("", new ToastShoulderTapImage() { - AssertBindingShoulderTapPayload($"", binding); - } + Source = "img.png" + }); + } - [TestMethod] - public void Test_ToastV2_ShoulderTapImage() + [TestMethod] + public void Test_ToastV2_ShoulderTapImage_SourceRequired() + { + Assert.ThrowsException(() => { - AssertShoulderTapImagePayload("alt text", new ToastShoulderTapImage() - { - Source = "img.png", - AddImageQuery = true, - AlternateText = "alt text" - }); + AssertShoulderTapImagePayload("exception should be thrown", new ToastShoulderTapImage()); + }); - // Defaults shouldn't have anything assigned - AssertShoulderTapImagePayload("", new ToastShoulderTapImage() + Assert.ThrowsException(() => + { + new ToastShoulderTapImage() { - Source = "img.png" - }); - } + Source = null + }; + }); + } - [TestMethod] - public void Test_ToastV2_ShoulderTapImage_SourceRequired() + private static void AssertShoulderTapImagePayload(string expectedImageXml, ToastShoulderTapImage image) + { + AssertBindingShoulderTapPayload($"{expectedImageXml}", new ToastBindingShoulderTap() { - Assert.ThrowsException(() => - { - AssertShoulderTapImagePayload("exception should be thrown", new ToastShoulderTapImage()); - }); + Image = image + }); + } - Assert.ThrowsException(() => - { - new ToastShoulderTapImage() - { - Source = null - }; - }); - } + [TestMethod] + public void Test_ToastV2_SpriteSheet() + { + AssertSpriteSheetProperties("spritesheet-src='sprite.png' spritesheet-height='80' spritesheet-fps='25' spritesheet-startingFrame='15'", new ToastSpriteSheet() + { + Source = "sprite.png", + FrameHeight = 80, + Fps = 25, + StartingFrame = 15 + }); - private static void AssertShoulderTapImagePayload(string expectedImageXml, ToastShoulderTapImage image) + // Defaults shouldn't have anything assigned + AssertSpriteSheetProperties("spritesheet-src='sprite.png'", new ToastSpriteSheet() { - AssertBindingShoulderTapPayload($"{expectedImageXml}", new ToastBindingShoulderTap() - { - Image = image - }); - } + Source = "sprite.png" + }); - [TestMethod] - public void Test_ToastV2_SpriteSheet() + // Can assign invalid values + AssertSpriteSheetProperties("spritesheet-src='sprite.png' spritesheet-height='0' spritesheet-fps='150' spritesheet-startingFrame='15'", new ToastSpriteSheet() { - AssertSpriteSheetProperties("spritesheet-src='sprite.png' spritesheet-height='80' spritesheet-fps='25' spritesheet-startingFrame='15'", new ToastSpriteSheet() - { - Source = "sprite.png", - FrameHeight = 80, - Fps = 25, - StartingFrame = 15 - }); + Source = "sprite.png", + FrameHeight = 0, + Fps = 150, + StartingFrame = 15 + }); + } - // Defaults shouldn't have anything assigned - AssertSpriteSheetProperties("spritesheet-src='sprite.png'", new ToastSpriteSheet() - { - Source = "sprite.png" - }); - - // Can assign invalid values - AssertSpriteSheetProperties("spritesheet-src='sprite.png' spritesheet-height='0' spritesheet-fps='150' spritesheet-startingFrame='15'", new ToastSpriteSheet() - { - Source = "sprite.png", - FrameHeight = 0, - Fps = 150, - StartingFrame = 15 - }); - } - - [TestMethod] - public void Test_ToastV2_SpriteSheet_SourceRequired() + [TestMethod] + public void Test_ToastV2_SpriteSheet_SourceRequired() + { + Assert.ThrowsException(() => { - Assert.ThrowsException(() => - { - AssertSpriteSheetProperties("exception should be thrown", new ToastSpriteSheet()); - }); + AssertSpriteSheetProperties("exception should be thrown", new ToastSpriteSheet()); + }); - Assert.ThrowsException(() => - { - new ToastSpriteSheet() - { - Source = null - }; - }); - } - - private static void AssertSpriteSheetProperties(string expectedProperties, ToastSpriteSheet spriteSheet) + Assert.ThrowsException(() => { - AssertShoulderTapImagePayload($"", new ToastShoulderTapImage() + new ToastSpriteSheet() { - Source = "img.png", - SpriteSheet = spriteSheet - }); - } + Source = null + }; + }); + } - private static void AssertBindingShoulderTapPayload(string expectedBindingXml, ToastBindingShoulderTap binding) + private static void AssertSpriteSheetProperties(string expectedProperties, ToastSpriteSheet spriteSheet) + { + AssertShoulderTapImagePayload($"", new ToastShoulderTapImage() { - AssertVisualPayload("" + expectedBindingXml + "", new ToastVisual() - { - BindingGeneric = new ToastBindingGeneric(), - BindingShoulderTap = binding - }); - } + Source = "img.png", + SpriteSheet = spriteSheet + }); + } - [TestMethod] - public void Test_ToastV2_AppLogo_Crop_None() + private static void AssertBindingShoulderTapPayload(string expectedBindingXml, ToastBindingShoulderTap binding) + { + AssertVisualPayload("" + expectedBindingXml + "", new ToastVisual() { - var appLogo = new ToastGenericAppLogo() - { - HintCrop = ToastGenericAppLogoCrop.None, - Source = "img.png" - }; - - AssertAppLogoPayload(@"", appLogo); - } + BindingGeneric = new ToastBindingGeneric(), + BindingShoulderTap = binding + }); + } - [TestMethod] - public void Test_ToastV2_AppLogo_Crop_Circle() + [TestMethod] + public void Test_ToastV2_AppLogo_Crop_None() + { + var appLogo = new ToastGenericAppLogo() { - var appLogo = new ToastGenericAppLogo() - { - HintCrop = ToastGenericAppLogoCrop.Circle, - Source = "img.png" - }; + HintCrop = ToastGenericAppLogoCrop.None, + Source = "img.png" + }; - AssertAppLogoPayload(@"", appLogo); - } + AssertAppLogoPayload(@"", appLogo); + } - [TestMethod] - public void Test_ToastV2_AppLogo_Source_Defaults() + [TestMethod] + public void Test_ToastV2_AppLogo_Crop_Circle() + { + var appLogo = new ToastGenericAppLogo() { - var appLogo = new ToastGenericAppLogo() - { - Source = "http://xbox.com/Avatar.jpg" - }; + HintCrop = ToastGenericAppLogoCrop.Circle, + Source = "img.png" + }; - AssertAppLogoPayload(@"", appLogo); - } + AssertAppLogoPayload(@"", appLogo); + } - [TestMethod] - public void Test_ToastV2_AppLogo_Source_Alt() + [TestMethod] + public void Test_ToastV2_AppLogo_Source_Defaults() + { + var appLogo = new ToastGenericAppLogo() { - var appLogo = new ToastGenericAppLogo() - { - Source = "http://xbox.com/Avatar.jpg", - AlternateText = "alternate" - }; + Source = "http://xbox.com/Avatar.jpg" + }; - AssertAppLogoPayload(@"", appLogo); - } + AssertAppLogoPayload(@"", appLogo); + } - [TestMethod] - public void Test_ToastV2_AppLogo_Source_AddImageQuery_False() + [TestMethod] + public void Test_ToastV2_AppLogo_Source_Alt() + { + var appLogo = new ToastGenericAppLogo() { - var appLogo = new ToastGenericAppLogo() - { - Source = "http://xbox.com/Avatar.jpg", - AddImageQuery = false - }; + Source = "http://xbox.com/Avatar.jpg", + AlternateText = "alternate" + }; - AssertAppLogoPayload(@"", appLogo); - } + AssertAppLogoPayload(@"", appLogo); + } - [TestMethod] - public void Test_ToastV2_AppLogo_Source_AddImageQuery_True() + [TestMethod] + public void Test_ToastV2_AppLogo_Source_AddImageQuery_False() + { + var appLogo = new ToastGenericAppLogo() { - var appLogo = new ToastGenericAppLogo() - { - Source = "http://xbox.com/Avatar.jpg", - AddImageQuery = true - }; + Source = "http://xbox.com/Avatar.jpg", + AddImageQuery = false + }; - AssertAppLogoPayload(@"", appLogo); - } + AssertAppLogoPayload(@"", appLogo); + } - [TestMethod] - public void Test_ToastV2_Xml_HeroImage_Default() + [TestMethod] + public void Test_ToastV2_AppLogo_Source_AddImageQuery_True() + { + var appLogo = new ToastGenericAppLogo() { - var hero = new ToastGenericHeroImage(); + Source = "http://xbox.com/Avatar.jpg", + AddImageQuery = true + }; - try - { - AssertHeroImagePayload("", hero); - } - catch (NullReferenceException) - { - return; - } + AssertAppLogoPayload(@"", appLogo); + } - Assert.Fail("Exception should have been thrown since Source wasn't provided."); - } + [TestMethod] + public void Test_ToastV2_Xml_HeroImage_Default() + { + var hero = new ToastGenericHeroImage(); - [TestMethod] - public void Test_ToastV2_Xml_HeroImage_WithSource() + try { - var hero = new ToastGenericHeroImage() - { - Source = "http://food.com/peanuts.jpg" - }; - - AssertHeroImagePayload("", hero); + AssertHeroImagePayload("", hero); + } + catch (NullReferenceException) + { + return; } - [TestMethod] - public void Test_ToastV2_Xml_HeroImage_Alt() + Assert.Fail("Exception should have been thrown since Source wasn't provided."); + } + + [TestMethod] + public void Test_ToastV2_Xml_HeroImage_WithSource() + { + var hero = new ToastGenericHeroImage() { - var hero = new ToastGenericHeroImage() - { - Source = "http://food.com/peanuts.jpg", - AlternateText = "peanuts" - }; + Source = "http://food.com/peanuts.jpg" + }; - AssertHeroImagePayload("peanuts", hero); - } + AssertHeroImagePayload("", hero); + } - [TestMethod] - public void Test_ToastV2_Xml_HeroImage_AddImageQuery() + [TestMethod] + public void Test_ToastV2_Xml_HeroImage_Alt() + { + var hero = new ToastGenericHeroImage() { - var hero = new ToastGenericHeroImage() - { - Source = "http://food.com/peanuts.jpg", - AddImageQuery = true - }; + Source = "http://food.com/peanuts.jpg", + AlternateText = "peanuts" + }; - AssertHeroImagePayload("", hero); - } + AssertHeroImagePayload("peanuts", hero); + } - [TestMethod] - public void Test_ToastV2_Xml_HeroImage_AllProperties() + [TestMethod] + public void Test_ToastV2_Xml_HeroImage_AddImageQuery() + { + var hero = new ToastGenericHeroImage() { - var hero = new ToastGenericHeroImage() - { - Source = "http://food.com/peanuts.jpg", - AddImageQuery = true, - AlternateText = "peanuts" - }; + Source = "http://food.com/peanuts.jpg", + AddImageQuery = true + }; - AssertHeroImagePayload("peanuts", hero); - } + AssertHeroImagePayload("", hero); + } - private static ToastContent GenerateFromVisual(ToastVisual visual) + [TestMethod] + public void Test_ToastV2_Xml_HeroImage_AllProperties() + { + var hero = new ToastGenericHeroImage() { - return new ToastContent() - { - Visual = visual - }; - } + Source = "http://food.com/peanuts.jpg", + AddImageQuery = true, + AlternateText = "peanuts" + }; + + AssertHeroImagePayload("peanuts", hero); + } - /// - /// Used for testing properties of visual without needing to specify the Generic binding - /// - private static void AssertVisualPayloadProperties(string expectedVisualProperties, ToastVisual visual) + private static ToastContent GenerateFromVisual(ToastVisual visual) + { + return new ToastContent() { - visual.BindingGeneric = new ToastBindingGeneric(); + Visual = visual + }; + } - AssertVisualPayload("", visual); - } + /// + /// Used for testing properties of visual without needing to specify the Generic binding + /// + private static void AssertVisualPayloadProperties(string expectedVisualProperties, ToastVisual visual) + { + visual.BindingGeneric = new ToastBindingGeneric(); - private static void AssertBindingGenericPayload(string expectedBindingXml, ToastBindingGeneric binding) + AssertVisualPayload("", visual); + } + + private static void AssertBindingGenericPayload(string expectedBindingXml, ToastBindingGeneric binding) + { + AssertVisualPayload("" + expectedBindingXml + "", new ToastVisual() { - AssertVisualPayload("" + expectedBindingXml + "", new ToastVisual() - { - BindingGeneric = binding - }); - } + BindingGeneric = binding + }); + } - private static void AssertAdaptiveText(string expectedAdaptiveTextXml, AdaptiveText text) + private static void AssertAdaptiveText(string expectedAdaptiveTextXml, AdaptiveText text) + { + AssertBindingGenericPayload("" + expectedAdaptiveTextXml + "", new ToastBindingGeneric() { - AssertBindingGenericPayload("" + expectedAdaptiveTextXml + "", new ToastBindingGeneric() + Children = { - Children = - { - text - } - }); - } + text + } + }); + } - private static void AssertAppLogoPayload(string expectedAppLogoXml, ToastGenericAppLogo appLogo) + private static void AssertAppLogoPayload(string expectedAppLogoXml, ToastGenericAppLogo appLogo) + { + AssertVisualPayload(@"" + expectedAppLogoXml + "", new ToastVisual() { - AssertVisualPayload(@"" + expectedAppLogoXml + "", new ToastVisual() + BindingGeneric = new ToastBindingGeneric() { - BindingGeneric = new ToastBindingGeneric() - { - AppLogoOverride = appLogo - } - }); - } + AppLogoOverride = appLogo + } + }); + } - private static void AssertHeroImagePayload(string expectedHeroXml, ToastGenericHeroImage heroImage) + private static void AssertHeroImagePayload(string expectedHeroXml, ToastGenericHeroImage heroImage) + { + AssertVisualPayload(@"" + expectedHeroXml + "", new ToastVisual() { - AssertVisualPayload(@"" + expectedHeroXml + "", new ToastVisual() + BindingGeneric = new ToastBindingGeneric() { - BindingGeneric = new ToastBindingGeneric() - { - HeroImage = heroImage - } - }); - } + HeroImage = heroImage + } + }); + } - [TestMethod] - public void Test_Toast_Xml_Audio_Defaults() - { - var audio = new ToastAudio(); + [TestMethod] + public void Test_Toast_Xml_Audio_Defaults() + { + var audio = new ToastAudio(); - AssertAudioPayload("