Skip to content

Commit

Permalink
Merge pull request #579 from CommunityToolkit/components/notifications
Browse files Browse the repository at this point in the history
Ported notifications component from 7.x
  • Loading branch information
Arlodotexe authored Oct 31, 2024
2 parents 49395d9 + dae165d commit eba3625
Show file tree
Hide file tree
Showing 130 changed files with 16,591 additions and 0 deletions.
3 changes: 3 additions & 0 deletions components/Notifications/OpenSolution.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@ECHO OFF

powershell ..\..\tooling\ProjectHeads\GenerateSingleSampleHeads.ps1 -componentPath %CD% %*
41 changes: 41 additions & 0 deletions components/Notifications/src/Adaptive/AdaptiveGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// 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.Collections.Generic;
using CommunityToolkit.Notifications.Adaptive.Elements;

namespace CommunityToolkit.Notifications
{
/// <summary>
/// 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.
/// </summary>
public sealed class AdaptiveGroup : ITileBindingContentAdaptiveChild, IAdaptiveChild, IToastBindingGenericChild
{
/// <summary>
/// Gets the only valid children of groups are <see cref="AdaptiveSubgroup"/>.
/// Each subgroup is displayed as a separate vertical column. Note that you must
/// include at least one subgroup in your group, otherwise an <see cref="InvalidOperationException"/>
/// will be thrown when you try to retrieve the XML for the notification.
/// </summary>
public IList<AdaptiveSubgroup> Children { get; private set; } = new List<AdaptiveSubgroup>();

internal Element_AdaptiveGroup ConvertToElement()
{
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();

foreach (var subgroup in Children)
{
group.Children.Add(subgroup.ConvertToElement());
}

return group;
}
}
}
41 changes: 41 additions & 0 deletions components/Notifications/src/Adaptive/AdaptiveHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// 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;

namespace CommunityToolkit.Notifications.Adaptive
{
internal static class AdaptiveHelper
{
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)
{
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());
}
}
}
92 changes: 92 additions & 0 deletions components/Notifications/src/Adaptive/AdaptiveImage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// 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 CommunityToolkit.Notifications.Adaptive.Elements;

namespace CommunityToolkit.Notifications
{
/// <summary>
/// An inline image.
/// </summary>
public sealed class AdaptiveImage
: IBaseImage,
IToastBindingGenericChild,
ITileBindingContentAdaptiveChild,
IAdaptiveChild,
IAdaptiveSubgroupChild
{
/// <summary>
/// Gets or sets the desired cropping of the image.
/// Supported on Tiles since RTM. Supported on Toast since Anniversary Update.
/// </summary>
public AdaptiveImageCrop HintCrop { get; set; }

/// <summary>
/// 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.
/// </summary>
public bool? HintRemoveMargin { get; set; }

/// <summary>
/// Gets or sets the horizontal alignment of the image.
/// For Toast, this is only supported when inside an <see cref="AdaptiveSubgroup"/>.
/// </summary>
public AdaptiveImageAlign HintAlign { get; set; }

private string _source;

/// <summary>
/// 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.
/// </summary>
public string Source
{
get { return _source; }
set { BaseImageHelper.SetSource(ref _source, value); }
}

/// <summary>
/// Gets or sets a description of the image, for users of assistive technologies.
/// </summary>
public string AlternateText { get; set; }

/// <summary>
/// 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.
/// </summary>
public bool? AddImageQuery { get; set; }

/// <summary>
/// Returns the image's source string.
/// </summary>
/// <returns>The image's source string.</returns>
public override string ToString()
{
if (Source == null)
{
return "Source is null";
}

return Source;
}

internal Element_AdaptiveImage ConvertToElement()
{
Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this);

image.Crop = HintCrop;
image.RemoveMargin = HintRemoveMargin;
image.Align = HintAlign;
image.Placement = AdaptiveImagePlacement.Inline;

return image;
}
}
}
58 changes: 58 additions & 0 deletions components/Notifications/src/Adaptive/AdaptiveImageEnums.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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.

namespace CommunityToolkit.Notifications
{
/// <summary>
/// Specifies the horizontal alignment for an image.
/// </summary>
public enum AdaptiveImageAlign
{
/// <summary>
/// Default value, alignment behavior determined by renderer.
/// </summary>
Default,

/// <summary>
/// Image stretches to fill available width (and potentially available height too, depending on where the image is).
/// </summary>
Stretch,

/// <summary>
/// Align the image to the left, displaying the image at its native resolution.
/// </summary>
Left,

/// <summary>
/// Align the image in the center horizontally, displaying the image at its native resolution.
/// </summary>
Center,

/// <summary>
/// Align the image to the right, displaying the image at its native resolution.
/// </summary>
Right
}

/// <summary>
/// Specify the desired cropping of the image.
/// </summary>
public enum AdaptiveImageCrop
{
/// <summary>
/// Default value, cropping behavior determined by renderer.
/// </summary>
Default,

/// <summary>
/// Image is not cropped.
/// </summary>
None,

/// <summary>
/// Image is cropped to a circle shape.
/// </summary>
Circle
}
}
63 changes: 63 additions & 0 deletions components/Notifications/src/Adaptive/AdaptiveProgressBar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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.

#pragma warning disable SA1121 // UseBuiltInTypeAlias

using System;
using CommunityToolkit.Notifications.Adaptive.Elements;
using BindableProgressBarValue = CommunityToolkit.Notifications.BindableProgressBarValue;
using BindableString = CommunityToolkit.Notifications.BindableString;

namespace CommunityToolkit.Notifications
{
/// <summary>
/// New in Creators Update: A progress bar. Only supported on toasts on Desktop, build 15007 or newer.
/// </summary>
public sealed class AdaptiveProgressBar : IToastBindingGenericChild
{
/// <summary>
/// Gets or sets an optional title string. Supports data binding.
/// </summary>
public BindableString Title { get; set; }

/// <summary>
/// Gets or sets the value of the progress bar. Supports data binding. Defaults to 0.
/// </summary>
public BindableProgressBarValue Value { get; set; } = AdaptiveProgressBarValue.FromValue(0);

/// <summary>
/// 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.
/// </summary>
public BindableString ValueStringOverride { get; set; }

/// <summary>
/// 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..."
/// </summary>
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)
{
throw new NullReferenceException("Status property is required.");
}

return answer;
}
}
}
Loading

0 comments on commit eba3625

Please sign in to comment.