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

StackedNotificationsBehavior port #170

Merged
merged 16 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
57 changes: 54 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ on:

env:
DOTNET_VERSION: ${{ '7.0.x' }}
ENABLE_DIAGNOSTICS: false
ENABLE_DIAGNOSTICS: true
#COREHOST_TRACE: 1
COREHOST_TRACEFILE: corehosttrace.log
MULTI_TARGET_DIRECTORY: tooling/MultiTarget
Expand Down Expand Up @@ -68,6 +68,22 @@ jobs:

# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: Configure Pagefile
uses: al-cheb/configure-pagefile-action@v1.3
with:
minimum-size: 32GB
maximum-size: 32GB
disk-root: "C:"

- name: Enable User-Mode Dumps collecting
if: ${{ env.ENABLE_DIAGNOSTICS == 'true' || env.COREHOST_TRACE != '' }}
shell: powershell
run: |
New-Item '${{ github.workspace }}\CrashDumps' -Type Directory
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps' -Name 'DumpFolder' -Type ExpandString -Value '${{ github.workspace }}\CrashDumps'
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps' -Name 'DumpCount' -Type DWord -Value '10'
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps' -Name 'DumpType' -Type DWord -Value '2'

- name: Install .NET SDK v${{ env.DOTNET_VERSION }}
uses: actions/setup-dotnet@v3
with:
Expand Down Expand Up @@ -106,8 +122,13 @@ jobs:
run: powershell -version 5.1 -command "./UseUnoWinUI.ps1 3" -ErrorAction Stop
if: ${{ matrix.platform == 'WinUI3' }}

- name: MSBuild (With diagnostics)
if: ${{ env.ENABLE_DIAGNOSTICS == 'true' }}
run: msbuild.exe CommunityToolkit.AllComponents.sln /restore /nowarn:MSB4011 -p:Configuration=Release -m /bl -v:diag

- name: MSBuild
run: msbuild.exe CommunityToolkit.AllComponents.sln /restore /nowarn:MSB4011 -p:Configuration=Release -m -p:UseDotNetNativeToolchain=false
if: ${{ env.ENABLE_DIAGNOSTICS == 'false' }}
run: msbuild.exe CommunityToolkit.AllComponents.sln /restore /nowarn:MSB4011 -p:Configuration=Release -m

# Build All Packages
- name: pack experiments
Expand All @@ -125,7 +146,7 @@ jobs:

# Run tests
- name: Setup VSTest Path
uses: darenm/Setup-VSTest@v1
uses: darenm/Setup-VSTest@v1.2

- name: Install Testspace Module
uses: testspace-com/setup-testspace@v1
Expand All @@ -152,6 +173,36 @@ jobs:
name: build-logs
path: ./**/*.*log

- name: Artifact - ILC Repro
uses: actions/upload-artifact@v3
if: ${{ (env.ENABLE_DIAGNOSTICS == 'true' || env.COREHOST_TRACE != '') && always() }}
with:
name: ilc-repro
path: ./*.zip

# https://github.com/dorny/paths-filter#custom-processing-of-changed-files
- name: Detect If any Dump Files
uses: dorny/paths-filter@v2.11.1
id: filter
with:
list-files: shell
filters: |
dump:
- added: '${{ github.workspace }}/CrashDumps/*.dmp'

- name: Artifact - WER crash dumps
uses: actions/upload-artifact@v3
if: ${{ steps.filter.outputs.dump == 'true' && (env.ENABLE_DIAGNOSTICS == 'true' || env.COREHOST_TRACE != '') && always() }}
with:
name: CrashDumps-${{ matrix.platform }}
path: '${{ github.workspace }}/CrashDumps'

- name: Analyze Dump
if: ${{ steps.filter.outputs.dump == 'true' && (env.ENABLE_DIAGNOSTICS == 'true' || env.COREHOST_TRACE != '') && always() }}
run: |
dotnet tool install --global dotnet-dump
dotnet-dump analyze ${{ steps.filter.outputs.dump_files }} -c "clrstack" -c "pe -lines" -c "exit"

wasm-linux:
runs-on: ubuntu-latest

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion components/Behaviors/samples/Behaviors.Samples.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Assets\ToolkitIcon.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
77 changes: 77 additions & 0 deletions components/Behaviors/samples/StackedNotificationsBehavior.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: StackedNotificationsBehavior
author: vgromfeld
description: A behavior to add stacked notifications to a WinUI InfoBar control.
keywords: StackedNotificationsBehavior, Control, Layout, InfoBar, Behavior
dev_langs:
- csharp
category: Xaml
subcategory: Behaviors
discussion-id: 0
issue-id: 0
icon: Assets/StackedNotificationsBehavior.png
---

The `StackedNotificationsBehavior` allows you to provide notifications within your app using an `InfoBar` control. This is a replacement for the prior `InAppNotification` control in the Toolkit.

With the default settings, a notification will be displayed until it is dismissed by the user. Any subsequent notifications will be displayed
in the order of being sent afterwards one-by-one.

## Example

Clicking on the button multiple times will queue up multiple messages to be displayed one after another.

> [!Sample StackedNotificationsBehaviorCustomSample]

## Notification options

By default, the properties provided on the attached `InfoBar` will be used, like `ContentTemplate` or `IsIconVisible`.

However, there are a number of options available on the `Notification` class to override these. When set, these will override any defaults
or modified properties set on the parent `InfoBar` itself. They will be restored to the previously set value on the `InfoBar` after the message has been displayed.

> [!WARNING]
> Properties set on the `InfoBar` will be modified directly by the behavior with notification overrides, this means any bindings will
> be broken by that change when it is overridden or restored by the notification. Therefore, it is best to only provide constants on the
> parent `InfoBar` itself that will be consistent for all messages and set any dynamic options in the `Notification` options.

When a `Duration` is provided, if the user has their pointer over the message, it will not be dismissed. It will instead reset the time before
being dismissed once the pointer has left the active notification.

## Migrating from InAppNotification

If you previously used the `InAppNotification` component from the Windows Community Toolkit, like so:

```xml
<controls:InAppNotification x:Name="ExampleInAppNotification"/>
```

You can simply replace it with an `InfoBar` control and add the attached behavior:

```xml
<muxc:InfoBar>
<interactivity:Interaction.Behaviors>
<behaviors:StackedNotificationsBehavior x:Name="ExampleInAppNotification" />
</interactivity:Interaction.Behaviors>
</muxc:InfoBar>
```

There are some changes to the `Show` method, however a simple text based one has been provided for backwards compatibility,
otherwise it's best to construct your own `Notification` object for greater flexibility or set common properties on the
parent `InfoBar` itself.

> [!NOTE]
> There is no `StackMode` property to control the behavior of the queue. Providing a stable queue of messages one after another
> provides the best user experience as it reduces the risk when interacting with a notification for a new one to suddenly appear
> and replace the one being displayed.

The `ShowDismissButton` property should be mapped to the `InfoBar.IsClosable` property instead. Similar to any adjustments to position
should be handled by the layout of the `InfoBar` control itself within the XAML layout.

The `Closing` and `Closed` events can be mapped to those on the `InfoBar` as well.

### Complete example

This example shows sending simple text based notifications that will appear only for 2 seconds:

> [!Sample StackedNotificationsBehaviorToolkitSample]
Original file line number Diff line number Diff line change
@@ -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. -->
<Page x:Class="BehaviorsExperiment.Samples.StackedNotificationsBehaviorCustomSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">

<Grid MinHeight="186">
<Button HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="Button_Click"
Content="Send notification" />

<muxc:InfoBar MaxWidth="480"
Margin="24"
HorizontalAlignment="Right"
VerticalAlignment="Bottom">
<interactivity:Interaction.Behaviors>
<behaviors:StackedNotificationsBehavior x:Name="NotificationQueue" />
</interactivity:Interaction.Behaviors>
</muxc:InfoBar>
</Grid>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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.WinUI.Behaviors;

namespace BehaviorsExperiment.Samples;

[ToolkitSample(id: nameof(StackedNotificationsBehaviorCustomSample), "Stacked Notifications", description: $"A sample for showing how to create and use a {nameof(StackedNotificationsBehavior)} custom behavior.")]
public sealed partial class StackedNotificationsBehaviorCustomSample : Page
{
public StackedNotificationsBehaviorCustomSample()
{
this.InitializeComponent();
}

private void Button_Click(object sender, RoutedEventArgs e)
{
var notification = new Notification
{
Title = $"Notification {DateTimeOffset.Now}",
Message = GetRandomText(),
Severity = MUXC.InfoBarSeverity.Informational,
};

NotificationQueue.Show(notification);
}

private static int _current = 0;

private static string GetRandomText() => (_current++ % 4) switch
{
1 => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sollicitudin bibendum enim at tincidunt. Praesent egestas ipsum ligula, nec tincidunt lacus semper non.",
2 => "Pellentesque in risus eget leo rhoncus ultricies nec id ante.",
3 => "Sed quis nisi quis nunc condimentum varius id consectetur metus. Duis mauris sapien, commodo eget erat ac, efficitur iaculis magna. Morbi eu velit nec massa pharetra cursus.",
_ => "Fusce non quam egestas leo finibus interdum eu ac massa. Quisque nec justo leo. Aenean scelerisque placerat ultrices. Sed accumsan lorem at arcu commodo tristique.",
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!-- 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. -->
<Page x:Class="BehaviorsExperiment.Samples.StackedNotificationsBehaviorToolkitSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">

<StackPanel MinHeight="136"
Orientation="Vertical"
Spacing="24">
<Button HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="Button_Click"
Content="Send notification" />

<muxc:InfoBar HorizontalAlignment="Left"
VerticalAlignment="Bottom"
IsIconVisible="False">
<interactivity:Interaction.Behaviors>
<behaviors:StackedNotificationsBehavior x:Name="NotificationQueue" />
</interactivity:Interaction.Behaviors>
</muxc:InfoBar>
</StackPanel>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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.WinUI.Behaviors;

namespace BehaviorsExperiment.Samples;

[ToolkitSample(id: nameof(StackedNotificationsBehaviorToolkitSample), "Stacked Notification Migration", description: $"A sample for showing how to create and use a {nameof(StackedNotificationsBehavior)} custom behavior upgrading from InAppNotification.")]
public sealed partial class StackedNotificationsBehaviorToolkitSample : Page
{
public StackedNotificationsBehaviorToolkitSample()
{
this.InitializeComponent();
}

private void Button_Click(object sender, RoutedEventArgs e)
{
// Show our notification for 2 seconds
NotificationQueue.Show(GetRandomText(), 2000);
}

private static int _current = 0;

private static string GetRandomText() => (_current++ % 4) switch
{
1 => "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sollicitudin bibendum enim at tincidunt. Praesent egestas ipsum ligula, nec tincidunt lacus semper non.",
2 => "Pellentesque in risus eget leo rhoncus ultricies nec id ante.",
3 => "Sed quis nisi quis nunc condimentum varius id consectetur metus. Duis mauris sapien, commodo eget erat ac, efficitur iaculis magna. Morbi eu velit nec massa pharetra cursus.",
_ => "Fusce non quam egestas leo finibus interdum eu ac massa. Quisque nec justo leo. Aenean scelerisque placerat ultrices. Sed accumsan lorem at arcu commodo tristique.",
};
}
Loading
Loading