RI release/1.2 preview1 to Main (#2939)

This commit is contained in:
Kyaw Thant 2022-09-07 18:02:14 -07:00 коммит произвёл GitHub
Родитель 0616493ad5
Коммит 423a8f0bdc
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
76 изменённых файлов: 4368 добавлений и 106 удалений

Просмотреть файл

@ -8,4 +8,4 @@
<disabledPackageSources>
<clear />
</disabledPackageSources>
</configuration>
</configuration>

Просмотреть файл

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32616.157
@ -348,6 +348,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeploymentAgent", "dev\Depl
{B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppNotificationBuilder", "dev\AppNotifications\AppNotificationBuilder\AppNotificationBuilder.vcxitems", "{E49329F3-5196-4BBA-B5C4-E11CE7EFB07A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppNotificationBuilderTests", "test\AppNotificationBuilderTests\AppNotificationBuilderTests.vcxproj", "{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Windows.Security.AccessControl.Projection", "dev\Projections\CS\Microsoft.Windows.Security.AccessControl.Projection\Microsoft.Windows.Security.AccessControl.Projection.csproj", "{E6D59245-696F-4D13-ACF6-7ECE6E653367}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "API", "API", "{0D6B1FF3-A075-4194-9FC0-AF7BB89D0519}"
@ -400,6 +404,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test_DeploymentManagerAutoI
ProjectSection(ProjectDependencies) = postProject
{B73AD907-6164-4294-88FB-F3C9C10DA1F1} = {B73AD907-6164-4294-88FB-F3C9C10DA1F1}
EndProjectSection
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Windows.AppNotifications.Builder.Projection", "dev\Projections\CS\Microsoft.Windows.AppNotifications.Builder.Projection\Microsoft.Windows.AppNotifications.Builder.Projection.csproj", "{50BF3E96-3050-4053-B012-BF6993483DA5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "VersionInfo", "VersionInfo", "{2A2D1131-273C-4E17-BCD3-8812170A4B95}"
EndProject
@ -444,6 +449,7 @@ Global
dev\Deployment\Deployment.vcxitems*{db38fb4d-d04f-4c1d-93e0-f8ae259c5fd6}*SharedItemsImports = 9
dev\EnvironmentManager\ChangeTracker\ChangeTracker.vcxitems*{e15c3465-9d45-495d-92ce-b91ef45e8623}*SharedItemsImports = 9
dev\AppLifecycle\AppLifecycle.vcxitems*{e3a522a3-6635-4a42-bded-1af46a15f63c}*SharedItemsImports = 9
dev\AppNotifications\AppNotificationBuilder\AppNotificationBuilder.vcxitems*{e49329f3-5196-4bba-b5c4-e11ce7efb07a}*SharedItemsImports = 9
dev\VersionInfo\VersionInfo.vcxitems*{e3edec7f-a24e-4766-bb1d-6bdfba157c51}*SharedItemsImports = 9
test\inc\inc.vcxitems*{e5659a29-fe68-417b-9bc5-613073dd54df}*SharedItemsImports = 4
test\inc\inc.vcxitems*{e977b1bd-00dc-4085-a105-e0a18e0183d7}*SharedItemsImports = 4
@ -1421,6 +1427,20 @@ Global
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Release|x64.Build.0 = Release|x64
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Release|x86.ActiveCfg = Release|Win32
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Release|x86.Build.0 = Release|Win32
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Debug|Any CPU.ActiveCfg = Debug|Win32
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Debug|ARM64.ActiveCfg = Debug|ARM64
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Debug|ARM64.Build.0 = Debug|ARM64
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Debug|x64.ActiveCfg = Debug|x64
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Debug|x64.Build.0 = Debug|x64
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Debug|x86.ActiveCfg = Debug|Win32
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Debug|x86.Build.0 = Debug|Win32
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Release|Any CPU.ActiveCfg = Release|Win32
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Release|ARM64.ActiveCfg = Release|ARM64
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Release|ARM64.Build.0 = Release|ARM64
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Release|x64.ActiveCfg = Release|x64
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Release|x64.Build.0 = Release|x64
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Release|x86.ActiveCfg = Release|Win32
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A}.Release|x86.Build.0 = Release|Win32
{E6D59245-696F-4D13-ACF6-7ECE6E653367}.Debug|Any CPU.ActiveCfg = Debug|x86
{E6D59245-696F-4D13-ACF6-7ECE6E653367}.Debug|ARM64.ActiveCfg = Debug|arm64
{E6D59245-696F-4D13-ACF6-7ECE6E653367}.Debug|ARM64.Build.0 = Debug|arm64
@ -1555,6 +1575,20 @@ Global
{5A4FBF6D-04A2-4061-B11F-1A0E64129610}.Release|x64.Build.0 = Release|x64
{5A4FBF6D-04A2-4061-B11F-1A0E64129610}.Release|x86.ActiveCfg = Release|x86
{5A4FBF6D-04A2-4061-B11F-1A0E64129610}.Release|x86.Build.0 = Release|x86
{50BF3E96-3050-4053-B012-BF6993483DA5}.Debug|Any CPU.ActiveCfg = Debug|x86
{50BF3E96-3050-4053-B012-BF6993483DA5}.Debug|ARM64.ActiveCfg = Debug|arm64
{50BF3E96-3050-4053-B012-BF6993483DA5}.Debug|ARM64.Build.0 = Debug|arm64
{50BF3E96-3050-4053-B012-BF6993483DA5}.Debug|x64.ActiveCfg = Debug|x64
{50BF3E96-3050-4053-B012-BF6993483DA5}.Debug|x64.Build.0 = Debug|x64
{50BF3E96-3050-4053-B012-BF6993483DA5}.Debug|x86.ActiveCfg = Debug|x86
{50BF3E96-3050-4053-B012-BF6993483DA5}.Debug|x86.Build.0 = Debug|x86
{50BF3E96-3050-4053-B012-BF6993483DA5}.Release|Any CPU.ActiveCfg = Release|x86
{50BF3E96-3050-4053-B012-BF6993483DA5}.Release|ARM64.ActiveCfg = Release|arm64
{50BF3E96-3050-4053-B012-BF6993483DA5}.Release|ARM64.Build.0 = Release|arm64
{50BF3E96-3050-4053-B012-BF6993483DA5}.Release|x64.ActiveCfg = Release|x64
{50BF3E96-3050-4053-B012-BF6993483DA5}.Release|x64.Build.0 = Release|x64
{50BF3E96-3050-4053-B012-BF6993483DA5}.Release|x86.ActiveCfg = Release|x86
{50BF3E96-3050-4053-B012-BF6993483DA5}.Release|x86.Build.0 = Release|x86
{442FB943-1197-48FE-B3B6-8C1BCA1E81E4}.Debug|Any CPU.ActiveCfg = Debug|Win32
{442FB943-1197-48FE-B3B6-8C1BCA1E81E4}.Debug|ARM64.ActiveCfg = Debug|ARM64
{442FB943-1197-48FE-B3B6-8C1BCA1E81E4}.Debug|ARM64.Build.0 = Debug|ARM64
@ -1683,6 +1717,8 @@ Global
{D9139E3C-8D21-4BD9-84E3-30A03A54D610} = {99C514E4-A6B3-4B09-B870-5511EF9D93AC}
{4A74BBED-3B20-44A7-B6FF-3373160DE741} = {99C514E4-A6B3-4B09-B870-5511EF9D93AC}
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF} = {E378857C-D22A-4E5E-A6DA-A59C445CF22E}
{E49329F3-5196-4BBA-B5C4-E11CE7EFB07A} = {1C9A0791-2BAA-420B-84B6-C0721F22A6E8}
{131DE0C4-AA1E-4649-B5BC-7B43508FA93A} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
{E6D59245-696F-4D13-ACF6-7ECE6E653367} = {716C26A0-E6B0-4981-8412-D14A4D410531}
{0D6B1FF3-A075-4194-9FC0-AF7BB89D0519} = {68E63911-6283-4212-BFFE-3F972AF8F835}
{2B653A15-2482-40E5-9509-C531E69D0749} = {68E63911-6283-4212-BFFE-3F972AF8F835}
@ -1697,6 +1733,7 @@ Global
{608A8D5A-A839-45F6-98E6-766FC096104A} = {3A37083C-AA67-461E-BA78-0E0A65FE0C22}
{676BA502-4220-465A-A9ED-ED22CDE4A24B} = {3A37083C-AA67-461E-BA78-0E0A65FE0C22}
{5A4FBF6D-04A2-4061-B11F-1A0E64129610} = {3A37083C-AA67-461E-BA78-0E0A65FE0C22}
{50BF3E96-3050-4053-B012-BF6993483DA5} = {716C26A0-E6B0-4981-8412-D14A4D410531}
{2A2D1131-273C-4E17-BCD3-8812170A4B95} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A}
{E3EDEC7F-A24E-4766-BB1D-6BDFBA157C51} = {2A2D1131-273C-4E17-BCD3-8812170A4B95}
{442FB943-1197-48FE-B3B6-8C1BCA1E81E4} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}

Просмотреть файл

@ -41,6 +41,7 @@ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\Microsoft.WindowsAppRuntime.p
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\Microsoft.WindowsAppRuntime.lib $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppLifecycle.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.Builder.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.PushNotifications.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.DynamicDependency.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.winmd $FullPublishDir\Microsoft.WindowsAppRuntime\
@ -105,6 +106,8 @@ PublishFile $FullBuildOutput\Microsoft.Windows.AppLifecycle.Projection\Microsoft
PublishFile $FullBuildOutput\Microsoft.Windows.AppLifecycle.Projection\Microsoft.Windows.AppLifecycle.Projection.pdb $NugetDir\lib\net5.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.AppNotifications.Projection\Microsoft.Windows.AppNotifications.Projection.dll $NugetDir\lib\net5.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.AppNotifications.Projection\Microsoft.Windows.AppNotifications.Projection.pdb $NugetDir\lib\net5.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.AppNotifications.Builder.Projection\Microsoft.Windows.AppNotifications.Builder.Projection.dll $NugetDir\lib\net5.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.AppNotifications.Builder.Projection\Microsoft.Windows.AppNotifications.Builder.Projection.pdb $NugetDir\lib\net5.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.PushNotifications.Projection\Microsoft.Windows.PushNotifications.Projection.dll $NugetDir\lib\net5.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.PushNotifications.Projection\Microsoft.Windows.PushNotifications.Projection.pdb $NugetDir\lib\net5.0-windows10.0.17763.0
PublishFile $FullBuildOutput\Microsoft.Windows.System.Projection\Microsoft.Windows.System.Projection.dll $NugetDir\lib\net5.0-windows10.0.17763.0
@ -172,6 +175,7 @@ PublishFile $FullBuildOutput\WindowsAppRuntime_MSIXInstallFromPath\WindowsAppRun
# WinMD for UWP apps
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppLifecycle.winmd $NugetDir\lib\uap10.0
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.winmd $NugetDir\lib\uap10.0
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.Builder.winmd $NugetDir\lib\uap10.0
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.PushNotifications.winmd $NugetDir\lib\uap10.0
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.DynamicDependency.winmd $NugetDir\lib\uap10.0
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.winmd $NugetDir\lib\uap10.0

Просмотреть файл

@ -69,6 +69,23 @@
<!-- PowerNotifications -->
<ActivatableClass ActivatableClassId="Microsoft.Windows.System.Power.PowerManager" ThreadingModel="both" />
<!-- AppNotifications -->
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.AppNotificationManager" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.AppNotification" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.AppNotificationProgressData" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.AppNotificationActivatedEventArgs" ThreadingModel="both" />
<!-- AppNotificationBuilder -->
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.Builder.AppNotificationBuilder" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.Builder.AppNotificationTextProperties" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.Builder.AppNotificationButton" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.Builder.AppNotificationProgressBar" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.Builder.AppNotificationComboBox" ThreadingModel="both" />
<!-- AccessControl -->
<ActivatableClass ActivatableClassId="Microsoft.Windows.Security.AccessControl.SecurityDescriptorHelpers" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>

Просмотреть файл

@ -12,7 +12,7 @@ parameters:
- name: "IgnoreFailures"
type: boolean
default: False
- name: "PublishToMaestro"
- name: "PublishPackage"
type: boolean
default: False
- name: "WindowsAppRuntimeInsightsSourceDirectory"
@ -512,18 +512,18 @@ jobs:
itemPattern: |
**/*.nupkg
# this mysterious guid fixes the "NuGetCommand@2 is ambiguous" error :-(
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: 'NuGet push to ProjectReunion.nuget.internal'
inputs:
command: 'push'
packagesToPush: '$(Build.SourcesDirectory)/FullNuget/*.nupkg;!$(Build.SourcesDirectory)/FullNuget/*.symbols.nupkg'
verbosityPush: 'Detailed'
nuGetFeedType: 'internal'
#Note: The project qualifier is always required when using a feed name. Also, do not use organization scoped feeds.
publishVstsFeed: 'ProjectReunion/Project.Reunion.nuget.internal'
- ${{ if or(eq(variables['Build.Reason'], 'Schedule'), eq(parameters.PublishPackage, 'true')) }}:
# this mysterious guid fixes the "NuGetCommand@2 is ambiguous" error :-(
- task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2
displayName: 'NuGet push to ProjectReunion.nuget.internal'
inputs:
command: 'push'
packagesToPush: '$(Build.SourcesDirectory)/FullNuget/*.nupkg;!$(Build.SourcesDirectory)/FullNuget/*.symbols.nupkg'
verbosityPush: 'Detailed'
nuGetFeedType: 'internal'
#Note: The project qualifier is always required when using a feed name. Also, do not use organization scoped feeds.
publishVstsFeed: 'ProjectReunion/Project.Reunion.nuget.internal'
- ${{ if or(eq(variables['Build.Reason'], 'Schedule'), eq(parameters.publishToMaestro, 'true')) }}:
- template: ..\eng\common\AzurePipelinesTemplates\Maestro-PublishBuildToMaestro-Steps.yml
parameters:
AssetNames: 'Microsoft.WindowsAppSDK.Foundation.TransportPackage'

Просмотреть файл

@ -0,0 +1,20 @@
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
jobs:
- job: Merge
pool: $(ProjectReunionBuildPool)
steps:
- checkout: self
persistCredentials: true
- task: CmdLine@2
inputs:
script: |
git checkout develop
git config user.name "reunion-maestro-bot"
git config user.email "reunion-maestro-bot@microsoft.com"
git pull origin main
- task: CmdLine@2
inputs:
script: |
git push

Просмотреть файл

@ -1,5 +1,5 @@
variables:
# Version Control
major: "1"
minor: "1"
minor: "2"
patch: "0"

Просмотреть файл

@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
#include "AppNotificationActivatedEventArgs.h"
#include "Microsoft.Windows.AppNotifications.AppNotificationActivatedEventArgs.g.cpp"
#include "AppNotificationBuilder/AppNotificationBuilderUtility.h"
namespace winrt::Microsoft::Windows::AppNotifications::implementation
{
winrt::Windows::Foundation::Collections::IMap<hstring, hstring> AppNotificationActivatedEventArgs::DecodeArguments(std::wstring arguments)
{
auto result{ winrt::single_threaded_map<winrt::hstring, winrt::hstring>() };
std::vector<std::wstring> pairs{};
size_t pos{ 0 };
// Separate the key/value pairs by ';' as the delimiter
while ((pos = arguments.find(L';')) != std::wstring::npos)
{
pairs.push_back(arguments.substr(0, pos));
arguments.erase(0, pos + 1);
}
// Need to push back final string
pairs.push_back(arguments);
for (auto pair : pairs)
{
// Get the key/value individual values separated by '='
pos = pair.find(L'=');
if (pos == std::wstring::npos)
{
result.Insert(Decode(pair).c_str(), L"");
}
else
{
result.Insert(Decode(pair.substr(0, pos)).c_str(), Decode(pair.substr(pos + 1)).c_str());
}
}
return result;
}
}

Просмотреть файл

@ -1,3 +1,4 @@
// Copyright (c) Microsoft Corporation and Contributors.
// Licensed under the MIT License.
@ -10,12 +11,17 @@ namespace winrt::Microsoft::Windows::AppNotifications::implementation
{
AppNotificationActivatedEventArgs() = default;
AppNotificationActivatedEventArgs(winrt::hstring const& arguments, winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> const& userInput) : m_arguments(arguments), m_userInput(userInput) {};
winrt::hstring Argument() { return m_arguments; };
AppNotificationActivatedEventArgs(winrt::hstring const& argument, winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> const& userInput)
: m_argument(argument), m_userInput(userInput), m_arguments(DecodeArguments(argument.c_str())) {};
winrt::hstring Argument() { return m_argument; };
winrt::Windows::Foundation::Collections::IMap<hstring, hstring> UserInput() { return m_userInput; };
winrt::Windows::Foundation::Collections::IMap<hstring, hstring> Arguments() { return m_arguments; };
private:
winrt::hstring m_arguments;
winrt::Windows::Foundation::Collections::IMap<hstring, hstring> DecodeArguments(std::wstring arguments);
winrt::hstring m_argument;
winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> m_userInput;
winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> m_arguments{ nullptr };
};
}

Просмотреть файл

@ -0,0 +1,396 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
#include "AppNotificationBuilder.h"
#include <winrt/Windows.Globalization.h>
#include <winrt/Windows.Globalization.DateTimeFormatting.h>
#include "Microsoft.Windows.AppNotifications.Builder.AppNotificationBuilder.g.cpp"
#include "AppNotificationBuilderUtility.h"
#include <iomanip>
#include <ctime>
#include <sstream>
#include <IsWindowsVersion.h>
using namespace winrt::Windows::Globalization;
using namespace winrt::Windows::Globalization::DateTimeFormatting;
namespace winrt::Microsoft::Windows::AppNotifications::Builder::implementation
{
void AppNotificationBuilder::ThrowIfMaxInputItemsExceeded()
{
THROW_HR_IF_MSG(E_INVALIDARG, m_textBoxList.size() + m_comboBoxList.size() >= c_maxTextInputElements, "Maximum number of input elements added");
}
bool AppNotificationBuilder::IsUrgentScenarioSupported()
{
return WindowsVersion::IsWindows10_20H1OrGreater();
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::AddArgument(hstring const& key, hstring const& value)
{
THROW_HR_IF_MSG(E_INVALIDARG, key.empty(), "You must provide a key when adding an argument");
m_arguments.Insert(EncodeArgument(key.c_str()), EncodeArgument(value.c_str()));
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetTimeStamp(winrt::Windows::Foundation::DateTime const& value)
{
auto seconds{ winrt::clock::to_time_t(value) };
struct tm buf {};
localtime_s(&buf, &seconds);
std::wstringstream buffer;
buffer << std::put_time(&buf, L"%FT%T%z");
std::wstring timestamp{ buffer.str() };
timestamp.insert(timestamp.size() - c_offsetIndexValue, L":");
m_timeStamp = wil::str_printf<std::wstring>(L" displayTimestamp='%ls'", timestamp.c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetScenario(AppNotificationScenario const& value)
{
m_scenario = value;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetDuration(AppNotificationDuration const& value)
{
m_duration = value;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::AddText(hstring const& text)
{
THROW_HR_IF_MSG(E_INVALIDARG, m_textLines.size() >= c_maxTextElements, "Maximum number of text elements added");
m_textLines.push_back(wil::str_printf<std::wstring>(L"<text>%ls</text>", EncodeXml(text).c_str()).c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::AddText(hstring const& text, AppNotificationTextProperties const& properties)
{
THROW_HR_IF_MSG(E_INVALIDARG, m_textLines.size() >= c_maxTextElements, "Maximum number of text elements added");
std::wstring props{ properties.as<winrt::Windows::Foundation::IStringable>().ToString() };
m_textLines.push_back(wil::str_printf<std::wstring>(L"%ls%ls</text>", props.c_str(), EncodeXml(text).c_str()).c_str());
if (properties.IncomingCallAlignment())
{
m_scenario = AppNotificationScenario::IncomingCall;
}
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetAttributionText(hstring const& text)
{
m_attributionText = wil::str_printf<std::wstring>(L"<text placement='attribution'>%ls</text>", EncodeXml(text).c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetAttributionText(hstring const& text, hstring const& language)
{
THROW_HR_IF_MSG(E_INVALIDARG, language.empty(), "You must provide a language calling SetAttributionText");
m_attributionText = wil::str_printf<std::wstring>(L"<text placement='attribution' lang='%ls'>%ls</text>", language.c_str(), EncodeXml(text).c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetInlineImage(winrt::Windows::Foundation::Uri const& imageUri)
{
m_inlineImage = wil::str_printf<std::wstring>(L"<image src='%ls'/>", imageUri.ToString().c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetInlineImage(winrt::Windows::Foundation::Uri const& imageUri, AppNotificationImageCrop const& imageCrop)
{
if (imageCrop == AppNotificationImageCrop::Circle)
{
m_inlineImage = wil::str_printf<std::wstring>(L"<image src='%ls' hint-crop='circle'/>", imageUri.ToString().c_str());
}
else
{
SetInlineImage(imageUri);
}
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetInlineImage(winrt::Windows::Foundation::Uri const& imageUri, AppNotificationImageCrop const& imageCrop, hstring const& alternateText)
{
THROW_HR_IF_MSG(E_INVALIDARG, alternateText.empty(), "You must provide an alternate text string calling SetInlineImage");
std::wstring hintCrop { imageCrop == AppNotificationImageCrop::Circle ? L" hint-crop='circle'" : L"" };
m_inlineImage = wil::str_printf<std::wstring>(L"<image src='%ls' alt='%ls'%ls/>", imageUri.ToString().c_str(), EncodeXml(alternateText).c_str(), hintCrop.c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetAppLogoOverride(winrt::Windows::Foundation::Uri const& imageUri)
{
m_appLogoOverride = wil::str_printf<std::wstring>(L"<image placement='appLogoOverride' src='%ls'/>", imageUri.ToString().c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetAppLogoOverride(winrt::Windows::Foundation::Uri const& imageUri, AppNotificationImageCrop const& imageCrop)
{
if (imageCrop == AppNotificationImageCrop::Circle)
{
m_appLogoOverride = wil::str_printf<std::wstring>(L"<image placement='appLogoOverride' src='%ls' hint-crop='circle'/>", imageUri.ToString().c_str());
}
else
{
SetAppLogoOverride(imageUri);
}
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetAppLogoOverride(winrt::Windows::Foundation::Uri const& imageUri, AppNotificationImageCrop const& imageCrop, hstring const& alternateText)
{
THROW_HR_IF_MSG(E_INVALIDARG, alternateText.empty(), "You must provide an alternate text string calling SetAppLogoOverride");
std::wstring hintCrop{ imageCrop == AppNotificationImageCrop::Circle ? L" hint-crop='circle'" : L"" };
m_appLogoOverride = wil::str_printf<std::wstring>(L"<image placement='appLogoOverride' src='%ls' alt='%ls'%ls/>", imageUri.ToString().c_str(), EncodeXml(alternateText).c_str(), hintCrop.c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetHeroImage(winrt::Windows::Foundation::Uri const& imageUri)
{
m_heroImage = wil::str_printf<std::wstring>(L"<image placement='hero' src='%ls'/>", imageUri.ToString().c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetHeroImage(winrt::Windows::Foundation::Uri const& imageUri, hstring const& alternateText)
{
THROW_HR_IF_MSG(E_INVALIDARG, alternateText.empty(), "You must provide an alternate text string calling SetHeroImage");
m_heroImage = wil::str_printf<std::wstring>(L"<image placement='hero' src='%ls' alt='%ls'/>", imageUri.ToString().c_str(), EncodeXml(alternateText).c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetAudioUri(winrt::Windows::Foundation::Uri const& audioUri)
{
m_audio = wil::str_printf<std::wstring>(L"<audio src='%ls'/>", audioUri.ToString().c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetAudioUri(winrt::Windows::Foundation::Uri const& audioUri, AppNotificationAudioLooping const& loop)
{
m_audio = wil::str_printf<std::wstring>(L"<audio src='%ls' loop='%ls'/>", audioUri.ToString().c_str(), loop == AppNotificationAudioLooping::Loop ? L"true" : L"false");
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetAudioEvent(AppNotificationSoundEvent const& soundEvent)
{
m_audio = wil::str_printf<std::wstring>(L"<audio src='%ls'/>", GetWinSoundEventString(soundEvent));
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetAudioEvent(AppNotificationSoundEvent const& soundEvent, AppNotificationAudioLooping const& loop)
{
m_audio = wil::str_printf<std::wstring>(L"<audio src='%ls' loop='%ls'/>", GetWinSoundEventString(soundEvent), loop == AppNotificationAudioLooping::Loop ? L"true" : L"false");
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::MuteAudio()
{
m_audio = L"<audio silent='true'/>";
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::AddProgressBar(AppNotificationProgressBar const& value)
{
m_progressBarList.push_back(value);
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::AddTextBox(hstring id)
{
ThrowIfMaxInputItemsExceeded();
THROW_HR_IF_MSG(E_INVALIDARG, id.empty(), "You must provide an id for the TextBox");
m_textBoxList.push_back(wil::str_printf<std::wstring>(L"<input id='%ls' type='text'/>", EncodeXml(id).c_str()));
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::AddTextBox(hstring id, hstring placeHolderText, hstring title)
{
ThrowIfMaxInputItemsExceeded();
THROW_HR_IF_MSG(E_INVALIDARG, id.empty(), "You must provide an id for the TextBox");
m_textBoxList.push_back(wil::str_printf<std::wstring>(L"<input id='%ls' type='text' placeHolderContent='%ls' title='%ls'/>", EncodeXml(id).c_str(), EncodeXml(placeHolderText).c_str(), EncodeXml(title).c_str()));
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::AddButton(AppNotificationButton const& value)
{
THROW_HR_IF_MSG(E_INVALIDARG, m_buttonList.size() >= c_maxButtonElements, "Maximum number of buttons added");
m_buttonList.push_back(value);
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::AddComboBox(AppNotificationComboBox const& value)
{
ThrowIfMaxInputItemsExceeded();
m_comboBoxList.push_back(value);
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetTag(hstring const& value)
{
m_tag = value;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetGroup(hstring const& value)
{
m_group = value;
return *this;
}
std::wstring AppNotificationBuilder::GetDuration()
{
return m_duration == AppNotificationDuration::Default ? L"" : L" duration='long'";
}
std::wstring AppNotificationBuilder::GetScenario()
{
// Add scenario attribute if set
switch (m_scenario)
{
case AppNotificationScenario::Alarm:
return L" scenario='alarm'";
case AppNotificationScenario::Reminder:
return L" scenario='reminder'";
case AppNotificationScenario::IncomingCall:
return L" scenario='incomingCall'";
case AppNotificationScenario::Urgent:
return L" scenario='urgent'";
default:
return {};
}
}
std::wstring AppNotificationBuilder::GetArguments()
{
// Add launch arguments if given arguments
if (m_arguments.Size())
{
std::wstring arguments;
for (auto pair : m_arguments)
{
if (!pair.Value().empty())
{
arguments.append(wil::str_printf<std::wstring>(L"%ls=%ls;", pair.Key().c_str(), pair.Value().c_str()));
}
else
{
arguments.append(wil::str_printf<std::wstring>(L"%ls;", pair.Key().c_str()));
}
}
arguments.pop_back();
return wil::str_printf<std::wstring>(L" launch='%ls'", arguments.c_str());
}
else
{
return {};
}
}
std::wstring AppNotificationBuilder::GetText()
{
std::wstring result{};
for (auto text : m_textLines)
{
result.append(text);
}
return result;
}
std::wstring AppNotificationBuilder::GetImages()
{
return wil::str_printf<std::wstring>(L"%ls%ls%ls", m_inlineImage.c_str(), m_heroImage.c_str(), m_appLogoOverride.c_str());
}
std::wstring AppNotificationBuilder::GetActions()
{
std::wstring result{};
for (auto input : m_textBoxList)
{
result.append(input.c_str());
}
for (auto input : m_comboBoxList)
{
result.append(input.as<winrt::Windows::Foundation::IStringable>().ToString().c_str());
}
for (auto input : m_buttonList)
{
if (input.ButtonStyle() != AppNotificationButtonStyle::Default)
{
m_useButtonStyle = true;
}
result.append(input.as<winrt::Windows::Foundation::IStringable>().ToString().c_str());
}
return (result.empty()) ? result : wil::str_printf<std::wstring>(L"<actions>%ls</actions>", result.c_str());
}
// You must call GetActions first to retrieve this value.
std::wstring AppNotificationBuilder::GetButtonStyle()
{
return m_useButtonStyle ? L" useButtonStyle='true'" : L"";
}
std::wstring AppNotificationBuilder::GetProgressBars()
{
std::wstring result{};
for (auto progressBar : m_progressBarList)
{
result.append(progressBar.as<winrt::Windows::Foundation::IStringable>().ToString());
}
return result;
}
winrt::Microsoft::Windows::AppNotifications::AppNotification AppNotificationBuilder::BuildNotification()
{
// Build the actions string and fill m_useButtonStyle
std::wstring actions{ GetActions() };
auto xmlResult{ wil::str_printf<std::wstring>(L"<toast%ls%ls%ls%ls%ls><visual><binding template='ToastGeneric'>%ls%ls%ls%ls</binding></visual>%ls%ls</toast>",
m_timeStamp.c_str(),
GetDuration().c_str(),
GetScenario().c_str(),
GetArguments().c_str(),
GetButtonStyle().c_str(),
GetText().c_str(),
m_attributionText.c_str(),
GetImages().c_str(),
GetProgressBars().c_str(),
m_audio.c_str(),
actions.c_str()) };
THROW_HR_IF_MSG(E_FAIL, xmlResult.size() > c_maxAppNotificationPayload, "Maximum payload size exceeded");
winrt::Microsoft::Windows::AppNotifications::AppNotification appNotification{ xmlResult };
appNotification.Tag(m_tag);
appNotification.Group(m_group);
return appNotification;
}
}

Просмотреть файл

@ -0,0 +1,103 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
#include "Microsoft.Windows.AppNotifications.Builder.AppNotificationBuilder.g.h"
namespace winrt::Microsoft::Windows::AppNotifications::Builder::implementation
{
struct AppNotificationBuilder : AppNotificationBuilderT<AppNotificationBuilder>
{
AppNotificationBuilder() = default;
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AddArgument(hstring const& key, hstring const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetTimeStamp(winrt::Windows::Foundation::DateTime const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetScenario(AppNotificationScenario const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetDuration(AppNotificationDuration const& value);
// Text component APIs
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AddText(hstring const& text);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AddText(hstring const& text, AppNotificationTextProperties const& properties);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetAttributionText(hstring const& text);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetAttributionText(hstring const& text, hstring const& language);
// Inline image component APIs
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetInlineImage(winrt::Windows::Foundation::Uri const& imageUri);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetInlineImage(winrt::Windows::Foundation::Uri const& imageUri, AppNotificationImageCrop const& imageCrop);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetInlineImage(winrt::Windows::Foundation::Uri const& imageUri, AppNotificationImageCrop const& imageCrop, winrt::hstring const& alternateText);
// AppLogoOverride component APIs
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetAppLogoOverride(winrt::Windows::Foundation::Uri const& imageUri);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetAppLogoOverride(winrt::Windows::Foundation::Uri const& imageUri, AppNotificationImageCrop const& imageCrop);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetAppLogoOverride(winrt::Windows::Foundation::Uri const& imageUri, AppNotificationImageCrop const& imageCrop, winrt::hstring const& alternateText);
// Hero image component APIs
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetHeroImage(winrt::Windows::Foundation::Uri const& imageUri);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetHeroImage(winrt::Windows::Foundation::Uri const& imageUri, winrt::hstring const& alternateText);
// SetAudio
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetAudioUri(winrt::Windows::Foundation::Uri const& audioUri);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetAudioUri(winrt::Windows::Foundation::Uri const& audioUri, AppNotificationAudioLooping const& loop);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetAudioEvent(AppNotificationSoundEvent const& soundEvent);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetAudioEvent(AppNotificationSoundEvent const& soundEvent, AppNotificationAudioLooping const& loop);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder MuteAudio();
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AddTextBox(hstring id);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AddTextBox(hstring id, hstring placeHolderText, hstring title);
// Adds a button to the AppNotificationBuilder
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AddButton(AppNotificationButton const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AddProgressBar(AppNotificationProgressBar const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AddComboBox(AppNotificationComboBox const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetTag(winrt::hstring const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder SetGroup(winrt::hstring const& value);
winrt::Microsoft::Windows::AppNotifications::AppNotification BuildNotification();
static bool IsUrgentScenarioSupported();
private:
void ThrowIfMaxInputItemsExceeded();
std::wstring GetDuration();
std::wstring GetScenario();
std::wstring GetArguments();
std::wstring GetButtonStyle();
std::wstring GetText();
std::wstring GetImages();
std::wstring GetActions();
std::wstring GetProgressBars();
std::wstring m_timeStamp{};
AppNotificationDuration m_duration{ AppNotificationDuration::Default };
AppNotificationScenario m_scenario{ AppNotificationScenario::Default };
bool m_useButtonStyle{};
std::vector<winrt::hstring> m_textLines{};
winrt::hstring m_attributionText{};
winrt::hstring m_inlineImage{};
winrt::hstring m_appLogoOverride{};
winrt::hstring m_heroImage{};
winrt::hstring m_audio{};
winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> m_arguments{ winrt::single_threaded_map<winrt::hstring, winrt::hstring>() };
std::vector<AppNotificationButton> m_buttonList{};
std::vector<AppNotificationProgressBar> m_progressBarList{};
std::vector<std::wstring> m_textBoxList{};
std::vector<AppNotificationComboBox> m_comboBoxList{};
winrt::hstring m_tag{};
winrt::hstring m_group{};
};
}
namespace winrt::Microsoft::Windows::AppNotifications::Builder::factory_implementation
{
struct AppNotificationBuilder : AppNotificationBuilderT<AppNotificationBuilder, implementation::AppNotificationBuilder>
{
};
}

Просмотреть файл

@ -0,0 +1,246 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
import "..\AppNotifications\AppNotifications.idl";
namespace Microsoft.Windows.AppNotifications.Builder
{
[contractversion(1)]
apicontract AppNotificationBuilderContract {}
[contract(AppNotificationBuilderContract, 1)]
runtimeclass AppNotificationTextProperties
{
// Contains the set of <text> attributes
AppNotificationTextProperties();
String Language;
Boolean IncomingCallAlignment;
Int32 MaxLines;
AppNotificationTextProperties SetLanguage(String value);
AppNotificationTextProperties SetIncomingCallAlignment();
AppNotificationTextProperties SetMaxLines(Int32 value);
};
[contract(AppNotificationBuilderContract, 1)]
enum AppNotificationButtonStyle
{
Default,
Success,
Critical,
};
[contract(AppNotificationBuilderContract, 1)]
runtimeclass AppNotificationButton
{
AppNotificationButton();
AppNotificationButton(String content);
String Content;
Windows.Foundation.Collections.IMap<String, String> Arguments;
Windows.Foundation.Uri Icon;
String ToolTip;
Boolean ContextMenuPlacement;
AppNotificationButtonStyle ButtonStyle;
String InputId;
Windows.Foundation.Uri InvokeUri;
String TargetAppId;
AppNotificationButton AddArgument(String key, String value);
// Sets the Icon for the button.
AppNotificationButton SetIcon(Windows.Foundation.Uri value);
// The tooltip for a button, if the button has an empty content string.
AppNotificationButton SetToolTip(String value);
static Boolean IsToolTipSupported();
// Sets the Button as context menu action.
AppNotificationButton SetContextMenuPlacement();
// Sets the ButtonStyle to Success or Critical
AppNotificationButton SetButtonStyle(AppNotificationButtonStyle value);
static Boolean IsButtonStyleSupported();
// Specifies the ID of an existing TextBox next to which the button will be placed.
AppNotificationButton SetInputId(String value);
// Launches the URI passed into the button when activated.
AppNotificationButton SetInvokeUri(Windows.Foundation.Uri protocolUri);
AppNotificationButton SetInvokeUri(Windows.Foundation.Uri protocolUri, String targetAppId);
};
[contract(AppNotificationBuilderContract, 1)]
runtimeclass AppNotificationProgressBar
{
// AppNotificationProgressBar binds to AppNotificationProgressData so the AppNotification will
// receive every update to the status and value. In the WinAppSDK, these binding
// values are static, so developers won't need to define these binding values
// themselves.
AppNotificationProgressBar();
// Setting these properties will remove the data binding with a static value
String Title;
String Status;
Double Value;
String ValueStringOverride;
AppNotificationProgressBar SetTitle(String value);
AppNotificationProgressBar BindTitle();
AppNotificationProgressBar SetStatus(String value);
AppNotificationProgressBar BindStatus();
AppNotificationProgressBar SetValue(Double value);
AppNotificationProgressBar BindValue();
AppNotificationProgressBar SetValueStringOverride(String value);
AppNotificationProgressBar BindValueStringOverride();
};
[contract(AppNotificationBuilderContract, 1)]
runtimeclass AppNotificationComboBox
{
AppNotificationComboBox(String id);
Windows.Foundation.Collections.IMap<String, String> Items;
String Title;
String SelectedItem;
// Add a selection to the AppNotificationComboBox. The id parameter identifies the item the user selected.
AppNotificationComboBox AddItem(String id, String content);
// Adds a title to display on top
AppNotificationComboBox SetTitle(String value);
// Sets the default selection to be displayed by the AppNotificationComboBox
AppNotificationComboBox SetSelectedItem(String id);
};
[contract(AppNotificationBuilderContract, 1)]
enum AppNotificationSoundEvent
{
Default,
IM,
Mail,
Reminder,
SMS,
Alarm,
Alarm2,
Alarm3,
Alarm4,
Alarm5,
Alarm6,
Alarm7,
Alarm8,
Alarm9,
Alarm10,
Call,
Call2,
Call3,
Call4,
Call5,
Call6,
Call7,
Call8,
Call9,
Call10,
};
[contract(AppNotificationBuilderContract, 1)]
enum AppNotificationScenario
{
Default, // The normal AppNotification behavior. The AppNotification appears for a short duration, and then automatically dismisses into Notification Center.
Reminder, // The notification will stay on screen until the user dismisses it or takes action.
Alarm, // Alarms behave like Reminder, but alarms will additionally loop audio with a default alarm sound.
IncomingCall, // Incoming call notifications are displayed pre-expanded in a special call format and stay on the user's screen till dismissed.
Urgent, // Important notifications allow users to have more control over what 1st party and 3rd party apps can send them high-priority AppNotifications (urgent/important) that can break through Focus Assist.
};
[contract(AppNotificationBuilderContract, 1)]
enum AppNotificationAudioLooping
{
None, // Audio will not loop
Loop, // Audio will loop for the duration of the AppNotification
};
[contract(AppNotificationBuilderContract, 1)]
enum AppNotificationDuration
{
Default, // Default value. AppNotification appears for a short while and then goes into Notification Center.
Long, // AppNotification stays on-screen for longer, and then goes into Notification Center.
};
[contract(AppNotificationBuilderContract, 1)]
enum AppNotificationImageCrop
{
Default, // Uses the default renderer to display the image
Circle, // Crops the image as a circle.
};
[contract(AppNotificationBuilderContract, 1)]
runtimeclass AppNotificationBuilder
{
AppNotificationBuilder();
// Adds arguments to the launch attribute to return when AppNotification is clicked.
AppNotificationBuilder AddArgument(String key, String value);
// Sets the timeStamp of the AppNotification to when it was constructed instead of when it was sent.
AppNotificationBuilder SetTimeStamp(Windows.Foundation.DateTime value);
AppNotificationBuilder SetDuration(AppNotificationDuration duration);
// Sets the scenario of the AppNotification.
AppNotificationBuilder SetScenario(AppNotificationScenario value);
static Boolean IsUrgentScenarioSupported();
// Adds text to the AppNotification.
AppNotificationBuilder AddText(String text);
AppNotificationBuilder AddText(String text, AppNotificationTextProperties properties);
AppNotificationBuilder SetAttributionText(String text);
AppNotificationBuilder SetAttributionText(String text, String language);
// Sets the full-width inline-image that appears when you expand the AppNotification
AppNotificationBuilder SetInlineImage(Windows.Foundation.Uri imageUri);
AppNotificationBuilder SetInlineImage(Windows.Foundation.Uri imageUri, AppNotificationImageCrop imageCrop);
AppNotificationBuilder SetInlineImage(Windows.Foundation.Uri imageUri, AppNotificationImageCrop imagecrop, String alternateText);
// Sets the image that replaces the app logo
AppNotificationBuilder SetAppLogoOverride(Windows.Foundation.Uri imageUri);
AppNotificationBuilder SetAppLogoOverride(Windows.Foundation.Uri imageUri, AppNotificationImageCrop imageCrop);
AppNotificationBuilder SetAppLogoOverride(Windows.Foundation.Uri imageUri, AppNotificationImageCrop imageCrop, String alternateText);
// Sets the image that displays within the banner of the AppNotification.
AppNotificationBuilder SetHeroImage(Windows.Foundation.Uri imageUri);
AppNotificationBuilder SetHeroImage(Windows.Foundation.Uri imageUri, String alternateText);
// SetAudio
AppNotificationBuilder SetAudioUri(Windows.Foundation.Uri audioUri);
AppNotificationBuilder SetAudioUri(Windows.Foundation.Uri audioUri, AppNotificationAudioLooping loop);
AppNotificationBuilder SetAudioEvent(AppNotificationSoundEvent appNotificationSoundEvent);
AppNotificationBuilder SetAudioEvent(AppNotificationSoundEvent appNotificationSoundEvent, AppNotificationAudioLooping loop);
AppNotificationBuilder MuteAudio();
AppNotificationBuilder AddTextBox(String id);
AppNotificationBuilder AddTextBox(String id, String placeHolderText, String title);
// Adds a button to the AppNotificationBuilder
AppNotificationBuilder AddButton(AppNotificationButton value);
AppNotificationBuilder AddComboBox(AppNotificationComboBox value);
AppNotificationBuilder AddProgressBar(AppNotificationProgressBar value);
// Constructs a WindowsAppSDK AppNotification object with the XML payload
Microsoft.Windows.AppNotifications.AppNotification BuildNotification();
// AppNotification properties
AppNotificationBuilder SetTag(String value);
AppNotificationBuilder SetGroup(String group);
};
}

Просмотреть файл

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<ItemsProjectGuid>{e49329f3-5196-4bba-b5c4-e11ce7efb07a}</ItemsProjectGuid>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectCapability Include="SourceItemsFromImports" />
</ItemGroup>
<ItemGroup>
<Midl Include="$(MSBuildThisFileDirectory)AppNotificationBuilder.idl" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)AppNotificationBuilder.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)AppNotificationButton.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)AppNotificationProgressBar.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)AppNotificationComboBox.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)AppNotificationTextProperties.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)AppNotificationBuilder.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)AppNotificationBuilderUtility.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)AppNotificationButton.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)AppNotificationProgressBar.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)AppNotificationComboBox.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)AppNotificationTextProperties.h" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,167 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
#include "winrt/Microsoft.Windows.AppNotifications.Builder.h"
#include <algorithm>
#include <regex>
#include <map>
#include <iostream>
constexpr size_t c_maxAppNotificationPayload{ 5120 };
constexpr uint8_t c_maxTextElements{ 3 };
constexpr uint8_t c_maxButtonElements{ 5 };
constexpr size_t c_maxEncodingSize{ 3 };
constexpr uint8_t c_maxTextInputElements{ 5 };
constexpr uint8_t c_maxSelectionElements{ 5 };
constexpr uint8_t c_offsetIndexValue{ 2 };
namespace AppNotificationBuilder
{
using namespace winrt::Microsoft::Windows::AppNotifications::Builder;
}
inline std::unordered_map<wchar_t, std::wstring> GetXmlEscapeEncodings()
{
static std::unordered_map<wchar_t, std::wstring> encodings = { { L'&', L"&amp;"}, { L'\"', L"&quot;"}, {L'<', L"&lt;"}, {L'>', L"&gt;"}, {L'\'', L"&apos;"}};
return encodings;
}
inline std::unordered_map<wchar_t, std::wstring> GetPercentEncodings()
{
static std::unordered_map<wchar_t, std::wstring> encodings = {{ L'%', L"%25"}, {L';', L"%3B"}, {L'=', L"%3D"} };
return encodings;
}
inline std::unordered_map<std::wstring, wchar_t> GetPercentEncodingsReverse()
{
static std::unordered_map<std::wstring, wchar_t> encodings = { { L"%25", L'%' }, {L"%3B", L';' }, { L"%3D", L'=' } };
return encodings;
}
inline PCWSTR GetWinSoundEventString(AppNotificationBuilder::AppNotificationSoundEvent soundEvent)
{
switch (soundEvent)
{
case AppNotificationBuilder::AppNotificationSoundEvent::IM:
return L"ms-winsoundevent:Notification.IM";
case AppNotificationBuilder::AppNotificationSoundEvent::Mail:
return L"ms-winsoundevent:Notification.Mail";
case AppNotificationBuilder::AppNotificationSoundEvent::Reminder:
return L"ms-winsoundevent:Notification.Reminder";
case AppNotificationBuilder::AppNotificationSoundEvent::SMS:
return L"ms-winsoundevent:Notification.SMS";
case AppNotificationBuilder::AppNotificationSoundEvent::Alarm:
return L"ms-winsoundevent:Notification.Looping.Alarm";
case AppNotificationBuilder::AppNotificationSoundEvent::Alarm2:
return L"ms-winsoundevent:Notification.Looping.Alarm2";
case AppNotificationBuilder::AppNotificationSoundEvent::Alarm3:
return L"ms-winsoundevent:Notification.Looping.Alarm3";
case AppNotificationBuilder::AppNotificationSoundEvent::Alarm4:
return L"ms-winsoundevent:Notification.Looping.Alarm4";
case AppNotificationBuilder::AppNotificationSoundEvent::Alarm5:
return L"ms-winsoundevent:Notification.Looping.Alarm5";
case AppNotificationBuilder::AppNotificationSoundEvent::Alarm6:
return L"ms-winsoundevent:Notification.Looping.Alarm6";
case AppNotificationBuilder::AppNotificationSoundEvent::Alarm7:
return L"ms-winsoundevent:Notification.Looping.Alarm7";
case AppNotificationBuilder::AppNotificationSoundEvent::Alarm8:
return L"ms-winsoundevent:Notification.Looping.Alarm8";
case AppNotificationBuilder::AppNotificationSoundEvent::Alarm9:
return L"ms-winsoundevent:Notification.Looping.Alarm9";
case AppNotificationBuilder::AppNotificationSoundEvent::Alarm10:
return L"ms-winsoundevent:Notification.Looping.Alarm10";
case AppNotificationBuilder::AppNotificationSoundEvent::Call:
return L"ms-winsoundevent:Notification.Looping.Call";
case AppNotificationBuilder::AppNotificationSoundEvent::Call2:
return L"ms-winsoundevent:Notification.Looping.Call2";
case AppNotificationBuilder::AppNotificationSoundEvent::Call3:
return L"ms-winsoundevent:Notification.Looping.Call3";
case AppNotificationBuilder::AppNotificationSoundEvent::Call4:
return L"ms-winsoundevent:Notification.Looping.Call4";
case AppNotificationBuilder::AppNotificationSoundEvent::Call5:
return L"ms-winsoundevent:Notification.Looping.Call5";
case AppNotificationBuilder::AppNotificationSoundEvent::Call6:
return L"ms-winsoundevent:Notification.Looping.Call6";
case AppNotificationBuilder::AppNotificationSoundEvent::Call7:
return L"ms-winsoundevent:Notification.Looping.Call7";
case AppNotificationBuilder::AppNotificationSoundEvent::Call8:
return L"ms-winsoundevent:Notification.Looping.Call8";
case AppNotificationBuilder::AppNotificationSoundEvent::Call9:
return L"ms-winsoundevent:Notification.Looping.Call9";
case AppNotificationBuilder::AppNotificationSoundEvent::Call10:
return L"ms-winsoundevent:Notification.Looping.Call10";
default:
return L"ms-winsoundevent:Notification.Default";
}
}
inline std::wstring EncodeArgument(std::wstring const& value)
{
std::wstring encodedValue{};
auto percentEncodings{ GetPercentEncodings() };
auto xmlEncodings{ GetXmlEscapeEncodings() };
for (auto ch : value)
{
if (percentEncodings.find(ch) != percentEncodings.end())
{
encodedValue.append(percentEncodings[ch]);
}
else if (xmlEncodings.find(ch) != xmlEncodings.end())
{
encodedValue.append(xmlEncodings[ch]);
}
else
{
encodedValue.push_back(ch);
}
}
return encodedValue;
}
inline std::wstring EncodeXml(winrt::hstring const& value)
{
std::wstring encodedValue{};
auto xmlEncodings{ GetXmlEscapeEncodings() };
for (auto ch : value)
{
if (xmlEncodings.find(ch) != xmlEncodings.end())
{
encodedValue.append(xmlEncodings[ch]);
}
else
{
encodedValue.push_back(ch);
}
}
return encodedValue;
}
// Decoding process based off the Windows Community Toolkit:
// https://github.com/CommunityToolkit/WindowsCommunityToolkit/blob/rel/7.1.0/Microsoft.Toolkit.Uwp.Notifications/Toasts/ToastArguments.cs#L389inline
inline std::wstring Decode(std::wstring const& value)
{
std::wstring result{};
auto percentEncodings{ GetPercentEncodingsReverse() };
// Need to unescape special characters
for (size_t index = 0; index < value.size();)
{
std::wstring curr{ value.substr(index, c_maxEncodingSize) };
if (percentEncodings.find(curr) != percentEncodings.end())
{
result.push_back(percentEncodings[curr]);
index += c_maxEncodingSize;
}
else
{
result.push_back(value.at(index));
index++;
}
}
return result;
}

Просмотреть файл

@ -0,0 +1,131 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
#include "AppNotificationButton.h"
#include "Microsoft.Windows.AppNotifications.Builder.AppNotificationButton.g.cpp"
#include <IsWindowsVersion.h>
#include "AppNotificationBuilderUtility.h"
namespace winrt::Microsoft::Windows::AppNotifications::Builder::implementation
{
AppNotificationButton::AppNotificationButton(winrt::hstring const& content) : m_content(content) { };
bool AppNotificationButton::IsToolTipSupported()
{
return WindowsVersion::IsWindows10_20H1OrGreater();
}
bool AppNotificationButton::IsButtonStyleSupported()
{
return WindowsVersion::IsWindows10_20H1OrGreater();
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton AppNotificationButton::AddArgument(winrt::hstring const& key, winrt::hstring const& value)
{
THROW_HR_IF_MSG(E_INVALIDARG, key.empty(), "You must provide a key when adding an argument");
THROW_HR_IF_MSG(E_INVALIDARG, m_protocolUri, "You cannot add an argument after calling SetInvokeUri");
m_arguments.Insert(EncodeArgument(key.c_str()), EncodeArgument(value.c_str()));
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton AppNotificationButton::SetIcon(winrt::Windows::Foundation::Uri const& value)
{
m_iconUri = value;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton AppNotificationButton::SetToolTip(winrt::hstring const& value)
{
m_toolTip = EncodeXml(value.c_str()).c_str();
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton AppNotificationButton::SetContextMenuPlacement()
{
m_useContextMenuPlacement = true;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton AppNotificationButton::SetButtonStyle(AppNotificationButtonStyle const& value)
{
m_buttonStyle = value;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton AppNotificationButton::SetInputId(winrt::hstring const& value)
{
m_inputId = EncodeXml(value.c_str()).c_str();
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton AppNotificationButton::SetInvokeUri(winrt::Windows::Foundation::Uri const& protocolUri)
{
THROW_HR_IF_MSG(E_INVALIDARG, m_arguments.Size() > 0u, "You cannot add a protocol activation uri after calling AddArgument");
m_protocolUri = protocolUri;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton AppNotificationButton::SetInvokeUri(winrt::Windows::Foundation::Uri const& protocolUri, winrt::hstring const& targetAppId)
{
THROW_HR_IF_MSG(E_INVALIDARG, m_arguments.Size() > 0u, "You cannot add a protocol activation uri after calling AddArgument");
m_protocolUri = protocolUri;
m_targetApplicationPfn = targetAppId;
return *this;
}
std::wstring AppNotificationButton::GetActivationArguments()
{
if (m_protocolUri)
{
std::wstring protocolTargetPfn{ !m_targetApplicationPfn.empty() ? wil::str_printf<std::wstring>(L" protocolActivationTargetApplicationPfn='%ls'", m_targetApplicationPfn.c_str()) : L"" };
return wil::str_printf<std::wstring>(L" arguments='%ws' activationType='protocol'%ls", m_protocolUri.ToString().c_str(), protocolTargetPfn.c_str());
}
else
{
std::wstring arguments;
for (auto pair : m_arguments)
{
if (!pair.Value().empty())
{
arguments.append(wil::str_printf<std::wstring>(L"%ls=%ls;", pair.Key().c_str(), pair.Value().c_str()));
}
else
{
arguments.append(wil::str_printf<std::wstring>(L"%ls;", pair.Key().c_str()));
}
}
arguments.pop_back();
return wil::str_printf<std::wstring>(L" arguments='%ls'", arguments.c_str());
}
}
std::wstring AppNotificationButton::GetButtonStyle()
{
if (m_buttonStyle == AppNotificationButtonStyle::Default)
{
return L"";
}
std::wstring style{ m_buttonStyle == AppNotificationButtonStyle::Success ? L"Success" : L"Critical" };
return wil::str_printf<std::wstring>(L" hint-buttonStyle='%ls'", style.c_str());
}
winrt::hstring AppNotificationButton::ToString()
{
std::wstring xmlResult{ wil::str_printf<std::wstring>(L"<action content='%ls'%ls%ls%ls%ls%ls%ls/>",
m_content.c_str(),
GetActivationArguments().c_str(),
m_useContextMenuPlacement ? L" placement='contextMenu'" : L"",
m_iconUri ? wil::str_printf<std::wstring>(L" imageUri='%ls'", m_iconUri.ToString().c_str()).c_str() : L"",
!m_inputId.empty() ? wil::str_printf<std::wstring>(L" hint-inputId='%ls'", m_inputId.c_str()).c_str() : L"",
GetButtonStyle().c_str(),
!m_toolTip.empty() ? wil::str_printf<std::wstring>(L" hint-toolTip='%ls'", m_toolTip.c_str()).c_str() : L"") };
return xmlResult.c_str();
}
}

Просмотреть файл

@ -0,0 +1,83 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
#include "Microsoft.Windows.AppNotifications.Builder.AppNotificationButton.g.h"
namespace winrt::Microsoft::Windows::AppNotifications::Builder::implementation
{
struct AppNotificationButton : AppNotificationButtonT<AppNotificationButton, winrt::Windows::Foundation::IStringable>
{
AppNotificationButton() = default;
AppNotificationButton(winrt::hstring const& content);
// Properties
void Content(winrt::hstring const& value) { m_content = value; };
winrt::hstring Content() { return m_content; };
void Arguments(winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> const& value) { m_arguments = value; };
winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> Arguments() { return m_arguments; };
void Icon(winrt::Windows::Foundation::Uri const& value) { m_iconUri = value; };
winrt::Windows::Foundation::Uri Icon() { return m_iconUri; };
void ToolTip(winrt::hstring const& value) { m_toolTip = value; };
winrt::hstring ToolTip() { return m_toolTip; };
void ContextMenuPlacement(bool const& value) { m_useContextMenuPlacement = value; };
bool ContextMenuPlacement() { return m_useContextMenuPlacement; };
void ButtonStyle(AppNotificationButtonStyle const& value) { m_buttonStyle = value; };
AppNotificationButtonStyle ButtonStyle() { return m_buttonStyle; };
void InputId(winrt::hstring const& value) { m_inputId = value; };
winrt::hstring InputId() { return m_inputId; };
void InvokeUri(winrt::Windows::Foundation::Uri const& value) { m_protocolUri = value; };
winrt::Windows::Foundation::Uri InvokeUri() { return m_protocolUri; };
void TargetAppId(winrt::hstring const& value) { m_targetApplicationPfn = value; };
winrt::hstring TargetAppId() { return m_targetApplicationPfn; };
// Fluent setters
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton AddArgument(winrt::hstring const& key, winrt::hstring const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton SetIcon(winrt::Windows::Foundation::Uri const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton SetToolTip(winrt::hstring const& value);
static bool IsToolTipSupported();
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton SetContextMenuPlacement();
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton SetButtonStyle(AppNotificationButtonStyle const& value);
static bool IsButtonStyleSupported();
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton SetInputId(winrt::hstring const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton SetInvokeUri(winrt::Windows::Foundation::Uri const& protocolUri);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationButton SetInvokeUri(winrt::Windows::Foundation::Uri const& protocolUri, winrt::hstring const& targetAppId);
winrt::hstring ToString();
private:
std::wstring GetActivationArguments();
std::wstring GetButtonStyle();
winrt::hstring m_content{};
winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> m_arguments { winrt::single_threaded_map<winrt::hstring, winrt::hstring>() };
winrt::Windows::Foundation::Uri m_iconUri{ nullptr };
winrt::Windows::Foundation::Uri m_protocolUri{ nullptr };
winrt::hstring m_targetApplicationPfn{};
winrt::hstring m_toolTip{};
winrt::hstring m_inputId{};
bool m_useContextMenuPlacement{};
AppNotificationButtonStyle m_buttonStyle { AppNotificationButtonStyle::Default };
};
}
namespace winrt::Microsoft::Windows::AppNotifications::Builder::factory_implementation
{
struct AppNotificationButton : AppNotificationButtonT<AppNotificationButton, implementation::AppNotificationButton>
{
};
}

Просмотреть файл

@ -0,0 +1,65 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
#include "AppNotificationComboBox.h"
#include "Microsoft.Windows.AppNotifications.Builder.AppNotificationComboBox.g.cpp"
#include "AppNotificationBuilderUtility.h"
namespace winrt::Microsoft::Windows::AppNotifications::Builder::implementation
{
AppNotificationComboBox::AppNotificationComboBox(hstring const& id)
{
THROW_HR_IF_MSG(E_INVALIDARG, id.empty(), "You must provide an id for the ComboBox");
m_id = EncodeXml(id).c_str();
};
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationComboBox AppNotificationComboBox::AddItem(winrt::hstring const& id, winrt::hstring const& content)
{
THROW_HR_IF_MSG(E_INVALIDARG, m_items.Size() >= c_maxSelectionElements, "Maximum number of items added");
THROW_HR_IF_MSG(E_INVALIDARG, id.empty(), "You must provide an id for the item");
m_items.Insert(EncodeXml(id).c_str(), EncodeXml(content).c_str());
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationComboBox AppNotificationComboBox::SetTitle(winrt::hstring const& value)
{
m_title = EncodeXml(value).c_str();
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationComboBox AppNotificationComboBox::SetSelectedItem(winrt::hstring const& id)
{
THROW_HR_IF_MSG(E_INVALIDARG, id.empty(), "You must provide an id for the selected item");
m_selectedItem = EncodeXml(id).c_str();
return *this;
}
std::wstring AppNotificationComboBox::GetSelectionItems()
{
std::wstring items{};
for (auto pair : m_items)
{
items.append(wil::str_printf<std::wstring>(L"<selection id='%ls' content='%ls'/>", pair.Key().c_str(), pair.Value().c_str()));
}
return items;
}
winrt::hstring AppNotificationComboBox::ToString()
{
std::wstring xmlResult{ wil::str_printf<std::wstring>(L"<input id='%ls' type='selection'%ls%ls>%ls</input>",
m_id.c_str(),
m_title.empty() ? L"" : wil::str_printf<std::wstring>(L" title='%ls'", m_title.c_str()).c_str(),
m_selectedItem.empty() ? L"" : wil::str_printf<std::wstring>(L" defaultInput='%ls'", m_selectedItem.c_str()).c_str(),
GetSelectionItems().c_str()) };
return xmlResult.c_str();
}
}

Просмотреть файл

@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
#include "Microsoft.Windows.AppNotifications.Builder.AppNotificationComboBox.g.h"
namespace winrt::Microsoft::Windows::AppNotifications::Builder::implementation
{
struct AppNotificationComboBox : AppNotificationComboBoxT<AppNotificationComboBox, winrt::Windows::Foundation::IStringable>
{
AppNotificationComboBox(winrt::hstring const& id);
// Properties
void Items(winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> const& value) { m_items = value; };
winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> Items() { return m_items; };
void Title(winrt::hstring const& value) { m_title = value; };
winrt::hstring Title() { return m_title; };
void SelectedItem(winrt::hstring const& value) { m_selectedItem = value; };
winrt::hstring SelectedItem() { return m_selectedItem; };
// Fluent Setters
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationComboBox AddItem(winrt::hstring const& id, winrt::hstring const& content);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationComboBox SetTitle(winrt::hstring const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationComboBox SetSelectedItem(winrt::hstring const& id);
// IStringable
winrt::hstring ToString();
private:
winrt::hstring m_id{};
winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::hstring> m_items{ winrt::single_threaded_map<winrt::hstring, winrt::hstring>() };
winrt::hstring m_title{};
winrt::hstring m_selectedItem{};
std::wstring GetSelectionItems();
};
}
namespace winrt::Microsoft::Windows::AppNotifications::Builder::factory_implementation
{
struct AppNotificationComboBox : AppNotificationComboBoxT<AppNotificationComboBox, implementation::AppNotificationComboBox>
{
};
}

Просмотреть файл

@ -0,0 +1,113 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
#include "AppNotificationProgressBar.h"
#include "Microsoft.Windows.AppNotifications.Builder.AppNotificationProgressBar.g.cpp"
#include "AppNotificationBuilderUtility.h"
namespace winrt::Microsoft::Windows::AppNotifications::Builder::implementation
{
AppNotificationProgressBar::AppNotificationProgressBar()
:m_titleBindMode{ BindMode::NotSet },
m_statusBindMode{ BindMode::NotSet },
m_valueBindMode{ BindMode::NotSet },
m_valueStringOverrideBindMode{ BindMode::NotSet }
{};
void AppNotificationProgressBar::Title(winrt::hstring const& value)
{
m_title = EncodeXml(value).c_str();
m_titleBindMode = BindMode::Value;
}
void AppNotificationProgressBar::Status(winrt::hstring const& value)
{
m_status = EncodeXml(value).c_str();
m_statusBindMode = BindMode::Value;
}
void AppNotificationProgressBar::Value(double value)
{
THROW_HR_IF_MSG(E_INVALIDARG, value < 0.0 || value > 1.0, "You must provide a value between 0.0 and 1.0");
m_value = value;
m_valueBindMode = BindMode::Value;
}
void AppNotificationProgressBar::ValueStringOverride(winrt::hstring const& value)
{
m_valueStringOverride = EncodeXml(value).c_str();
m_valueStringOverrideBindMode = BindMode::Value;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar AppNotificationProgressBar::SetTitle(winrt::hstring const& value)
{
Title(value);
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar AppNotificationProgressBar::BindTitle()
{
m_titleBindMode = BindMode::Bind;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar AppNotificationProgressBar::SetStatus(winrt::hstring const& value)
{
Status(value);
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar AppNotificationProgressBar::BindStatus()
{
m_statusBindMode = BindMode::Bind;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar AppNotificationProgressBar::SetValue(double value)
{
Value(value);
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar AppNotificationProgressBar::BindValue()
{
m_valueBindMode = BindMode::Bind;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar AppNotificationProgressBar::SetValueStringOverride(winrt::hstring const& value)
{
ValueStringOverride(value);
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar AppNotificationProgressBar::BindValueStringOverride()
{
m_valueStringOverrideBindMode = BindMode::Bind;
return *this;
}
winrt::hstring AppNotificationProgressBar::ToString()
{
auto title{ wil::str_printf<std::wstring>(L" title='%ls'", m_titleBindMode == BindMode::Value ? m_title.c_str() : L"{progressTitle}") };
auto status{ wil::str_printf<std::wstring>(L" status='%ls'", m_statusBindMode == BindMode::Value ? m_status.c_str() : L"{progressStatus}") };
auto value{ wil::str_printf<std::wstring>(L" value='%ls'", m_valueBindMode == BindMode::Value ? wil::str_printf<std::wstring>(L"%g", m_value).c_str() : L"{progressValue}") };
auto valueStringOverride{ wil::str_printf < std::wstring>(L" valueStringOverride='%ls'", m_valueStringOverrideBindMode == BindMode::Value ? m_valueStringOverride.c_str() : L"{progressValueString}") };
return wil::str_printf<std::wstring>(L"<progress%ls%ls%ls%ls/>",
m_titleBindMode == BindMode::NotSet ? L"" : title.c_str(),
status.c_str(),
value.c_str(),
m_valueStringOverrideBindMode == BindMode::NotSet ? L"" : valueStringOverride.c_str()).c_str();
}
}

Просмотреть файл

@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
#include "Microsoft.Windows.AppNotifications.Builder.AppNotificationProgressBar.g.h"
namespace winrt::Microsoft::Windows::AppNotifications::Builder::implementation
{
struct AppNotificationProgressBar : AppNotificationProgressBarT<AppNotificationProgressBar, winrt::Windows::Foundation::IStringable>
{
AppNotificationProgressBar();
// Properties
void Title(winrt::hstring const& value);
winrt::hstring Title() { return m_title; };
void Status(winrt::hstring const& value);
winrt::hstring Status() { return m_status; };
void Value(double value);
double Value() { return m_value; };
void ValueStringOverride(winrt::hstring const& value);
winrt::hstring ValueStringOverride() { return m_valueStringOverride; };
// Fluent setters
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar SetTitle(winrt::hstring const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar BindTitle();
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar SetStatus(winrt::hstring const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar BindStatus();
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar SetValue(double value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar BindValue();
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar SetValueStringOverride(winrt::hstring const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationProgressBar BindValueStringOverride();
// IStringable
winrt::hstring ToString();
private:
enum class BindMode {NotSet, Bind, Value};
BindMode m_titleBindMode;
winrt::hstring m_title;
BindMode m_statusBindMode;
winrt::hstring m_status;
BindMode m_valueBindMode;
double m_value;
BindMode m_valueStringOverrideBindMode;
winrt::hstring m_valueStringOverride;
};
}
namespace winrt::Microsoft::Windows::AppNotifications::Builder::factory_implementation
{
struct AppNotificationProgressBar : AppNotificationProgressBarT<AppNotificationProgressBar, implementation::AppNotificationProgressBar>
{
};
}

Просмотреть файл

@ -0,0 +1,36 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
#include "AppNotificationTextProperties.h"
#include "Microsoft.Windows.AppNotifications.Builder.AppNotificationTextProperties.g.cpp"
namespace winrt::Microsoft::Windows::AppNotifications::Builder::implementation
{
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationTextProperties AppNotificationTextProperties::SetLanguage(winrt::hstring const& value)
{
m_language = value;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationTextProperties AppNotificationTextProperties::SetIncomingCallAlignment()
{
m_useCallScenarioAlign = true;
return *this;
}
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationTextProperties AppNotificationTextProperties::SetMaxLines(int const& value)
{
m_maxLines = value;
return *this;
}
winrt::hstring AppNotificationTextProperties::ToString()
{
std::wstring language{ !m_language.empty() ? wil::str_printf<std::wstring>(L" lang='%ls'", m_language.c_str()) : L""};
std::wstring callScenarioAlign{ m_useCallScenarioAlign ? L" hint-callScenarioCenterAlign='true'" : L""};
std::wstring hintMaxLines{ m_maxLines ? wil::str_printf<std::wstring>(L" hint-maxLines='%d'", m_maxLines) : L"" };
return wil::str_printf<std::wstring>(L"<text%ls%ls%ls>", language.c_str(), hintMaxLines.c_str(), callScenarioAlign.c_str()).c_str();
}
}

Просмотреть файл

@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once
#include "Microsoft.Windows.AppNotifications.Builder.AppNotificationTextProperties.g.h"
namespace winrt::Microsoft::Windows::AppNotifications::Builder::implementation
{
struct AppNotificationTextProperties : AppNotificationTextPropertiesT<AppNotificationTextProperties, winrt::Windows::Foundation::IStringable>
{
AppNotificationTextProperties() = default;
// Properties
void Language(winrt::hstring const& value) { m_language = value; };
winrt::hstring Language() { return m_language; };
void MaxLines(int const& value) { m_maxLines = value; };
int MaxLines() { return m_maxLines; };
void IncomingCallAlignment(bool const& value) { m_useCallScenarioAlign = value; };
bool IncomingCallAlignment() { return m_useCallScenarioAlign; };
// Fluent Setters
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationTextProperties SetLanguage(winrt::hstring const& value);
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationTextProperties SetIncomingCallAlignment();
winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationTextProperties SetMaxLines(int const& value);
// IStringable
winrt::hstring ToString();
private:
int m_maxLines{ 0 };
winrt::hstring m_language{};
bool m_useCallScenarioAlign{};
};
}
namespace winrt::Microsoft::Windows::AppNotifications::Builder::factory_implementation
{
struct AppNotificationTextProperties : AppNotificationTextPropertiesT<AppNotificationTextProperties, implementation::AppNotificationTextProperties>
{
};
}

Просмотреть файл

@ -24,10 +24,11 @@
#include <winrt/Windows.Foundation.Collections.h>
#include <WindowsAppRuntime.SelfContained.h>
#include <ShellLocalization.h>
#include <filesystem>
using namespace std::literals;
constexpr std::wstring_view expectedAppServerArgs = L"----AppNotificationActivated:"sv;
constexpr std::wstring_view c_expectedAppServerArgs = L"----AppNotificationActivated:"sv;
namespace winrt
{
@ -129,50 +130,22 @@ namespace winrt::Microsoft::Windows::AppNotifications::implementation
m_registering = false;
}) };
winrt::guid storedComActivatorGuid{ GUID_NULL };
if (!PushNotificationHelpers::IsPackagedAppScenario())
{
if (!AppModel::Identity::IsPackagedProcess())
{
THROW_IF_FAILED(PushNotifications_RegisterFullTrustApplication(m_appId.c_str(), GUID_NULL));
storedComActivatorGuid = RegisterComActivatorGuidAndAssets();
}
if (!WindowsAppRuntime::SelfContained::IsSelfContained())
{
auto notificationPlatform{ PushNotificationHelpers::GetNotificationPlatform() };
THROW_IF_FAILED(notificationPlatform->AddToastRegistrationMapping(m_processName.c_str(), m_appId.c_str()));
}
}
winrt::guid registeredClsid{ GUID_NULL };
winrt::guid registeredClsid{};
if (AppModel::Identity::IsPackagedProcess())
{
registeredClsid = PushNotificationHelpers::GetComRegistrationFromRegistry(expectedAppServerArgs.data());
registeredClsid = RegisterPackagedApp();
}
else
{
AppNotificationAssets assets{ GetAssets() };
registeredClsid = RegisterUnpackagedApp(assets);
}
// Create event handle before COM Registration otherwise if a notification arrives will lead to race condition
m_waitHandleForArgs.create();
{
auto lock{ m_lock.lock_exclusive() };
THROW_HR_IF_MSG(E_INVALIDARG, m_notificationComActivatorRegistration, "Already Registered for App Notifications!");
// Check if the caller has registered event handlers, if so the REGCLS_MULTIPLEUSE flag will cause COM to ensure that all activators
// are routed inproc, otherwise with REGCLS_SINGLEUSE COM will launch a new process of the Win32 app for each invocation.
auto activationFlag{ m_notificationHandlers ? REGCLS_MULTIPLEUSE : REGCLS_SINGLEUSE };
// Register an INotificationActivationCallback to receive background activations from AppNotification.
// Also, STA threads that call CoRegisterClassObject need to use the REGCLS_AGILE flag so that the object is
// associated with the neutral apartment. This allows other threads to activate the STA registered thread.
THROW_IF_FAILED(::CoRegisterClassObject(
AppModel::Identity::IsPackagedProcess() ? registeredClsid : storedComActivatorGuid,
winrt::make<AppNotificationManagerFactory>().get(),
CLSCTX_LOCAL_SERVER,
activationFlag | REGCLS_AGILE,
&m_notificationComActivatorRegistration));
}
// Register the AppNotificationManager as a COM server for Shell to Activate and Invoke
RegisterComServer(registeredClsid);
}
catch (...)
{
@ -181,6 +154,110 @@ namespace winrt::Microsoft::Windows::AppNotifications::implementation
}
}
void AppNotificationManager::Register(hstring const& displayName, winrt::Windows::Foundation::Uri const& iconUri)
{
if (!IsSupported())
{
return;
}
HRESULT hr{ S_OK };
auto logTelemetry{ wil::scope_exit([&]() {
AppNotificationTelemetry::LogRegister(hr, m_appId);
}) };
try
{
THROW_HR_IF_MSG(E_ILLEGAL_METHOD_CALL, AppModel::Identity::IsPackagedProcess(), "Not applicable for packaged applications");
THROW_HR_IF(E_INVALIDARG, displayName.empty() || (iconUri == nullptr));
AppNotificationAssets assets{ ValidateAssets(displayName, iconUri.RawUri().c_str()) };
{
auto lock{ m_lock.lock_exclusive() };
THROW_HR_IF_MSG(HRESULT_FROM_WIN32(ERROR_OPERATION_IN_PROGRESS), m_registering, "Registration is in progress!");
m_registering = true;
}
auto registeringScopeExit{ wil::scope_exit([&]()
{
auto lock { m_lock.lock_exclusive() };
m_registering = false;
}) };
winrt::guid registeredClsid{ RegisterUnpackagedApp(assets) };
// Create event handle before COM Registration otherwise if a notification arrives will lead to race condition
m_waitHandleForArgs.create();
// Register the AppNotificationManager as a COM server for Shell to Activate and Invoke
RegisterComServer(registeredClsid);
}
catch (...)
{
hr = wil::ResultFromCaughtException();
throw;
}
}
void AppNotificationManager::RegisterComServer(winrt::guid const& registeredClsid)
{
auto lock{ m_lock.lock_exclusive() };
THROW_HR_IF_MSG(E_INVALIDARG, m_notificationComActivatorRegistration, "Already Registered for App Notifications!");
// Check if the caller has registered event handlers, if so the REGCLS_MULTIPLEUSE flag will cause COM to ensure that all activators
// are routed inproc, otherwise with REGCLS_SINGLEUSE COM will launch a new process of the Win32 app for each invocation.
auto activationFlag{ m_notificationHandlers ? REGCLS_MULTIPLEUSE : REGCLS_SINGLEUSE };
// Register an INotificationActivationCallback to receive background activations from AppNotification.
// Also, STA threads that call CoRegisterClassObject need to use the REGCLS_AGILE flag so that the object is
// associated with the neutral apartment. This allows other threads to activate the STA registered thread.
THROW_IF_FAILED(::CoRegisterClassObject(
registeredClsid,
winrt::make<AppNotificationManagerFactory>().get(),
CLSCTX_LOCAL_SERVER,
activationFlag | REGCLS_AGILE,
&m_notificationComActivatorRegistration));
}
void AppNotificationManager::RegisterAppNotificationSinkWithLongRunningPlatform()
{
auto notificationPlatform{ PushNotificationHelpers::GetNotificationPlatform() };
THROW_IF_FAILED(notificationPlatform->AddToastRegistrationMapping(m_processName.c_str(), m_appId.c_str()));
}
winrt::guid AppNotificationManager::RegisterPackagedApp()
{
winrt::guid registeredClsid{ PushNotificationHelpers::GetComRegistrationFromRegistry(c_expectedAppServerArgs.data()) };
if (!PushNotificationHelpers::IsPackagedAppScenario() && !WindowsAppRuntime::SelfContained::IsSelfContained())
{
RegisterAppNotificationSinkWithLongRunningPlatform();
}
return registeredClsid;
}
winrt::guid AppNotificationManager::RegisterUnpackagedApp(AppNotificationAssets const& assets)
{
THROW_IF_FAILED(PushNotifications_RegisterFullTrustApplication(m_appId.c_str(), GUID_NULL));
std::wstring notificationAppId{ RetrieveNotificationAppId() };
std::wstring comActivatorGuidString{ GetOrCreateComActivatorGuid() };
RegisterAssets(notificationAppId, comActivatorGuidString, assets);
if (!WindowsAppRuntime::SelfContained::IsSelfContained())
{
RegisterAppNotificationSinkWithLongRunningPlatform();
}
// Remove braces around the guid string
return winrt::guid(comActivatorGuidString.substr(1, comActivatorGuidString.size() - 2));
}
// This assumes that the caller has taken an exclusive lock
void AppNotificationManager::UnregisterHelper()
{
@ -337,11 +414,15 @@ namespace winrt::Microsoft::Windows::AppNotifications::implementation
winrt::guid registeredClsid{ GUID_NULL };
if (AppModel::Identity::IsPackagedProcess())
{
registeredClsid = PushNotificationHelpers::GetComRegistrationFromRegistry(expectedAppServerArgs.data());
registeredClsid = PushNotificationHelpers::GetComRegistrationFromRegistry(c_expectedAppServerArgs.data());
}
else
{
registeredClsid = RegisterComActivatorGuidAndAssets();
std::wstring registeredClsidString;
THROW_IF_FAILED(GetActivatorGuid(registeredClsidString));
// Remove braces around the guid string
registeredClsid = winrt::guid(registeredClsidString.substr(1, registeredClsidString.size() - 2));
}
auto notificationCallback{ winrt::create_instance<INotificationActivationCallback>(registeredClsid, CLSCTX_ALL) };

Просмотреть файл

@ -6,6 +6,7 @@
#include "NotificationActivationCallback.h"
#include "AppNotificationUtility.h"
#include "externs.h"
#include "ShellLocalization.h"
constexpr PCWSTR c_appNotificationContractId = L"Windows.Toast";
@ -22,6 +23,7 @@ namespace winrt::Microsoft::Windows::AppNotifications::implementation
static winrt::Microsoft::Windows::AppNotifications::AppNotificationManager Default();
static winrt::Windows::Foundation::IInspectable AppNotificationDeserialize(winrt::Windows::Foundation::Uri const& uri);
void Register();
void Register(hstring const& displayName, winrt::Windows::Foundation::Uri const& iconUri);
void Unregister();
void UnregisterAll();
static bool IsSupported();
@ -49,6 +51,11 @@ namespace winrt::Microsoft::Windows::AppNotifications::implementation
winrt::Windows::Foundation::IInspectable Deserialize(winrt::Windows::Foundation::Uri const& uri);
private:
winrt::guid RegisterPackagedApp();
winrt::guid RegisterUnpackagedApp(::Microsoft::Windows::AppNotifications::ShellLocalization::AppNotificationAssets const& assets);
void RegisterAppNotificationSinkWithLongRunningPlatform();
void RegisterComServer(winrt::guid const& registeredClsid);
void UnregisterHelper();
wil::unique_com_class_object_cookie m_notificationComActivatorRegistration;

Просмотреть файл

@ -38,6 +38,8 @@ namespace ToastABI
using namespace ::ABI::Microsoft::Internal::ToastNotifications;
}
using namespace Microsoft::Windows::AppNotifications::ShellLocalization;
std::wstring Microsoft::Windows::AppNotifications::Helpers::RetrieveUnpackagedNotificationAppId()
{
wil::unique_cotaskmem_string appId;
@ -241,7 +243,7 @@ std::wstring Microsoft::Windows::AppNotifications::Helpers::GetDisplayNameBasedO
return displayName;
}
winrt::guid Microsoft::Windows::AppNotifications::Helpers::RegisterComActivatorGuidAndAssets()
std::wstring Microsoft::Windows::AppNotifications::Helpers::GetOrCreateComActivatorGuid()
{
std::wstring registeredGuid;
auto hr = GetActivatorGuid(registeredGuid);
@ -264,14 +266,36 @@ winrt::guid Microsoft::Windows::AppNotifications::Helpers::RegisterComActivatorG
THROW_IF_FAILED(hr);
}
std::wstring notificationAppId{ Microsoft::Windows::AppNotifications::Helpers::RetrieveNotificationAppId() };
RegisterAssets(notificationAppId, registeredGuid);
// Remove braces around the guid string
return winrt::guid(registeredGuid.substr(1, registeredGuid.size() - 2));
return registeredGuid;
}
void Microsoft::Windows::AppNotifications::Helpers::RegisterAssets(std::wstring const& appId, std::wstring const& clsid)
// Try the following techniques to retrieve display name and icon:
// 1. Based on the best app shortcut, using the FrameworkUdk.
// 2. From the current process.
// 3. Set a default DisplayName, but leave empty the icon file path so Shell can set a default icon.
AppNotificationAssets Microsoft::Windows::AppNotifications::Helpers::GetAssets()
{
AppNotificationAssets assets{};
if (FAILED(RetrieveAssetsFromShortcut(assets)) &&
FAILED(RetrieveAssetsFromProcess(assets)))
{
assets.displayName = GetDisplayNameBasedOnProcessName();
}
return assets;
}
AppNotificationAssets Microsoft::Windows::AppNotifications::Helpers::ValidateAssets(winrt::hstring const& displayName, std::filesystem::path const& iconFilePath)
{
winrt::check_bool(std::filesystem::exists(iconFilePath));
THROW_HR_IF_MSG(E_INVALIDARG, !IsIconFileExtensionSupported(iconFilePath), "Icon format not supported");
return AppNotificationAssets{ displayName.c_str(), iconFilePath.wstring() };
}
void Microsoft::Windows::AppNotifications::Helpers::RegisterAssets(std::wstring const& appId, std::wstring const& clsid, AppNotificationAssets const& assets)
{
wil::unique_hkey hKey;
// subKey: \Software\Classes\AppUserModelId\{AppGUID}
@ -288,18 +312,6 @@ void Microsoft::Windows::AppNotifications::Helpers::RegisterAssets(std::wstring
&hKey,
nullptr /* lpdwDisposition */));
// Try the following techniques to retrieve display name and icon:
// 1. Based on the best app shortcut, using the FrameworkUdk.
// 2. From the current process.
// 3. Set a default DisplayName, but leave empty the icon file path so Shell can set a default icon.
Microsoft::Windows::AppNotifications::ShellLocalization::AppNotificationAssets assets{};
if (FAILED(Microsoft::Windows::AppNotifications::ShellLocalization::RetrieveAssetsFromShortcut(assets)) &&
FAILED(Microsoft::Windows::AppNotifications::ShellLocalization::RetrieveAssetsFromProcess(assets)))
{
assets.displayName = GetDisplayNameBasedOnProcessName();
}
RegisterValue(hKey, L"DisplayName", reinterpret_cast<const BYTE*>(assets.displayName.c_str()), REG_EXPAND_SZ, assets.displayName.size() * sizeof(wchar_t));
// If no icon is specified in the Registry, the OS will render a default icon for App Notifications.

Просмотреть файл

@ -8,6 +8,7 @@
#include <wil/resource.h>
#include <AppNotificationActivatedEventArgs.h>
#include <FrameworkUdk/toastnotificationsrt.h>
#include <ShellLocalization.h>
namespace Microsoft::Windows::AppNotifications::Helpers
{
@ -53,13 +54,17 @@ namespace Microsoft::Windows::AppNotifications::Helpers
HRESULT GetActivatorGuid(std::wstring& activatorGuid) noexcept;
winrt::guid RegisterComActivatorGuidAndAssets();
std::wstring GetOrCreateComActivatorGuid();
void RegisterAssets(std::wstring const& appId, std::wstring const& clsid);
void RegisterAssets(std::wstring const& appId, std::wstring const& clsid, Microsoft::Windows::AppNotifications::ShellLocalization::AppNotificationAssets const& assets);
wil::unique_cotaskmem_string ConvertUtf8StringToWideString(unsigned long length, const BYTE* utf8String);
winrt::Microsoft::Windows::AppNotifications::AppNotification ToastNotificationFromToastProperties(ABI::Microsoft::Internal::ToastNotifications::INotificationProperties* properties);
std::wstring GetDisplayNameBasedOnProcessName();
Microsoft::Windows::AppNotifications::ShellLocalization::AppNotificationAssets GetAssets();
Microsoft::Windows::AppNotifications::ShellLocalization::AppNotificationAssets ValidateAssets(winrt::hstring const& displayName, std::filesystem::path const& iconFilePath);
}

Просмотреть файл

@ -4,7 +4,7 @@ import "..\AppLifecycle\AppLifecycle.idl";
namespace Microsoft.Windows.AppNotifications
{
[contractversion(2)]
[contractversion(3)]
apicontract AppNotificationsContract {}
// Event args for the Notification Activation
@ -16,6 +16,10 @@ namespace Microsoft.Windows.AppNotifications
// The data from the input elements of a Notification like a TextBox
Windows.Foundation.Collections.IMap<String, String> UserInput{ get; };
// Arguments from the invoked button built from AppNotificationBuilder
[contract(AppNotificationsContract, 3)]
Windows.Foundation.Collections.IMap<String, String> Arguments{ get; };
}
// Notification Progress Data
@ -121,6 +125,10 @@ namespace Microsoft.Windows.AppNotifications
// For Unpackaged apps, the caller process will be registered as the COM server. And assets like displayname and icon will be gleaned from Shell and registered as well.
void Register();
// Unpackaged Apps can call this API to register custom displayname and icon for AppNotifications and register themselves as a COM server.
[contract(AppNotificationsContract, 2)]
void Register(String displayName, Windows.Foundation.Uri iconUri);
// Unregisters the COM Service so that a subsequent activation will launch a new process
void Unregister();

Просмотреть файл

@ -26,6 +26,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)ShellLocalization.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)AppNotificationActivatedEventArgs.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)AppNotificationManager.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)AppNotification.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)AppNotificationProgressData.cpp" />

Просмотреть файл

@ -167,7 +167,8 @@ void WriteHIconToPngFile(wil::unique_hicon const& hIcon, _In_ PCWSTR pszFileName
THROW_IF_FAILED(spStreamOut->Commit(STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE));
}
bool IsIconFileExtensionSupported(std::filesystem::path const& iconFilePath)
bool Microsoft::Windows::AppNotifications::ShellLocalization::IsIconFileExtensionSupported(std::filesystem::path const& iconFilePath)
{
static PCWSTR c_supportedExtensions[]{ L".bmp", L".ico", L".jpg", L".png" };
@ -258,10 +259,7 @@ HRESULT Microsoft::Windows::AppNotifications::ShellLocalization::DeleteIconFromC
std::path iconFilePath{ RetrieveLocalFolderPath() / (notificationAppId + c_pngExtension) };
// If DeleteFile returned FALSE, then deletion failed and we should return the corresponding error code.
if (DeleteFile(iconFilePath.c_str()) == FALSE)
{
THROW_HR(HRESULT_FROM_WIN32(GetLastError()));
}
RETURN_IF_WIN32_BOOL_FALSE(DeleteFileW(iconFilePath.c_str()));
return S_OK;
}

Просмотреть файл

@ -22,4 +22,6 @@ namespace Microsoft::Windows::AppNotifications::ShellLocalization
HRESULT RetrieveAssetsFromShortcut(_Out_ Microsoft::Windows::AppNotifications::ShellLocalization::AppNotificationAssets& assets) noexcept;
HRESULT DeleteIconFromCache() noexcept;
bool IsIconFileExtensionSupported(std::filesystem::path const& iconFilePath);
}

Просмотреть файл

@ -165,7 +165,7 @@
<Import Project="..\..\packages\Microsoft.SourceLink.Common.1.1.0-beta-21055-01\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.1.0-beta-21055-01\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.1.0-beta-20204-02\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.1.0-beta-20204-02\build\Microsoft.Build.Tasks.Git.targets')" />
<Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.1.0-beta-20204-02\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.1.0-beta-20204-02\build\Microsoft.SourceLink.GitHub.targets')" />
<Import Project="..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets" Condition="Exists('..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets')" />
<Import Project="..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets" Condition="Exists('..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
@ -179,6 +179,6 @@
<Error Condition="!Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.1.0-beta-20204-02\build\Microsoft.Build.Tasks.Git.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Build.Tasks.Git.1.1.0-beta-20204-02\build\Microsoft.Build.Tasks.Git.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.1.0-beta-20204-02\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.1.0-beta-20204-02\build\Microsoft.SourceLink.GitHub.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.1.0-beta-20204-02\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.1.0-beta-20204-02\build\Microsoft.SourceLink.GitHub.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets'))" />
</Target>
</Project>

Просмотреть файл

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Build.Tasks.Git" version="1.1.0-beta-20204-02" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.FrameworkUdk" version="1.1.2-CI-25087.1001.220410-1342.0" targetFramework="native" />
<package id="Microsoft.FrameworkUdk" version="1.0.5-CI-25099.1001.220418-1000.0" targetFramework="native" />
<package id="Microsoft.SourceLink.Common" version="1.1.0-beta-21055-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.1.0-beta-20204-02" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.220531.1" targetFramework="native" />

Просмотреть файл

@ -0,0 +1,52 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0-windows10.0.17763.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<Platforms>x64;x86;arm64</Platforms>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.Common" Version="1.1.0-beta-21055-01">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.0-beta-20204-02">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="$(MicrosoftWindowsCsWinRTPackageVersion)" />
</ItemGroup>
<PropertyGroup>
<CSWinRTIncludes>Microsoft.Windows.AppNotifications.Builder</CSWinRTIncludes>
<CSWinRTWindowsMetadata>10.0.17763.0</CSWinRTWindowsMetadata>
<WindowsSdkPackageVersion>10.0.17763.$(CsWinRTDependencyWindowsSdkVersionSuffixPackageVersion)</WindowsSdkPackageVersion>
</PropertyGroup>
<!-- Configure the release build binary to be as required by internal API scanning tools. -->
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<CsWinRTInputs Include="$(OutDir)/**/*.winmd" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Windows.AppNotifications.Projection\Microsoft.Windows.AppNotifications.Projection.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Windows.AppNotifications">
<HintPath>$(OutDir)..\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
</Reference>
<Reference Include="Microsoft.Windows.AppNotifications.Builder">
<HintPath>$(OutDir)..\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windows.AppNotifications.Builder.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
</Reference>
</ItemGroup>
</Project>

Просмотреть файл

@ -197,7 +197,7 @@
<Import Project="..\..\..\packages\Microsoft.SourceLink.GitHub.1.1.0-beta-20204-02\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\..\packages\Microsoft.SourceLink.GitHub.1.1.0-beta-20204-02\build\Microsoft.SourceLink.GitHub.targets')" />
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets" Condition="Exists('..\..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets')" />
<Import Project="..\..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets" Condition="Exists('..\..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
@ -212,6 +212,6 @@
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets'))" />
</Target>
</Project>

Просмотреть файл

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Build.Tasks.Git" version="1.1.0-beta-20204-02" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.FrameworkUdk" version="1.1.2-CI-25087.1001.220410-1342.0" targetFramework="native" />
<package id="Microsoft.FrameworkUdk" version="1.0.5-CI-25099.1001.220418-1000.0" targetFramework="native" />
<package id="Microsoft.SourceLink.Common" version="1.1.0-beta-21055-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.1.0-beta-20204-02" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.220531.1" targetFramework="native" />

Просмотреть файл

@ -87,6 +87,7 @@
<Import Project="..\AppLifecycle\AppLifecycle.vcxitems" Label="AppLifecycle" />
<Import Project="..\PushNotifications\PushNotifications.vcxitems" Label="PushNotifications" />
<Import Project="..\AppNotifications\AppNotifications.vcxitems" Label="AppNotifications" />
<Import Project="..\AppNotifications\AppNotificationBuilder\AppNotificationBuilder.vcxitems" Label="AppNotificationBuilder" />
<Import Project="..\DynamicDependency\API\DynamicDependency.vcxitems" Label="Shared" />
<Import Project="..\UndockedRegFreeWinRT\UndockedRegFreeWinRT.vcxitems" Label="Shared" />
<Import Project="..\Common\Common.vcxitems" Label="Shared" />
@ -279,9 +280,9 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets" Condition="Exists('..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets')" />
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets" Condition="Exists('..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets')" />
<Import Project="..\..\packages\Microsoft.SourceLink.Common.1.1.0-beta-21055-01\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.1.0-beta-21055-01\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.1.0-beta-20204-02\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.1.0-beta-20204-02\build\Microsoft.Build.Tasks.Git.targets')" />
<Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.1.0-beta-20204-02\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.1.0-beta-20204-02\build\Microsoft.SourceLink.GitHub.targets')" />
@ -297,10 +298,10 @@
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.FrameworkUdk.1.1.2-CI-25087.1001.220410-1342.0\build\native\Microsoft.FrameworkUdk.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.FrameworkUdk.1.0.5-CI-25099.1001.220418-1000.0\build\native\Microsoft.FrameworkUdk.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.Common.1.1.0-beta-21055-01\build\Microsoft.SourceLink.Common.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.Common.1.1.0-beta-21055-01\build\Microsoft.SourceLink.Common.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.Common.1.1.0-beta-21055-01\build\Microsoft.SourceLink.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.Common.1.1.0-beta-21055-01\build\Microsoft.SourceLink.Common.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.1.0-beta-20204-02\build\Microsoft.Build.Tasks.Git.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Build.Tasks.Git.1.1.0-beta-20204-02\build\Microsoft.Build.Tasks.Git.props'))" />

Просмотреть файл

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Build.Tasks.Git" version="1.1.0-beta-20204-02" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.FrameworkUdk" version="1.1.2-CI-25087.1001.220410-1342.0" targetFramework="native" />
<package id="Microsoft.FrameworkUdk" version="1.0.5-CI-25099.1001.220418-1000.0" targetFramework="native" />
<package id="Microsoft.SourceLink.Common" version="1.1.0-beta-21055-01" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.1.0-beta-20204-02" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.220531.1" targetFramework="native" />

37
docs/develop-branch.md Normal file
Просмотреть файл

@ -0,0 +1,37 @@
`develop` Branch
===
Building the full Windows App SDK package involves multiple repos and build pipelines.
Beyond the publicly-visible repos, we also have closed-source repos that produce public packages which
are then consumed by this repo ([WindowsAppSDK](https://github.com/microsoft/WindowsAppSDK)).
Some of those packages can't yet be pushed to the public feed on a CI/nightly basis though.
Until that's resolved, we could get this repo into a state of being buildable only internally,
by restoring the latest package from an internal feed.
To allow either configuration to be built (using the public dependent package or the internal one),
we maintain two branches (similar to the GitFlow process):
* `main` branch consumes the latest public package
* `develop` branch consumes the latest internal package.
The `develop` branch code is in the repo and still open, but can only be built internally.
The `main` branch is always buildable at HEAD.
External contributions to the repo are made to the `main` branch,
and are merged internally into `develop` when completed.
Whenever a new public version of the dependent packages are pushed to the public feed,
the `develop` branch can be merged into `main`.
For example as part of (pre)releases.
Merging between `develop` and `main` is normal (not squashed),
so that both branches can show the correct history, just with a few extra merge commits.
Once the packages can be kept immediately updated we can drop the `develop` branch
and not lose any history.
The long-lasting difference between `main` and `develop` is the `nuget.config` file;
in `main` it references the public feed and in `develop` it references the internal feed.
Package references might be different too if `develop` branch is consuming a package that's
not yet on the public feed.
![Example of main and develop branching](images/develop-branch-example.jpg)

Двоичные данные
docs/images/develop-branch-example.jpg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 90 KiB

Просмотреть файл

@ -0,0 +1,7 @@
For status checks on the develop branch, please use TransportPackage-Foundation
(https://microsoft.visualstudio.com/ProjectReunion/_build?definitionId=57248)
and run the build against your PR branch with the default parameters.
For status checks on the main branch, please use microsoft.ProjectReunion
(https://dev.azure.com/ms/ProjectReunion/_build?definitionId=391&_a=summary)
and run the build against your PR branch with the default paramters.

Просмотреть файл

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Dependencies>
<ProductDependencies>
<Dependency Name="Microsoft.WindowsAppSDK.AppLicensingInternal.TransportPackage" Version="1.1.0-stable.20220518.4">
<Dependency Name="Microsoft.WindowsAppSDK.AppLicensingInternal.TransportPackage" Version="1.2.0-main.20220810.1">
<Uri>https://dev.azure.com/microsoft/ProjectReunion/_git/ProjectReunionClosed</Uri>
<Sha>0f4add1a10caa92e635919b81a678d2f1bcf229b</Sha>
<Sha>1261bb31992442bf7e560330524002ea3a3e9d85</Sha>
</Dependency>
</ProductDependencies>
<ToolsetDependencies>

Просмотреть файл

@ -22,7 +22,7 @@ parameters:
default: 'ProjectReunionInternal'
steps:
- checkout: git://ProjectReunion/ProjectReunionInternal
- checkout: git://ProjectReunion/ProjectReunionInternal@release/1.2-preview1
- task: AzureKeyVault@1
inputs:

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 66 KiB

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 410 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 51 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 62 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 278 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 73 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 74 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 92 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 109 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 76 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 322 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 148 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 142 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 272 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 128 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 124 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 87 KiB

Двоичные данные
specs/AppNotifications/AppNotificationContentSpec/TextExample.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 22 KiB

Просмотреть файл

@ -139,6 +139,53 @@ int main()
}
```
## Registering for App Notifications using assets
For Unpackaged applications, the developer can Register using a custom Display Name and Icon.
WinAppSDK will register the application and display these assets when an App Notification is received.
The developer should provide both the assets or not provide them at all. Icon provided by the developer
should be a valid supported format. The API supports the formats - png, bmp, jpg, ico. The icon
should reside on the local machine only otherwise the API throws an exception. For Packaged applications,
this API is not applicable and will throw an exception. Below are some examples of usage:
```cpp
int main()
{
auto manager = winrt::AppNotificationManager::Default();
std::wstring iconFilepath{ std::filesystem::current_path() / "icon.ico" };
winrt::hstring displayName{ L"AppNotifications" };
manager.Register(displayName, winrt::Windows::Foundation::Uri {iconFilepath});
// other app init and then message loop here
// Call Unregister() before exiting main so that subsequent invocations will launch a new process
manager.Unregister();
return 0;
}
```
```cpp
int main()
{
auto manager = winrt::AppNotificationManager::Default();
std::wstring iconFilepath{ std::filesystem::current_path() / "icon.ico" };
std::wstring displayName{};
wil::GetModuleFileNameExW(GetCurrentProcess(), nullptr, displayName);
manager.Register(displayName.c_str(), winrt::Windows::Foundation::Uri {iconFilepath});
// other app init and then message loop here
// Call Unregister() before exiting main so that subsequent invocations will launch a new process
manager.Unregister();
return 0;
}
```
## Displaying an App Notification
To display a Notification, an app needs to define a payload in xml. In the example below, the
@ -451,6 +498,9 @@ namespace Microsoft.Windows.AppNotifications
// For Unpackaged apps, the caller process will be registered as the COM server. And assets like displayname and icon will be gleaned from Shell and registered as well.
void Register();
// For Unpackaged apps only, the caller process will be registered as the COM server.
void Register(String displayName, Windows.Foundation.Uri iconUri);
// Unregisters the COM Service so that a subsequent activation will launch a new process
void Unregister();

Просмотреть файл

@ -0,0 +1,670 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
namespace winrt
{
using namespace winrt::Microsoft::Windows::AppNotifications::Builder;
}
namespace Test::AppNotification::Builder
{
inline const winrt::Windows::Foundation::Uri c_sampleUri{ L"http://www.microsoft.com" };
class APITests
{
public:
BEGIN_TEST_CLASS(APITests)
TEST_CLASS_PROPERTY(L"ThreadingModel", L"MTA")
TEST_CLASS_PROPERTY(L"RunFixtureAs:Class", L"RestrictedUser")
END_TEST_CLASS()
TEST_CLASS_SETUP(ClassInit)
{
::Test::Bootstrap::Setup();
return true;
}
TEST_CLASS_CLEANUP(ClassUninit)
{
::Test::Bootstrap::Cleanup();
return true;
}
TEST_METHOD_SETUP(MethodSetup)
{
::Test::Bootstrap::SetupBootstrap();
::WindowsAppRuntime::VersionInfo::TestInitialize(::Test::Bootstrap::TP::WindowsAppRuntimeFramework::c_PackageFamilyName,
::Test::Bootstrap::TP::WindowsAppRuntimeMain::c_PackageFamilyName);
return true;
}
TEST_METHOD_CLEANUP(MethodCleanup)
{
::WindowsAppRuntime::VersionInfo::TestShutdown();
::Test::Bootstrap::CleanupBootstrap();
return true;
}
TEST_METHOD(AppNotificationBuilderDefault)
{
auto builder{ winrt::AppNotificationBuilder() };
auto expected{ L"<toast><visual><binding template='ToastGeneric'></binding></visual></toast>"};
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetTimeStamp)
{
auto time{ winrt::Windows::Foundation::DateTime::clock::now() };
auto builder{ winrt::AppNotificationBuilder().SetTimeStamp(time) };
struct tm dateTime {};
auto timeAsTimeT{ winrt::clock::to_time_t(time) };
localtime_s(&dateTime, &timeAsTimeT);
std::wstringstream buffer;
buffer << std::put_time(&dateTime, L"%FT%T%z");
std::wstring expectedTimestamp{ buffer.str() };
expectedTimestamp.insert(expectedTimestamp.size() - c_offsetIndexValue, L":");
std::wstring expected{ wil::str_printf<std::wstring>(L"<toast displayTimestamp='%ls'><visual><binding template='ToastGeneric'></binding></visual></toast>", expectedTimestamp.c_str()) };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddOneArgument)
{
auto builder{ winrt::AppNotificationBuilder().AddArgument(L"key", L"value") };
auto expected{ L"<toast launch='key=value'><visual><binding template='ToastGeneric'></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddTwoArguments)
{
auto builder{ winrt::AppNotificationBuilder().AddArgument(L"key1", L"value1").AddArgument(L"key2", L"value2") };
auto expected{ L"<toast launch='key1=value1;key2=value2'><visual><binding template='ToastGeneric'></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddArgumentEmptyValue)
{
auto builder{ winrt::AppNotificationBuilder().AddArgument(L"key", L"") };
auto expected{ L"<toast launch='key'><visual><binding template='ToastGeneric'></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddArgumentWithPercentChar)
{
auto builder{ winrt::AppNotificationBuilder().AddArgument(L"k%ey", L"v%alue") };
auto expected{ L"<toast launch='k%25ey=v%25alue'><visual><binding template='ToastGeneric'></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddArgumentWithEqualChar)
{
auto builder{ winrt::AppNotificationBuilder().AddArgument(L"k=ey", L"v=alue") };
auto expected{ L"<toast launch='k%3Dey=v%3Dalue'><visual><binding template='ToastGeneric'></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddArgumentWithSemicolonChar)
{
auto builder{ winrt::AppNotificationBuilder().AddArgument(L"k;ey", L"v;alue") };
auto expected{ L"<toast launch='k%3Bey=v%3Balue'><visual><binding template='ToastGeneric'></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(DecodeArguments)
{
VERIFY_ARE_EQUAL(Decode(L"key%3B"), L"key;");
VERIFY_ARE_EQUAL(Decode(L"key%3D"), L"key=");
VERIFY_ARE_EQUAL(Decode(L"key%25"), L"key%");
VERIFY_ARE_EQUAL(Decode(L"key%3B%3D%25"), L"key;=%");
VERIFY_ARE_EQUAL(Decode(L"%25%25%25"), L"%%%");
}
TEST_METHOD(AppNotificationBuilderAddArgumentEmptyKey)
{
VERIFY_THROWS_HR(winrt::AppNotificationBuilder().AddArgument(L"", L""), E_INVALIDARG);
}
TEST_METHOD(AppNotificationBuilderSetReminderScenario)
{
auto builder{ winrt::AppNotificationBuilder().SetScenario(winrt::AppNotificationScenario::Reminder) };
auto expected{ L"<toast scenario='reminder'><visual><binding template='ToastGeneric'></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetAlarmScenario)
{
auto builder{ winrt::AppNotificationBuilder().SetScenario(winrt::AppNotificationScenario::Alarm) };
auto expected{ L"<toast scenario='alarm'><visual><binding template='ToastGeneric'></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetIncomingCallScenario)
{
auto builder{ winrt::AppNotificationBuilder().SetScenario(winrt::AppNotificationScenario::IncomingCall) };
auto expected{ L"<toast scenario='incomingCall'><visual><binding template='ToastGeneric'></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetUrgentScenario)
{
auto builder{ winrt::AppNotificationBuilder().SetScenario(winrt::AppNotificationScenario::Urgent) };
auto expected{ L"<toast scenario='urgent'><visual><binding template='ToastGeneric'></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddText)
{
auto builder{ winrt::AppNotificationBuilder().AddText(L"content") };
auto expected{ L"<toast><visual><binding template='ToastGeneric'><text>content</text></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddTextWithLanguage)
{
auto builder{ winrt::AppNotificationBuilder()
.AddText(L"content", winrt::AppNotificationTextProperties()
.SetLanguage(L"en-US"))
};
auto expected{ L"<toast><visual><binding template='ToastGeneric'><text lang='en-US'>content</text></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddTextWithMaxLines)
{
auto builder{ winrt::AppNotificationBuilder()
.AddText(L"content", winrt::AppNotificationTextProperties()
.SetMaxLines(2))
};
auto expected{ L"<toast><visual><binding template='ToastGeneric'><text hint-maxLines='2'>content</text></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddTextWithCallScenarioAlign)
{
auto builder{ winrt::AppNotificationBuilder()
.AddText(L"content", winrt::AppNotificationTextProperties()
.SetIncomingCallAlignment())
};
auto expected{ L"<toast scenario='incomingCall'><visual><binding template='ToastGeneric'><text hint-callScenarioCenterAlign='true'>content</text></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddTextWithAllProperties)
{
auto builder{ winrt::AppNotificationBuilder()
.AddText(L"content", winrt::AppNotificationTextProperties()
.SetLanguage(L"en-US")
.SetMaxLines(2)
.SetIncomingCallAlignment())
};
auto expected{ L"<toast scenario='incomingCall'><visual><binding template='ToastGeneric'><text lang='en-US' hint-maxLines='2' hint-callScenarioCenterAlign='true'>content</text></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddTextThrows)
{
VERIFY_THROWS_HR(winrt::AppNotificationBuilder()
.AddText(L"content")
.AddText(L"content")
.AddText(L"content")
.AddText(L"content"), E_INVALIDARG);
}
TEST_METHOD(AppNotificationBuilderAddAttributionText)
{
auto builder{ winrt::AppNotificationBuilder().SetAttributionText(L"content") };
auto expected{ L"<toast><visual><binding template='ToastGeneric'><text placement='attribution'>content</text></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddAttributionTextWithLanguage)
{
auto builder{ winrt::AppNotificationBuilder().SetAttributionText(L"content", L"en-US")};
auto expected{ L"<toast><visual><binding template='ToastGeneric'><text placement='attribution' lang='en-US'>content</text></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetInlineImage)
{
auto builder{ winrt::AppNotificationBuilder().SetInlineImage(c_sampleUri) };
auto expected{ L"<toast><visual><binding template='ToastGeneric'><image src='http://www.microsoft.com/'/></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetInlineImageWithProperties)
{
auto builder{ winrt::AppNotificationBuilder().SetInlineImage(c_sampleUri, winrt::AppNotificationImageCrop::Circle, L"altText")};
auto expected{ L"<toast><visual><binding template='ToastGeneric'><image src='http://www.microsoft.com/' alt='altText' hint-crop='circle'/></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetAppLogoOverride)
{
auto builder{ winrt::AppNotificationBuilder().SetAppLogoOverride(c_sampleUri) };
auto expected{ L"<toast><visual><binding template='ToastGeneric'><image placement='appLogoOverride' src='http://www.microsoft.com/'/></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetAppLogoOverrideProperties)
{
auto builder{ winrt::AppNotificationBuilder().SetAppLogoOverride(c_sampleUri, winrt::AppNotificationImageCrop::Circle, L"altText") };
auto expected{ L"<toast><visual><binding template='ToastGeneric'><image placement='appLogoOverride' src='http://www.microsoft.com/' alt='altText' hint-crop='circle'/></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetHeroImage)
{
auto builder{ winrt::AppNotificationBuilder().SetHeroImage(c_sampleUri) };
auto expected{ L"<toast><visual><binding template='ToastGeneric'><image placement='hero' src='http://www.microsoft.com/'/></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetHeroImageWithAlt)
{
auto builder{ winrt::AppNotificationBuilder().SetHeroImage(c_sampleUri, L"altText") };
auto expected{ L"<toast><visual><binding template='ToastGeneric'><image placement='hero' src='http://www.microsoft.com/' alt='altText'/></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddButton)
{
auto builder{ winrt::AppNotificationBuilder()
.AddButton(winrt::AppNotificationButton(L"content")
.AddArgument(L"key", L"value"))
};
auto expected{ L"<toast><visual><binding template='ToastGeneric'></binding></visual><actions><action content='content' arguments='key=value'/></actions></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddButtonWithPlacement)
{
auto builder{ winrt::AppNotificationBuilder()
.AddButton(winrt::AppNotificationButton(L"content")
.AddArgument(L"key", L"value")
.SetContextMenuPlacement())
};
auto expected{ L"<toast><visual><binding template='ToastGeneric'></binding></visual><actions><action content='content' arguments='key=value' placement='contextMenu'/></actions></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderTooManyButtons)
{
VERIFY_THROWS_HR(winrt::AppNotificationBuilder()
.AddButton(winrt::AppNotificationButton(L"content").AddArgument(L"key1", L"value1"))
.AddButton(winrt::AppNotificationButton(L"content").AddArgument(L"key2", L"value2"))
.AddButton(winrt::AppNotificationButton(L"content").AddArgument(L"key3", L"value3"))
.AddButton(winrt::AppNotificationButton(L"content").AddArgument(L"key4", L"value4"))
.AddButton(winrt::AppNotificationButton(L"content").AddArgument(L"key5", L"value5"))
.AddButton(winrt::AppNotificationButton(L"content").AddArgument(L"key6", L"value6")), E_INVALIDARG);
}
TEST_METHOD(AppNotificationBuilderAddButtonWithProtocolActivation)
{
auto builder{ winrt::AppNotificationBuilder()
.AddButton(winrt::AppNotificationButton(L"content")
.SetInvokeUri(c_sampleUri))
};
auto expected{ L"<toast><visual><binding template='ToastGeneric'></binding></visual><actions><action content='content' arguments='http://www.microsoft.com/' activationType='protocol'/></actions></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddButtonWithProperties)
{
auto builder{ winrt::AppNotificationBuilder()
.AddButton(winrt::AppNotificationButton(L"content")
.AddArgument(L"key", L"value")
.SetButtonStyle(winrt::AppNotificationButtonStyle::Success)
.SetIcon(c_sampleUri)
.SetInputId(L"inputId")
.SetToolTip(L"toolTip"))
};
auto expected{ L"<toast useButtonStyle='true'><visual><binding template='ToastGeneric'></binding></visual><actions><action content='content' arguments='key=value' imageUri='http://www.microsoft.com/' hint-inputId='inputId' hint-buttonStyle='Success' hint-toolTip='toolTip'/></actions></toast>"};
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddButtonWithEmptyKey)
{
VERIFY_THROWS_HR(winrt::AppNotificationBuilder()
.AddButton(winrt::AppNotificationButton(L"content")
.AddArgument(L"", L"value")), E_INVALIDARG);
}
TEST_METHOD(AppNotificationBuilderAddButtonWithArgumentAndProtocol)
{
VERIFY_THROWS_HR(winrt::AppNotificationBuilder()
.AddButton(winrt::AppNotificationButton(L"content")
.AddArgument(L"key", L"value")
.SetInvokeUri(c_sampleUri)), E_INVALIDARG);
VERIFY_THROWS_HR(winrt::AppNotificationBuilder()
.AddButton(winrt::AppNotificationButton(L"content")
.SetInvokeUri(c_sampleUri)
.AddArgument(L"key", L"value")), E_INVALIDARG);
}
TEST_METHOD(AppNotificationBuilderSetAudioWithUri)
{
auto builder{ winrt::AppNotificationBuilder()
.SetAudioUri(c_sampleUri) };
auto expected{ L"<toast><visual><binding template='ToastGeneric'></binding></visual><audio src='http://www.microsoft.com/'/></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetAudioWithUriAndDuration)
{
auto builder{ winrt::AppNotificationBuilder()
.SetDuration(winrt::AppNotificationDuration::Long)
.SetAudioUri(c_sampleUri, winrt::AppNotificationAudioLooping::Loop) };
auto expected{ L"<toast duration='long'><visual><binding template='ToastGeneric'></binding></visual><audio src='http://www.microsoft.com/' loop='true'/></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetAudioWithSoundEvent)
{
auto builder{ winrt::AppNotificationBuilder()
.SetAudioEvent(winrt::AppNotificationSoundEvent::Reminder) };
auto expected{ L"<toast><visual><binding template='ToastGeneric'></binding></visual><audio src='ms-winsoundevent:Notification.Reminder'/></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderSetAudioWithSoundEventAndDuration)
{
auto builder{ winrt::AppNotificationBuilder()
.SetDuration(winrt::AppNotificationDuration::Long)
.SetAudioEvent(winrt::AppNotificationSoundEvent::Reminder, winrt::AppNotificationAudioLooping::Loop) };
auto expected{ L"<toast duration='long'><visual><binding template='ToastGeneric'></binding></visual><audio src='ms-winsoundevent:Notification.Reminder' loop='true'/></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderMuteAudio)
{
auto builder{ winrt::AppNotificationBuilder().MuteAudio() };
auto expected{ L"<toast><visual><binding template='ToastGeneric'></binding></visual><audio silent='true'/></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderBuildNotificationWithTooLargePayload)
{
VERIFY_THROWS_HR(winrt::AppNotificationBuilder()
.AddText(std::wstring(5120, 'A').c_str())
.BuildNotification(), E_FAIL);
}
TEST_METHOD(AppNotificationAddProgressBar)
{
auto builder{ winrt::AppNotificationBuilder()
.AddText(L"Downloading this week's new music...")
.AddProgressBar(winrt::AppNotificationProgressBar()
.BindTitle()
.BindValueStringOverride()) };
auto expected{ L"<toast><visual><binding template='ToastGeneric'><text>Downloading this week&apos;s new music...</text><progress title='{progressTitle}' status='{progressStatus}' value='{progressValue}' valueStringOverride='{progressValueString}'/></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationAddMoreThanOneProgressBar)
{
auto builder{ winrt::AppNotificationBuilder()
.AddText(L"Downloading this week's new music...")
.AddProgressBar(winrt::AppNotificationProgressBar()
.BindTitle()
.BindValueStringOverride())
.AddProgressBar(winrt::AppNotificationProgressBar()
.SetValue(0.8)
.SetStatus(L"Still downloading...")) };
auto expected{ L"<toast><visual><binding template='ToastGeneric'><text>Downloading this week&apos;s new music...</text><progress title='{progressTitle}' status='{progressStatus}' value='{progressValue}' valueStringOverride='{progressValueString}'/><progress status='Still downloading...' value='0.8'/></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationProgressBarDefaults)
{
auto progressBar{ winrt::AppNotificationProgressBar() };
auto expected{ L"<progress status='{progressStatus}' value='{progressValue}'/>" };
VERIFY_ARE_EQUAL(progressBar.as<winrt::Windows::Foundation::IStringable>().ToString(), expected);
}
TEST_METHOD(AppNotificationProgressBarSetSpecificValue)
{
auto progressBar{ winrt::AppNotificationProgressBar() };
progressBar.Value(0.8);
auto expected{ L"<progress status='{progressStatus}' value='0.8'/>" };
VERIFY_ARE_EQUAL(progressBar.as<winrt::Windows::Foundation::IStringable>().ToString(), expected);
}
TEST_METHOD(AppNotificationProgressBarSetValueLargerThanOne)
{
auto progressBar{ winrt::AppNotificationProgressBar() };
VERIFY_THROWS_HR(progressBar.Value(1.01), E_INVALIDARG);
VERIFY_THROWS_HR(winrt::AppNotificationProgressBar().SetValue(1.01), E_INVALIDARG);
}
TEST_METHOD(AppNotificationProgressBarSetValueSmallerThanZero)
{
auto progressBar{ winrt::AppNotificationProgressBar() };
VERIFY_THROWS_HR(progressBar.Value(-0.1), E_INVALIDARG);
VERIFY_THROWS_HR(winrt::AppNotificationProgressBar().SetValue(-0.1), E_INVALIDARG);
}
TEST_METHOD(AppNotificationProgressBarSetSpecificValueThenChangeToBind)
{
auto progressBar{ winrt::AppNotificationProgressBar() };
progressBar.Value(0.8);
progressBar.BindValue();
auto expected{ L"<progress status='{progressStatus}' value='{progressValue}'/>" };
VERIFY_ARE_EQUAL(progressBar.as<winrt::Windows::Foundation::IStringable>().ToString(), expected);
}
TEST_METHOD(AppNotificationProgressBarBindTitleThenChangeToSpecificText)
{
auto progressBar{ winrt::AppNotificationProgressBar()
.BindTitle()
.SetTitle(L"Specific title") };
auto expected{ L"<progress title='Specific title' status='{progressStatus}' value='{progressValue}'/>" };
VERIFY_ARE_EQUAL(progressBar.as<winrt::Windows::Foundation::IStringable>().ToString(), expected);
}
TEST_METHOD(AppNotificationBuilderAddTextBox)
{
auto builder{ winrt::AppNotificationBuilder()
.AddTextBox(L"input1") };
auto expected{ L"<toast><visual><binding template='ToastGeneric'></binding></visual><actions><input id='input1' type='text'/></actions></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddTextBoxWithEmptyId)
{
VERIFY_THROWS_HR(winrt::AppNotificationBuilder()
.AddTextBox(L""), E_INVALIDARG);
}
TEST_METHOD(AppNotificationBuilderAddTextBoxWithEmptyIdAndPlaceHolderTextAndTitle)
{
VERIFY_THROWS_HR(winrt::AppNotificationBuilder()
.AddTextBox(L"", L"placeholder text", L"title"), E_INVALIDARG);
}
TEST_METHOD(AppNotificationBuilderAddTooManyTextBoxes)
{
VERIFY_THROWS_HR(winrt::AppNotificationBuilder()
.AddTextBox(L"input1")
.AddTextBox(L"input2")
.AddTextBox(L"input3")
.AddTextBox(L"input4")
.AddTextBox(L"input5")
.AddTextBox(L"input6"), E_INVALIDARG);
}
TEST_METHOD(AppNotificationBuilderAddTextBoxWithPlaceHolderTextAndTitle)
{
auto builder{ winrt::AppNotificationBuilder()
.AddTextBox(L"some input id", L"Some placeholder text", L"A Title")};
auto expected{ L"<toast><visual><binding template='ToastGeneric'></binding></visual><actions><input id='some input id' type='text' placeHolderContent='Some placeholder text' title='A Title'/></actions></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddComboBox)
{
auto builder{ winrt::AppNotificationBuilder()
.AddComboBox(winrt::AppNotificationComboBox(L"comboBox1")
.AddItem(L"item1", L"item1 text")
.AddItem(L"item2", L"item2 text")
.AddItem(L"item3", L"item3 text")
.SetTitle(L"ComboBox Title")
.SetSelectedItem(L"item2"))};
auto expected{ L"<toast><visual><binding template='ToastGeneric'></binding></visual><actions><input id='comboBox1' type='selection' title='ComboBox Title' defaultInput='item2'><selection id='item1' content='item1 text'/><selection id='item2' content='item2 text'/><selection id='item3' content='item3 text'/></input></actions></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderAddTooManyComboBox)
{
VERIFY_THROWS_HR(winrt::AppNotificationBuilder()
.AddTextBox(L"input1")
.AddTextBox(L"input2")
.AddTextBox(L"input3")
.AddComboBox(winrt::AppNotificationComboBox(L"comboBox1")
.AddItem(L"item1", L"item1 text"))
.AddComboBox(winrt::AppNotificationComboBox(L"comboBox2")
.AddItem(L"item1", L"item1 text"))
.AddComboBox(winrt::AppNotificationComboBox(L"comboBox3")
.AddItem(L"item1", L"item1 text")), E_INVALIDARG);
}
TEST_METHOD(AppNotificationBuilderAddTooManyInputElements)
{
VERIFY_THROWS_HR(winrt::AppNotificationBuilder()
.AddComboBox(winrt::AppNotificationComboBox(L"comboBox1")
.AddItem(L"item1", L"item1 text"))
.AddComboBox(winrt::AppNotificationComboBox(L"comboBox2")
.AddItem(L"item1", L"item1 text"))
.AddComboBox(winrt::AppNotificationComboBox(L"comboBox3")
.AddItem(L"item1", L"item1 text"))
.AddComboBox(winrt::AppNotificationComboBox(L"comboBox4")
.AddItem(L"item1", L"item1 text"))
.AddComboBox(winrt::AppNotificationComboBox(L"comboBox5")
.AddItem(L"item1", L"item1 text"))
.AddComboBox(winrt::AppNotificationComboBox(L"comboBox6")
.AddItem(L"item1", L"item1 text")), E_INVALIDARG);
}
TEST_METHOD(AppNotificationComboBoxAddTooManySelectionItems)
{
VERIFY_THROWS_HR(winrt::AppNotificationComboBox(L"comboBox1")
.AddItem(L"item1", L"item1 text")
.AddItem(L"item2", L"item2 text")
.AddItem(L"item3", L"item3 text")
.AddItem(L"item4", L"item4 text")
.AddItem(L"item5", L"item5 text")
.AddItem(L"item6", L"item6 text"), E_INVALIDARG);
}
TEST_METHOD(AppNotificationComboBoxAddFiveSelectionItems)
{
auto comboBox{ winrt::AppNotificationComboBox(L"comboBox1")
.AddItem(L"item1", L"item1 text")
.AddItem(L"item2", L"item2 text")
.AddItem(L"item3", L"item3 text")
.AddItem(L"item4", L"item4 text")
.AddItem(L"item5", L"item5 text") };
auto expected{ L"<input id='comboBox1' type='selection'><selection id='item1' content='item1 text'/><selection id='item2' content='item2 text'/><selection id='item3' content='item3 text'/><selection id='item4' content='item4 text'/><selection id='item5' content='item5 text'/></input>" };
VERIFY_ARE_EQUAL(comboBox.as<winrt::Windows::Foundation::IStringable>().ToString(), expected);
}
TEST_METHOD(AppNotificationComboBoxAddSelectionItemWithoutAnId)
{
VERIFY_THROWS_HR(winrt::AppNotificationComboBox(L"comboBox1")
.AddItem(L"", L"item text"), E_INVALIDARG);
}
TEST_METHOD(AppNotificationComboBoxAddTwoSelectionItemsWithSameId)
{
auto comboBox{ winrt::AppNotificationComboBox(L"comboBox1")
.AddItem(L"item1", L"item1 text")
.AddItem(L"item1", L"item2 text") };
auto expected{ L"<input id='comboBox1' type='selection'><selection id='item1' content='item2 text'/></input>" };
VERIFY_ARE_EQUAL(comboBox.as<winrt::Windows::Foundation::IStringable>().ToString(), expected);
}
TEST_METHOD(AppNotificationComboBoxSetSelectedItemWithoutAnId)
{
VERIFY_THROWS_HR(winrt::AppNotificationComboBox(L"comboBox1")
.SetSelectedItem(L""), E_INVALIDARG);
}
TEST_METHOD(AppNotificationCreateComboBoxWithoutAnId)
{
VERIFY_THROWS_HR(winrt::AppNotificationComboBox(L""), E_INVALIDARG);
}
TEST_METHOD(AppNotificationBuilderEscapeXmlCharacters)
{
auto builder{ winrt::AppNotificationBuilder().AddText(LR"(&"'<>)") };
std::wstring expected{ L"<toast><visual><binding template='ToastGeneric'><text>&amp;&quot;&apos;&lt;&gt;</text></binding></visual></toast>"};
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
}
TEST_METHOD(AppNotificationBuilderArgumentsWithXmlCharacters)
{
auto builder{ winrt::AppNotificationBuilder()
.AddArgument(LR"(&;"='%<>)", L"")
.AddArgument(LR"(&"'<>)", L";=%")};
std::wstring expected{ L"<toast launch='&amp;%3B&quot;%3D&apos;%25&lt;&gt;;&amp;&quot;&apos;&lt;&gt;=%3B%3D%25'><visual><binding template='ToastGeneric'></binding></visual></toast>" };
VERIFY_ARE_EQUAL(builder.BuildNotification().Payload(), expected);
VERIFY_ARE_EQUAL(Decode(LR"(&%3B"%3D'%25<>)"), LR"(&;"='%<>)");
VERIFY_ARE_EQUAL(Decode(L"%3B%3D%25"), L";=%");
}
};
}

Просмотреть файл

@ -0,0 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
#include "AppNotificationBuilderTests.h"

Просмотреть файл

@ -0,0 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#pragma once

Просмотреть файл

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{131de0c4-aa1e-4649-b5bc-7b43508fa93a}</ProjectGuid>
<RootNamespace>AppNotificationBuilderTests</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>$(RepoRoot)\test\inc;$(RepoRoot)\Dev\Common;$(RepoRoot)\Dev\AppNotifications\AppNotificationBuilder;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories);$(OutDir)\..\WindowsAppRuntime_DLL;$(OutDir)\..\WindowsAppRuntime_BootstrapDLL</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="$(WindowsAppSDKBuildPipeline) == '1'">$(RepoRoot);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>onecore.lib;onecoreuap.lib;Microsoft.WindowsAppRuntime.lib;wex.common.lib;wex.logger.lib;te.common.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);$(OutDir)\..\WindowsAppRuntime_DLL</AdditionalLibraryDirectories>
<DelayLoadDLLs>Microsoft.WindowsAppRuntime.Bootstrap.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<DelayLoadDLLs>Microsoft.WindowsAppRuntime.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="APITests.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Windows.AppNotifications.Builder">
<HintPath>$(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.Windows.AppNotifications.Builder.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
</Reference>
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Windows.AppNotifications">
<HintPath>$(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.Windows.AppNotifications.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\dev\WindowsAppRuntime_BootstrapDLL\WindowsAppRuntime_BootstrapDLL.vcxproj">
<Project>{f76b776e-86f5-48c5-8fc7-d2795ecc9746}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\packages\Microsoft.Taef.10.58.210222006-develop\build\Microsoft.Taef.targets" Condition="Exists('..\..\packages\Microsoft.Taef.10.58.210222006-develop\build\Microsoft.Taef.targets')" />
<Import Project="..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
</ImportGroup>
<Target Name="CopyFiles" AfterTargets="AfterBuild">
<Copy SourceFiles="$(OutDir)\..\WindowsAppRuntime_BootstrapDLL\Microsoft.WindowsAppRuntime.Bootstrap.dll" DestinationFolder="$(OutDir)" />
<Copy SourceFiles="$(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.Internal.FrameworkUdk.dll" DestinationFolder="$(OutDir)" />
</Target>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\Microsoft.Taef.10.58.210222006-develop\build\Microsoft.Taef.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Taef.10.58.210222006-develop\build\Microsoft.Taef.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220201.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.220531.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{4b514c96-7ee8-44e5-aeb3-64c1bc0d6b91}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{9f96baa5-3d60-4ef4-9ff2-5a5fe8d7367b}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="APITests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Taef" version="10.58.210222006-develop" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.220531.1" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220201.1" targetFramework="native" />
</packages>

Просмотреть файл

@ -0,0 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#include "pch.h"
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

Просмотреть файл

@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
#ifndef PCH_H
#define PCH_H
#include <unknwn.h>
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <sddl.h>
#include <appmodel.h>
#include <vector>
#include <string>
#include <algorithm>
#include <wil/resource.h>
#include <wil/stl.h>
#include <wil/result.h>
#include <wil/cppwinrt.h>
#include <wil/token_helpers.h>
#include <wrl.h>
#include <WexTestClass.h>
#include <sstream>
#include <iomanip>
#include <wil/result_macros.h>
#include <wil/com.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Networking.PushNotifications.h>
#include <winrt/Windows.ApplicationModel.Activation.h>
#include <winrt/Windows.Management.Deployment.h>
#include <winrt/Windows.Security.Cryptography.h>
#include <winrt/Windows.Storage.h>
#include <winrt/Windows.System.h>
#include <WindowsAppRuntime.Test.Package.h>
#include <WindowsAppRuntime.Test.TAEF.h>
#include <WindowsAppRuntime.Test.Bootstrap.h>
#include <windows.applicationmodel.h>
#include <windows.applicationmodel.background.h>
#include <ShObjIdl_core.h>
#include <winrt/Microsoft.Windows.AppNotifications.h>
#include <winrt/Microsoft.Windows.AppNotifications.Builder.h>
#include <AppNotificationBuilderUtility.h>
#include <WindowsAppRuntime.SelfContained.h>
#include <WindowsAppRuntime.VersionInfo.h>
#define VERIFY_THROWS_HR(expression, hr) \
VERIFY_THROWS_SPECIFIC(expression, \
winrt::hresult_error, \
[&](winrt::hresult_error e) -> bool \
{ \
return (e.code() == hr); \
})
namespace TP = ::Test::Packages;
namespace TAEF = ::Test::TAEF;
#endif //PCH_H

Просмотреть файл

@ -94,6 +94,16 @@
<ActivatableClass ActivatableClassId="Microsoft.Windows.Security.AccessControl.SecurityDescriptorHelpers" ThreadingModel="both" />
</InProcessServer>
</Extension>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>Microsoft.WindowsAppRuntime.dll</Path>
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.Builder.AppNotificationBuilder" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.Builder.AppNotificationTextProperties" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.Builder.AppNotificationButton" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.Builder.AppNotificationProgressBar" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.AppNotifications.Builder.AppNotificationComboBox" ThreadingModel="both" />
</InProcessServer>
</Extension>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>Microsoft.WindowsAppRuntime.dll</Path>

Просмотреть файл

@ -211,6 +211,11 @@
<IsWinMDFile>true</IsWinMDFile>
<Implementation>$(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.WindowsAppRuntime.dll</Implementation>
</Reference>
<Reference Include="Microsoft.Windows.AppNotifications.Builder">
<HintPath>$(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.Windows.AppNotifications.Builder.winmd</HintPath>
<IsWinMDFile>true</IsWinMDFile>
<Implementation>$(OutDir)\..\WindowsAppRuntime_DLL\Microsoft.WindowsAppRuntime.dll</Implementation>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\dev\WindowsAppRuntime_BootstrapDLL\WindowsAppRuntime_BootstrapDLL.vcxproj">

Просмотреть файл

@ -18,6 +18,7 @@ namespace winrt
using namespace winrt::Microsoft::Windows::AppLifecycle;
using namespace winrt::Microsoft::Windows::PushNotifications;
using namespace winrt::Microsoft::Windows::AppNotifications;
using namespace winrt::Microsoft::Windows::AppNotifications::Builder;
using namespace winrt::Windows::ApplicationModel::Activation;
using namespace winrt::Windows::ApplicationModel::Background; // BackgroundTask APIs
using namespace winrt::Windows::Foundation;
@ -124,7 +125,9 @@ bool PostToastHelper(std::wstring const& tag, std::wstring const& group)
toast.Tag(tag.c_str());
toast.Group(group.c_str());
winrt::AppNotificationManager::Default().Show(toast);
auto builder{ winrt::AppNotificationBuilder().AddArgument(L"key", L"value").AddArgument(L"key", L"value").SetTag(tag.c_str()).SetGroup(group.c_str())};
winrt::AppNotificationManager::Default().Show(builder.BuildNotification());
if (toast.Id() == 0)
{
@ -170,11 +173,11 @@ int main()
winrt::event_token token = appNotificationManager.NotificationInvoked([](const auto&, winrt::AppNotificationActivatedEventArgs const& toastArgs)
{
std::wcout << L"AppNotification received foreground!\n";
winrt::hstring arguments{ toastArgs.Argument() };
std::wcout << arguments.c_str() << L"\n\n";
winrt::hstring argument{ toastArgs.Argument() };
std::wcout << argument.c_str() << L"\n\n";
winrt::IMap<winrt::hstring, winrt::hstring> userInput{ toastArgs.UserInput() };
for (auto pair : userInput)
winrt::IMap<winrt::hstring, winrt::hstring> arguments{ toastArgs.Arguments() };
for (auto pair : arguments)
{
std::wcout << "Key= " << pair.Key().c_str() << " " << "Value= " << pair.Value().c_str() << L"\n";
}
@ -200,11 +203,11 @@ int main()
{
std::wcout << L"Activated by AppNotification from background.\n";
winrt::AppNotificationActivatedEventArgs appNotificationArgs{ args.Data().as<winrt::AppNotificationActivatedEventArgs>() };
winrt::hstring arguments{ appNotificationArgs.Argument() };
std::wcout << arguments.c_str() << std::endl << std::endl;
winrt::hstring argument{ appNotificationArgs.Argument() };
std::wcout << argument.c_str() << std::endl << std::endl;
winrt::IMap<winrt::hstring, winrt::hstring> userInput = appNotificationArgs.UserInput();
for (auto pair : userInput)
winrt::IMap<winrt::hstring, winrt::hstring> arguments = appNotificationArgs.Arguments();
for (auto pair : arguments)
{
std::wcout << "Key= " << pair.Key().c_str() << " " << "Value= " << pair.Value().c_str() << L"\n";
}

Просмотреть файл

@ -17,3 +17,4 @@
#include <winrt/Microsoft.Windows.AppLifecycle.h>
#include <winrt/Microsoft.Windows.PushNotifications.h>
#include <winrt/Microsoft.Windows.AppNotifications.h>
#include <winrt/Microsoft.Windows.AppNotifications.Builder.h>

Просмотреть файл

@ -29,6 +29,7 @@ namespace winrt
const std::wstring c_localWindowsAppSDKFolder{ LR"(\Microsoft\WindowsAppSDK\)" };
const std::wstring c_pngExtension{ LR"(.png)" };
const std::wstring c_appUserModelId{ LR"(TaefTestAppId)" };
const std::wstring c_iconFilepath{ std::filesystem::current_path() / "icon1.ico" };
bool BackgroundActivationTest() // Activating application for background test.
{
@ -1327,6 +1328,122 @@ bool VerifyIconPathExists_Unpackaged()
return true;
}
bool VerifyRegisterWithNullDisplayNameFail_Unpackaged()
{
// Register is already called in main with an explicit appusermodelId
winrt::AppNotificationManager::Default().UnregisterAll();
try
{
winrt::AppNotificationManager::Default().Register(winrt::hstring{}, winrt::Uri{ c_iconFilepath });
}
catch (...)
{
return winrt::to_hresult() == E_INVALIDARG;
}
return false;
}
bool VerifyRegisterWithNullIconFail_Unpackaged()
{
// Register is already called in main with an explicit appusermodelId
winrt::AppNotificationManager::Default().UnregisterAll();
try
{
winrt::AppNotificationManager::Default().Register(L"AppNotificationApp", nullptr);
}
catch (...)
{
return winrt::to_hresult() == E_INVALIDARG;
}
return false;
}
bool VerifyRegisterWithNullDisplayNameAndNullIconFail_Unpackaged()
{
// Register is already called in main with an explicit appusermodelId
winrt::AppNotificationManager::Default().UnregisterAll();
try
{
winrt::AppNotificationManager::Default().Register(winrt::hstring{}, nullptr);
}
catch (...)
{
return winrt::to_hresult() == E_INVALIDARG;
}
return true;
}
bool VerifyShowToastWithCustomDisplayNameAndIcon_Unpackaged()
{
// Register is already called in main with an explicit appusermodelId
winrt::AppNotificationManager::Default().UnregisterAll();
try
{
winrt::AppNotificationManager::Default().Register(L"AppNotificationApp", winrt::Uri{ c_iconFilepath });
winrt::check_bool(VerifyShowToast_Unpackaged());
}
catch (...)
{
return false;
}
return true;
}
bool VerifyRegisterWithDisplayNameAndInvalidIconPathFail_Unpackaged()
{
// Register is already called in main with an explicit appusermodelId
winrt::AppNotificationManager::Default().UnregisterAll();
try
{
winrt::AppNotificationManager::Default().Register(L"AppNotificationApp", winrt::Uri{ LR"(C:\InvalidPath\)" });
}
catch (...)
{
return winrt::to_hresult() == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
return false;
}
bool VerifyRegisterWithEmptyDisplayNameFail_Unpackaged()
{
// Register is already called in main with an explicit appusermodelId
winrt::AppNotificationManager::Default().UnregisterAll();
try
{
// hstring treats L"" as assigning nullptr
winrt::AppNotificationManager::Default().Register(L"", winrt::Uri{ c_iconFilepath });
}
catch (...)
{
return winrt::to_hresult() == E_INVALIDARG;
}
return false;
}
bool VerifyRegisterWithAssetsFail()
{
// Register is already called in main with an explicit appusermodelId
winrt::AppNotificationManager::Default().UnregisterAll();
try
{
// API fails for Packaged Scenario
winrt::AppNotificationManager::Default().Register(L"AppNotificationApp", winrt::Uri{ LR"(C:\InvalidPath\)" });
}
catch (...)
{
return winrt::to_hresult() == E_ILLEGAL_METHOD_CALL;
}
return false;
}
std::map<std::string, bool(*)()> const& GetSwitchMapping()
{
static std::map<std::string, bool(*)()> switchMapping = {
@ -1385,6 +1502,14 @@ std::map<std::string, bool(*)()> const& GetSwitchMapping()
{ "VerifyToastProgressDataSequence0Fail", &VerifyToastProgressDataSequence0Fail },
{ "VerifyToastUpdateZeroSequenceFail_Unpackaged", &VerifyToastUpdateZeroSequenceFail_Unpackaged },
{ "VerifyIconPathExists_Unpackaged", &VerifyIconPathExists_Unpackaged},
{ "VerifyRegisterWithNullDisplayNameFail_Unpackaged", &VerifyRegisterWithNullDisplayNameFail_Unpackaged},
{ "VerifyRegisterWithNullIconFail_Unpackaged", &VerifyRegisterWithNullIconFail_Unpackaged},
{ "VerifyRegisterWithNullDisplayNameAndNullIconFail_Unpackaged", &VerifyRegisterWithNullDisplayNameAndNullIconFail_Unpackaged},
{ "VerifyShowToastWithCustomDisplayNameAndIcon_Unpackaged", &VerifyShowToastWithCustomDisplayNameAndIcon_Unpackaged},
{ "VerifyRegisterWithDisplayNameAndInvalidIconPathFail_Unpackaged", &VerifyRegisterWithDisplayNameAndInvalidIconPathFail_Unpackaged},
{ "VerifyRegisterWithEmptyDisplayNameFail_Unpackaged", &VerifyRegisterWithEmptyDisplayNameFail_Unpackaged},
{ "VerifyRegisterWithAssetsFail", &VerifyRegisterWithAssetsFail},
};
return switchMapping;

Просмотреть файл

@ -586,5 +586,40 @@ namespace Test::ToastNotifications
{
RunTestUnpackaged(L"VerifyIconPathExists_Unpackaged", testWaitTime());
}
TEST_METHOD(VerifyRegisterWithNullDisplayNameFail_Unpackaged)
{
RunTestUnpackaged(L"VerifyRegisterWithNullDisplayNameFail_Unpackaged", testWaitTime());
}
TEST_METHOD(VerifyRegisterWithNullIconFail_Unpackaged)
{
RunTestUnpackaged(L"VerifyRegisterWithNullIconFail_Unpackaged", testWaitTime());
}
TEST_METHOD(VerifyRegisterWithNullDisplayNameAndNullIconFail_Unpackaged)
{
RunTestUnpackaged(L"VerifyRegisterWithNullDisplayNameAndNullIconFail_Unpackaged", testWaitTime());
}
TEST_METHOD(VerifyShowToastWithCustomDisplayNameAndIcon_Unpackaged)
{
RunTestUnpackaged(L"VerifyShowToastWithCustomDisplayNameAndIcon_Unpackaged", testWaitTime());
}
TEST_METHOD(VerifyRegisterWithDisplayNameAndInvalidIconPathFail_Unpackaged)
{
RunTestUnpackaged(L"VerifyRegisterWithDisplayNameAndInvalidIconPathFail_Unpackaged", testWaitTime());
}
TEST_METHOD(VerifyRegisterWithEmptyDisplayNameFail_Unpackaged)
{
RunTestUnpackaged(L"VerifyRegisterWithEmptyDisplayNameFail_Unpackaged", testWaitTime());
}
TEST_METHOD(VerifyRegisterWithAssetsFail)
{
RunTest(L"VerifyRegisterWithAssetsFail", testWaitTime());
}
};
}