Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Ported notifications component from 7.x #579

Merged
merged 6 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading