diff --git a/specs/AppNotifications/AppNotificationContentSpec/AppLogoOverrideImageExample.png b/specs/AppNotifications/AppNotificationContentSpec/AppLogoOverrideImageExample.png new file mode 100644 index 0000000000..65c0aeb26d Binary files /dev/null and b/specs/AppNotifications/AppNotificationContentSpec/AppLogoOverrideImageExample.png differ diff --git a/specs/AppNotifications/AppNotificationContentSpec/AppNotificationBuilder-spec.md b/specs/AppNotifications/AppNotificationContentSpec/AppNotificationBuilder-spec.md new file mode 100644 index 0000000000..3769e71334 --- /dev/null +++ b/specs/AppNotifications/AppNotificationContentSpec/AppNotificationBuilder-spec.md @@ -0,0 +1,1227 @@ +# App Notification Content Builder + +# Background + +App Notifications are UI popups that contain rich text, controls and images to display a message to +the user. With the Windows App SDK, developers can define an XML payload and display an +AppNotification using the AppNotificationManager::Show API, but defining these XML payloads can be +tedious when written by hand. + +To generate an AppNotification like this one: + +![App Notification With Avatar Image](AppNotificationWithAvatarImage.png) + +Developers have to write something like this: + +```c++ +int sequenceId {1234}; +std::wstring pathToImage {LR"(ms-appx://images/appLogo.png)"}; + +winrt::hstring xmlPayload{ + fmt::format(LR"( + + + + App Notification with Avatar Image + This is an example message using XML + + + + + + )" , + sequenceId, pathToImage, sequenceId)}; +auto appNotification{ winrt::AppNotification(xmlPayload) }; +winrt::AppNotificationManager::Default().Show(appNotification); +``` + +# Description + +To improve the AppNotification construction experience, the Windows App SDK is introducing +AppNotificationBuilder, a builder that constructs simple or rich App Notifications for the +developer. + +```c++ +AppNotificationBuilder() + .AddArgument(L"AppNotificationClick") + .AddArgument(L"sequence", winrt::to_hstring(sequenceId)) + .SetAppLogoOverride(winrt::Windows::Foundation::Uri(pathToImage), AppNotificationImageCrop::Circle) + .AddText(L"App Notification with Avatar Image") + .AddText(L"This is an example message") + .AddButton(AppNotificationButton(L"Open App") + .AddArgument(L"action", L"OpenAppButton") + .AddArgument(L"sequence", winrt::to_hstring(sequenceId))); +``` + +# API Components + +# AppNotificationBuilder + +The AppNotificationBuilder component sets up the xml for a ``. This is the wrapper content +that will include any component adding to the AppNotification UI. + +### WinAppSDK 1.2 `` Schema + +```xml + + + visual, audio?, actions? + +``` + +These attributes are abstracted away by the following AppNotificationBuilder component APIs +available in the Windows App SDK: + +- AppNotificationBuilder(); +- AddArgument(String key, String value) +- SetTimeStamp(Windows.Foundation.DateTime dateTime) +- SetScenario(AppNotificationScenario Scenario) + - AppNotificationScenario.Reminder + - AppNotificationScenario.Alarm + - AppNotificationScenario.IncomingCall + - AppNotificationScenario.Urgent + +useButtonStyle will only be set if AppNotificationButton::SetButtonStyle is used. + +You can append UI components through the AppNotificationBuilder component APIs: + +- AddText +- AddButton +- SetInlineImage +- SetAppLogoOverrideImage +- SetHeroImage +- SetAudioUri +- SetAudioEvent +- AddTextBox +- AddComboBox + +The main advantage as an API is to provide validation, type safety, and foremost intellisense. + +Below is an example usage: + +![AppNotification Example](AppNotificationExample.png) + +AppNotificationBuilder code: + +```cpp +AppNotificationBuilder() + .AddArgument(L"action", L"openThread") + .AddArgument(L"threadId", L"92187") + .SetTimeStamp(DateTime.now()) + .AddText(L"Jill Bender", AppNotificationTextProperties().SetMaxLines(1)) + .AddText(L"Checkout where we camped last weekend") + .SetAppLogoOverride(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/appLogo.png)"), AppNotificationImageCrop::Circle) + .SetHeroImage(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/heroImage.png)")) + .AddTextBox(L"textBox", L"reply") + .AddButton(AppNotificationButton() + .AddArgument(L"action", L"reply") + .AddArgument(L"threadId", L"92187") + .SetIcon(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/Icon.png)")) + .SetInputId(L"textBox")) + .BuildNotification(); +``` + +XML payload: + +```xml + + + + Jill Bender + Check out where we camped last weekend! It was incredible, wish you could have come on the backpacking trip! + + + + + + + + + +``` + +## Limitations + +- AppNotificationScenario.Urgent is only supported for to builds 19041 (20H1) and above. Using + this attribute on lower builds will not prevent the AppNotification from being constructed, but + developers can use AppNotificationBuilder.IsUrgentScenarioSupported to check if the feature is + available at runtime. + +# Text + +The Text component sets up the xml for a `` element. Developers can define the content, +language, and placement of the text on the AppNotification. + +**WinAppSDK 1.2 \ Schema**: + +```xml + +``` + +These attributes are abstracted with the following AppNotificationTextProperties component APIs +available in the Windows App SDK: + +- SetLanguage(String language) +- SetHintMaxLines(Int32) +- SetIncomingCallAlignment() + +Below are some example usages: + +![Text Example](TextExample.png) + +AppNotificationBuilder Code: + +```cpp +AppNotificationBuilder() + .AddText(L"Content") + .SetAttributionText(L"Attribution Text") + .BuildNotification(); +``` + +XML payload: + +```xml + + + + Content + Attribution Text + + + +``` + +Developers can use SetIncomingCallAlignment() to center the text like an incoming call. This feature +will be ignored unless the AppNotification scenario is set to IncomingCall using +AppNotificationBuilder::SetScenario(enum AppNotificationScenario). + +![IncomingCall Simple Example](IncomingCallSimpleExample.png) + +AppNotificationBuilder code: + +```cpp +AppNotificationBuilder() + .SetScenario(AppNotificationScenario::IncomingCall) + .AddText(L"Incoming Call", AppNotificationTextProperties() + .SetIncomingCallAlignment()) + .AddText(L"Andrew Barnes", AppNotificationTextProperties() + .SetIncomingCallAlignment()) + .SetInlineImage(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/inlineImage.png)"), AppNotificationImageCrop::Circle) + .AddButton(AppNotificationButton() + .SetIcon(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/icon.png)")) + .SetButtonStyle(AppNotificationButtonStyle::Success) + .SetToolTip(L"Answer video call")) + .BuildNotification(); +``` + +XML payload: + +```xml + + + + Incoming Call + Andrew Barnes + + + + + + + +``` + +Notice that the text is inserted into the xml the order that it was provided in the builder. + +# AppNotificationButton + +The AppNotificationButton component API sets up the xml for the `` element. +AppNotificationButtons are user-clickable components meant to start an action from the app. + +**WinAppSDK 1.2 \ Schema**: + +```xml + +``` + +These attributes are abstracted with the following AppNotificationButton component APIs available in +the Windows App SDK: + +- AppNotificationButton() +- AppNotificationButton(String content) +- SetIcon(Windows.Foundation.Uri iconUri) +- SetToolTip(String toolTip) +- SetContextMenuPlacement() +- SetInputId(String inputId) + +Below are some example usages: + +![Button Example](ButtonExample.png) + +AppNotificationBuilder code: + +```cpp +AppNotificationBuilder() + .AddText(L"Content") + .AddTextBox(L"textBox", L"Reply") + .AddButton(AppNotificationButton(L"Send") + .AddArgument(L"action", L"textReply") + .SetIcon(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/icon.png)")) + .SetInputId(L"textBox")) + .BuildNotification(); +``` + +XML payload: + +```xml + + + + Content + + + + + + + + +``` + +Developers can change the button style of the button using +SetButtonStyle(AppNotificationButtonStyle). The two button styles are +AppNotificationButtonStyle.Success and AppNotificationButtonStyle.Critical. + +![Button Style Example](IncomingCallExample.png) + +AppNotificationBuilder code: + +```cpp +AppNotificationBuilder() + .SetScenario(AppNotificationScenario::IncomingCall) + .AddText(L"Incoming Call", AppNotificationTextProperties() + .SetIncomingCallAlignment()) + .AddText(L"Andrew Barnes", AppNotificationTextProperties() + .SetIncomingCallAlignment()) + .SetInlineImage(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/inlineImage.png)"), AppNotificationImageCrop::Circle) + .AddButton(AppNotificationButton() + .AddArgument(L"videoCall", L"938465") + .SetIcon(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/videoCall.png)")) + .SetButtonStyle(AppNotificationButtonStyle::Success) + .SetToolTip(L"Answer video call")) + .AddButton(AppNotificationButton() + .AddArgument(L"voiceCall", L"938465") + .SetIcon(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/voiceCall.png)")) + .SetButtonStyle(AppNotificationButtonStyle::Success) + .SetToolTip(L"Answer voice call")) + .AddButton(AppNotificationButton() + .AddArgument(L"declineCall", L"938465") + .SetIcon(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/declineCall.png)")) + .SetButtonStyle(AppNotificationButtonStyle::Critical) + .SetToolTip(L"Decline all")) + .BuildNotification(); +``` + +XML payload: + +```xml + + + + Incoming Call + Andrew Barnes + + + + + + + + + + +``` + +Notice that the AppNotificationButtons are inserted into the xml the order that it was provided in +the builder. + +The ToolTip is useful for buttons with icons and no content. Users can hover over the button with +the cursor and a text will display describing what the button does. + +![Button ToolTip Example](ButtonToolTipExample.png) + +AppNotificationBuilder code: + +```cpp +AppNotificationBuilder() + .AddText(L"Content") + .AddTextBox(L"textBox", L"Reply") + .AddButton(AppNotificationButton() + .AddArgument(L"action", L"textReply") + .SetInputId(L"textBox") + .SetToolTip(L"Send") + .SetIcon(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/icon.png)"))) + .BuildNotification(); +``` + +XML payload: + +```xml + + + + Content + + + + + + + + +``` + +The context menu is a popup UI that appears when the user right clicks on the AppNotification. The +default options are to turn off receiving notifications for the application and to launch the +notification settings page. Using SetContextMenuPlacement() will add an option to the context menu. +The behavior is the same as other buttons and when activated returns the arguments to the app. + +![Button ContextMenu Example](ButtonContextMenuExample.png) + +AppNotificationBuilder code: + +```cpp +AppNotificationBuilder() + .AddText(L"Content") + .AddTextBox(L"textBox", L"Reply") + .AddButton(AppNotificationButton(L"Modify app settings") + .AddArgument(L"action", L"textReply") + .SetContextMenuPlacement()) + .BuildNotification(); +``` + +XML payload: + +```xml + + + + Content + + + + + + + + +``` + +## Limitations + +- hint-toolTip and hint-buttonStyle are only supported for builds 19041 (20H1) and above. Using + these attributes on lower builds will not prevent the AppNotification from being constructed, + but developers can use AppNotificationButton.IsButtonStyleSupported and + AppNotificationButton.IsToolTipSupported to check if the feature is available at runtime. + +# Image + +The Image component API sets up the xml for the `` element. Images are visual elements that +are used to enhance an AppNotification. + +The image source can be specified using one of these protocol handlers: + +- http:// or https:// (A web-based image) (unavailable for unpackaged application on build 22000) +- ms-appx:/// (An image included in the app package) (only for packaged applications) +- ms-appdata:///local/ (An image saved to local storage) (only for packaged applications) +- file:/// (A local image) (only for unpackaged) + +**WinAppSDK 1.2 \ Schema**: + +```xml + +``` + +Images can be displayed in three different ways: + +## Inline + +A full-width inline-image that appears when you expand the AppNotification. + +![Inline Image Example](InlineImageExample.png) + +AppNotificationBuilder code: + +```cpp +AppNotificationBuilder() + .AddText(L"Below is an inline image") + .SetInlineImage(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/inlineImage.png)")) + .BuildNotification(); +``` + +XML payload: + +```xml + + + + Below is an inline image + + + + +``` + +## AppLogoOverride + +The image replaces your app's logo in the AppNotification. + +![AppLogoOverride Image Example](AppLogoOverrideImageExample.png) + +AppNotificationBuilder code: + +```cpp +AppNotificationBuilder() + .AddText(L"To the left is an AppLogoOverride") + .SetAppLogoOverride(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/appLogo.png)")) + .BuildNotification(); +``` + +XML payload: + +```xml + + + + To the left is an AppLogoOverride + + + + +``` + +## Hero + +Prominently displays image within the AppNotification banner and while inside Notification Center. + +![Hero Image Example](HeroImageExample.png) + +AppNotificationBuilder code: + +```cpp +AppNotificationBuilder() + .AddText(L"Above is a Hero image") + .SetHeroImage(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/heroImage.png)")) + .BuildNotification(); +``` + +XML payload: + +```xml + + + + Above is a Hero image + + + + +``` + +## Cropped AppLogoOverride + +For both Inline and AppLogoOverride, developers can set how the image will be cropped. + +![Cropped AppLogoOverride Image Example](CroppedAppLogoOverrideExample.png) + +AppNotificationBuilder code: + +```cpp +AppNotificationBuilder() + .AddText(L"To the left is a cropped AppLogoOverride") + .SetAppLogoOverride(winrt::Windows::Foundation::Uri(LR"(ms-appx://images/appLogo.png)"), AppNotificationImageCrop::Circle); +``` + +XML payload: + +```xml + + + + To the left is a cropped AppLogoOverride + + + + +``` + +Supported image file types include: + +- .png +- .jpg +- .svg + +# Audio + +The Audio component allows the developer to define a custom audio to play when an AppNotification is +displayed. The audio file can be defined by string value pointing to an app asset or one of the +[ms-winsoundevents](https://docs.microsoft.com/uwp/schemas/tiles/toastschema/element-audio). + +**WinAppSDK 1.2 `